- 在线时间
- 63 小时
- 最后登录
- 2019-5-3
- 注册时间
- 2004-5-10
- 听众数
- 442
- 收听数
- 0
- 能力
- -250 分
- 体力
- 10122 点
- 威望
- -12 点
- 阅读权限
- 150
- 积分
- -586
- 相册
- 6
- 日志
- 10
- 记录
- 10
- 帖子
- 2003
- 主题
- 1253
- 精华
- 36
- 分享
- 8
- 好友
- 1292

复兴中华数学头子
TA的每日心情 | 开心 2011-9-26 17:31 |
---|
签到天数: 3 天 [LV.2]偶尔看看I
- 自我介绍
- 数学中国网站(www.madio.cn)是目前中国最大的数学建模交流社区
群组: 越狱吧 群组: 湖南工业大学数学建模同盟会 群组: 四川农业大学数学建模协会 群组: 重庆交通大学数学建模协会 群组: 中国矿业大学数学建模协会 |
3#
发表于 2004-9-27 14:33
|只看该作者
|
|邮箱已经成功绑定
UNUSUAL_DEV(07c4, a400, 0x0000, 0xffff,
6 P, _6 l5 C/ j' D4 W- |. \" USB ", " Mass Storage ", 4 L* l! Q a3 {+ z
US_SC_SCSI, US_PR_BULK, NULL, - k3 y& P! S( f6 `9 U; u
US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE ) $ T; z- B2 H' E" K# }
) |8 a- }; J% z6 F注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。 ( l @8 ^+ D% [4 {
最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 p% b0 D* ]' ^3 w" D5 o
键盘飞梭支持
) D8 M3 s5 c& j A* @目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 " W, s; ]2 h# E6 K) L
下面是具体看到的信息
4 K% q9 j+ h2 a( a) { P0 p) b
5 R- x5 m9 c" x+ [T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
# b* Y. T" T+ T! [: ?. u9 [B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0 3 t# K$ U( Y/ {' w
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
" n, L- t& b* y1 p" s, iP: Vendor=0000 ProdID=0000 Rev= 0.00
( c' x& j4 W B7 V1 p- dS: Product=USB UHCI Root Hub
0 k: J- y; m" z6 w: s4 @S: SerialNumber=d800
- T+ k7 Q/ R+ U! b5 ZC:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA ! O+ W& L: A7 }1 u g( }( f
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub * ]7 o$ j6 q/ d6 m, J2 r
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
) h- B' ^0 P% ^/ h7 `. T8 O6 m& \T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3
! r; [# S. d7 n; h( yD: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 $ { U4 J! z# t. Y
P: Vendor=07e4 ProdID=9473 Rev= 0.02
F; R% K, [5 W9 Y0 ES: Manufacturer=ALCOR
9 x- `3 G- R3 mS: Product=Movado USB Keyboard
) ~1 ?' ]( y8 g$ z* M, t+ T! q9 `C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA 4 C9 n* ?$ w& \& S% R5 B, M
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
5 w# Q2 m1 Z$ `" R p) L# s n EE: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms 3 o* l; C" ~( m; J- Q
找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照drivers/usb/usbkbd..c代码进行一些改动就可以了。因为没能拿到相应的硬件USB协议,我无从知道飞梭在按下时通讯协议众到底发什么,我只能把它的信息打出来进行分析。幸好,它比较简单,在下面代码的usb_kbd_irq函数中if(kbd->new[0] == (char)0x01)和if(((kbd->new[1]>>4)&0x0f)!=0x7)就是判断飞梭左旋。usb_kbd_irq函数就是键盘中断响应函数。他的挂接,就是在usb_kbd_probe函数中
1 F. L& \! ~& F
7 E, L% p7 g9 \ S9 dFILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 4 u, W/ ^1 |/ P" U' y
usb_kbd_irq, kbd, endpoint->bInterval);
# `! N$ v/ {9 H- \' {% o6 T/ i+ h# \) n
一句中实现。
; \8 r# L q% M+ S从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。 ; e7 N m, L* @ _' F
在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。
) |! p# a4 f {6 B程序见附录1:键盘飞梭驱动。 ) m- x- ]& E( B7 t
使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。
' R1 u9 ]5 H- b2 R9 p/ _2 ]参考资料
. k& a4 ` i" C+ W) T' f# e( o1. 《LINUX设备驱动程序》
4 O3 Z& G* ^. P3 I2 v! C3 X0 W& Y, [ALESSANDRO RUBINI著 / ^; b/ G$ P( V; G- K5 _* x, b" P( W
LISOLEG 译 " G- c5 f2 E7 ~% S
2. 《Linux系统分析与高级编程技术》 ; `% w- F0 l% A9 E
周巍松 编著 , A1 R5 U. J" h, ^ A, d
3. Linux Kernel-2.4.20源码和文档说明 * H. y0 W9 q' Q" w/ S
附录1:键盘飞梭驱动
. | @- v0 j1 n3 \% s4 t. g" x
- Q& Y/ l6 w2 k$ @& z: `#include <linux/kernel.h> % J/ l' P1 }* i' i, u- k0 E
#include <linux/slab.h>
" b9 }0 ~% J2 R8 f#include <linux/module.h>
: F& w6 L3 Y% f4 s- C#include <linux/input.h>
9 T0 g" ~% f2 h2 F; `#include <linux/init.h>
6 N" b4 N' \) E! L' v1 n#include <linux/usb.h> # i$ K3 y+ N: K6 i" T1 O \
#include <linux/kbd_ll.h>
/ M& J% @8 V J& j2 [
W% b. n- g: ?, {/* ! ^# [( j; {, W
* Version Information
5 y D4 p, ^) h2 ` E */ ) e* q+ a: H4 L5 a
#define DRIVER_VERSION ""
& j! f8 p- S: ?- E# B# e#define DRIVER_AUTHOR "TGE HOTKEY "
; ~3 ~+ V0 V1 u5 I#define DRIVER_DESC "USB HID Tge hotkey driver" - h5 s( B# y5 @4 G
1 `( N: z" {5 F% s#define USB_HOTKEY_VENDOR_ID 0x07e4 + U, c Y% D- g' Y) @( P/ A5 k
#define USB_HOTKEY_PRODUCT_ID 0x9473 3 ^- i1 Q4 I( Z$ w6 `
//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值 # V" h3 W* l) l$ S& {# n2 z N
" x8 e. O- Z. l; lMODULE_AUTHOR( DRIVER_AUTHOR );
% d; @: e: {9 T, s" V" `4 r8 Z# |MODULE_DESCRIPTION( DRIVER_DESC ); 0 n" ^6 I; B6 @
) F3 i# Q7 y9 z) q& O
struct usb_kbd { ; } G' B7 q. r Z4 o2 f, w
struct input_dev dev;
1 e5 W) R7 w2 Ostruct usb_device *usbdev; / D c# w! v. v! e' K8 `
unsigned char new[8];
8 K! v; Z- D0 S' e9 O/ Y, yunsigned char old[8];
" j( c2 O# t, Jstruct urb irq, led;
4 m5 v& {4 U8 ~& d// devrequest dr; . E1 Q" f; }/ @/ j) q
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化 6 Z6 W+ B% ^: @
struct usb_ctrlrequest dr; + O0 C8 u5 ^- _2 ]
unsigned char leds, newleds;
/ L' a' ?# x: k0 S# Wchar name[128]; . [/ {$ K1 L' ^/ h/ s/ [
int open; 0 j/ N0 B# h+ I& a8 `# b6 @$ V1 f
}; 4 [, `: ^+ V; T) M7 a+ S
//此结构来自内核中drivers/usb/usbkbd..c
2 I5 O; H- [/ U, D5 n) c I' }6 u) C& O `- |
static void usb_kbd_irq(struct urb *urb)
" x9 v. e% }2 F: V{ 1 P, [$ I; ]7 }
struct usb_kbd *kbd = urb->context;
1 v+ _6 G6 t' j4 c9 t! w- D int *new; ) r2 l% Y1 J2 y! | h& t
new = (int *) kbd->new; 3 s% T8 S% n* x- T1 Q7 U8 t
5 l9 h# \' Y7 z: jif(kbd->new[0] == (char)0x01) % B3 t" R+ y& H; V* `- C
{ # r# v+ V% G: r; ^% U5 q, F* z
if(((kbd->new[1]>>4)&0x0f)!=0x7) ) `$ R' n# r0 h5 k' V* {" s
{ " z3 U5 T% B% x' i1 a, {
handle_scancode(0xe0,1); & R; e9 b* y6 k% r* G/ G
handle_scancode(0x4b,1); 6 H9 W" @" v' k' R
handle_scancode(0xe0,0); : w+ f' c+ O e2 V+ D
handle_scancode(0x4b,0);
3 _3 l7 o! N3 y& S} 5 u" J1 @4 y9 b( r- a. Q# D$ C" |- \
else ( {* B; E/ q" l+ ?
{ ( I$ |7 o& R1 G5 x0 A" Z
handle_scancode(0xe0,1); 7 l1 V0 b! E) U' A9 D* H+ }
handle_scancode(0x4d,1); 0 d2 d5 O5 J3 y
handle_scancode(0xe0,0);
5 o: I' [8 w5 r) ]9 F' X- ] handle_scancode(0x4d,0);
" E2 M' P, |! C% |' Q* H}
. [- B) R1 `" g}
9 E! x. t# {) @; t
; ~0 a! t- C; Z6 x* _ P% s& g- r- z# I/ A
printk("new=%x %x %x %x %x %x %x %x",
. m3 O6 ]& I; m1 _kbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], # v c, t6 p! p
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]); * [: Y- o; h9 X- H! r
/ j6 t# R& y5 S1 W% Y- Z( t
}
8 i/ F: l7 O, ?# L' o8 t/ e6 V. j8 g1 e( f- z7 u
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
' G" O4 {# B2 ]4 ]1 W const struct usb_device_id *id) 0 H* U: d# C# p0 u3 J6 F
{
5 X8 V* z6 I) u; {9 wstruct usb_interface *iface; 8 ]6 e7 [ P& V {/ e! h1 k! O
struct usb_interface_descriptor *interface; " u. {2 t, Y* g9 H1 i6 d" K
struct usb_endpoint_descriptor *endpoint; & f5 M( V/ p9 y# W: o8 L
struct usb_kbd *kbd;
3 ~: d f- V; W int pipe, maxp; Z) p# b! H* y; I. a) ^: X
4 z( U8 H2 z+ S8 ~
iface = &dev->actconfig->interface[ifnum]; & i, ^/ s% | b/ Z: \
interface = &iface->altsetting[iface->act_altsetting]; 9 F: }4 c+ O! Z: {. l
( `: i+ ^$ N6 ^( b! h
if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || 8 h% K a7 i4 C; {; h' d
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) ||
" b& D6 C& H, ]. {(ifnum != 1))
6 h/ V+ n0 J- Z4 u; }% t. M{ - S8 B! _2 j, ]3 q' K8 f
return NULL;
- ^" F. `0 A8 t6 v U/ p4 w} ! ]: m: U, c8 U$ q4 h2 Q$ t5 Z' D. r
if (dev->actconfig->bNumInterfaces != 2)
' `8 m; j- z7 n) i2 Q3 ~% a W{
8 }: }& A& d' c4 }( `return NULL; . U( F8 h* h) Q5 o3 l
}
" M, K/ R) \& R9 r9 ~* R3 h! H% {+ u
if (interface->bNumEndpoints != 1) return NULL;
$ J3 q2 D8 x' G1 L" {
$ R, q! @" ~- N& t4 Z; R endpoint = interface->endpoint + 0;
u/ c; u; c: d+ g5 A
0 m+ c) ^9 ?! {; K/ j+ R0 d pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
6 Y. t; }3 o5 f3 E0 t maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); & O9 J+ V6 m7 i. v
9 _# @. C9 M# V9 H; O usb_set_protocol(dev, interface->bInterfaceNumber, 0); ( d! f' K, F X6 L; ?3 h
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
& L1 c1 E$ @6 T) [7 t: ^& q9 Z' H% w2 W z( G
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
{3 w) G0 u* h$ O5 a% R6 Hdev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp);
5 }; w7 q1 W$ h+ j. A. m% V8 Y' e; X* z
if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
$ O6 K. b& U6 x8 x* ?% i% l* c- G, O7 C memset(kbd, 0, sizeof(struct usb_kbd)); + g% }5 N( [3 E% C+ [% f; s9 {" u
# ]( b' ]: J% P% i, N" e( c) P
kbd->usbdev = dev;
6 w( e: c2 c$ x/ |0 w$ l9 v' c' |% N1 e9 X, H
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, / r* v9 |" |5 j, W" y d9 s. V
usb_kbd_irq, kbd, endpoint->bInterval); 2 C1 ?9 \* N! s0 c6 }" O8 b
0 R, a- h# m$ C- a# Q" M, Q! O( ^kbd->irq.dev = kbd->usbdev;
- g: [5 l: F j8 E
8 D- E! e7 a' a2 bif (dev->descriptor.iManufacturer) 3 ]" m' g; k7 u. g9 Y& n- A4 w
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63);
7 L. B1 ]' z0 ^2 F1 R% `, y1 {0 E8 n5 P3 G3 p+ N
if (usb_submit_urb(&kbd->irq)) {
1 P/ u7 j# c8 v, H5 t, k$ M* D kfree(kbd); : ]3 X' x: q! K3 V6 g
return NULL;
. m+ O7 E3 k, O& ^# h. G }
9 g) y2 g8 }" b2 c; z
/ N% M: g) ]/ Cprintk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", % B4 _. Z* t9 j
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); + k8 _) B, [( T8 {
2 X4 K" l1 o8 M) M
return kbd;
, Q" C- S; D; [} " `8 j5 L4 D2 J6 i9 c: R" j
/ p/ O( j, @( B" L6 n% R
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
9 S& L& ^% ~7 v* d4 w( B{
- N) F/ ]1 K2 a# H8 p1 Pstruct usb_kbd *kbd = ptr;
+ {# W9 n9 |% Z7 ?5 R usb_unlink_urb(&kbd->irq); 9 J5 o+ Y+ B' u: ~/ m
kfree(kbd); / j! K. Q) @! {2 o
" u! x: a2 H" ?
} ) j/ T* a: x' [ i. ^
5 s' [# e# @# [- P5 Gstatic struct usb_device_id usb_kbd_id_table [] = { + E) N1 O% y6 S& o! l+ Q& O
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) },
8 B$ y S2 Y: A* P, f{ } /* Terminating entry */ 6 t6 d/ n# s: b' Q9 F E
};
9 Q0 `0 @* ~7 Z2 r5 b+ V6 r8 G2 Q* E
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
7 Z2 G" y) Q5 ~$ I9 A$ u! x3 \, Q, i8 }. ?* P1 e
static struct usb_driver usb_kbd_driver = { 5 }' c4 U+ J* e) m& y0 M) o
name: "Hotkey",
+ G% l. h+ M& D# V Yprobe: usb_kbd_probe, % B, D; }2 c3 |- N0 x; j
disconnect: usb_kbd_disconnect, g$ }6 m) {8 p8 w: t/ h$ e
id_table: usb_kbd_id_table, " W# n' G: K, V, i. @7 n3 U# h
NULL,
; W- l3 q" d: h};
/ Y5 n4 }- P6 n+ _: [3 d' S- [- l: x
static int __init usb_kbd_init(void)
! D* s- W" D0 x# F r{ 2 ~+ S& t, C# u v) T, O6 u o: M
usb_register(&usb_kbd_driver); - Y! S' x& B5 v) I. k
info(DRIVER_VERSION ":" DRIVER_DESC);
( |+ r E0 A5 U4 y; H+ U" L& ~return 0;
/ M5 C1 }- _8 B, n) }4 e}
6 ^3 d0 L/ s6 V/ d$ M4 M' B
! o6 _8 {% m/ Astatic void __exit usb_kbd_exit(void)
, }: i# ^ F. H4 B! f" X{ / W$ A r# S' }
usb_deregister(&usb_kbd_driver);
5 K: P/ M- i1 b! F& Y5 @6 I} 3 J. k6 w9 k/ K6 r1 X, y
' j# c% m6 s9 ^: q: b p
module_init(usb_kbd_init); 1 ]! ?8 V3 U+ y; d% `- Y4 p
module_exit(usb_kbd_exit); |
|