- 在线时间
- 63 小时
- 最后登录
- 2019-5-3
- 注册时间
- 2004-5-10
- 听众数
- 442
- 收听数
- 0
- 能力
- -250 分
- 体力
- 10122 点
- 威望
- -12 点
- 阅读权限
- 150
- 积分
- -586
- 相册
- 6
- 日志
- 10
- 记录
- 10
- 帖子
- 2003
- 主题
- 1253
- 精华
- 43
- 分享
- 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,
7 V: z5 O( A7 r0 q4 q2 h" USB ", " Mass Storage ", % h6 V6 N0 l3 J8 t) e2 o5 V
US_SC_SCSI, US_PR_BULK, NULL, 8 C# X+ }, g4 A; n# w7 l. Y& \) L
US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE )
0 Z: G6 f5 p! f
; z! z6 I- o0 C1 R# h$ p注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。 0 {4 l: P; v. Z, C S
最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。
: F$ T+ o' ^7 g' X- i$ l键盘飞梭支持 7 p4 B$ G/ @8 |, O% x5 [2 i* f, U
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 ) R* s3 u0 i- L3 l0 n
下面是具体看到的信息 - h: ]# ~( _4 B4 X
, p/ \; u: {( k4 V: _ ZT: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
2 c0 P+ V. e) q7 sB: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0 6 w$ T$ m, G! D9 T: S' B6 e8 v& u6 e+ `
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 & H, [' [ }, ?+ Q8 |
P: Vendor=0000 ProdID=0000 Rev= 0.00 ' p" z7 g5 b; w
S: Product=USB UHCI Root Hub ) @: J$ `; M; E7 ]5 w5 y. T
S: SerialNumber=d800
. H8 G0 e/ G4 m/ }5 HC:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA $ _* o) N& \" o$ D
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
) E! ~& \9 E/ i/ m" fE: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms 3 m' k3 c' m* A& m' e: V1 d* K
T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3
( Q8 l9 a0 P. k, |" {, CD: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 " @; |, ~1 B$ I' W2 B% I( `
P: Vendor=07e4 ProdID=9473 Rev= 0.02 * ^3 V; Q! e8 \' T9 D/ @; d
S: Manufacturer=ALCOR
0 ^# k( v u* dS: Product=Movado USB Keyboard 5 ?% o4 n7 D/ Q3 q1 \
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
* D$ l+ ?' j7 U8 nI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub + K5 \$ `5 a# P( `1 F b9 ^
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
' @4 ~4 D$ y: s. c1 v找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中
3 ?2 P! o! Z& Z
# F) g# J f" w& b9 @% C) X2 {FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
; [7 F3 B: X' S& t% u( Nusb_kbd_irq, kbd, endpoint->bInterval);
9 A$ W& M/ t9 ^. W
8 k) k4 C6 `" r% ?' v, D, f, ~" Q d一句中实现。
# e; l3 \& {2 _; b从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。
' s* ]& w% I& d5 s1 P0 Y% G在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 6 ?/ y* J; \" s/ i) S
程序见附录1:键盘飞梭驱动。
% K# l# |2 J. c- w使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。
+ a+ M5 g- I( J* h, X0 D J) {参考资料
1 {# x T: A3 f* W1 j) u1. 《LINUX设备驱动程序》
3 z5 i( ^5 y: u& D' ZALESSANDRO RUBINI著
! u) V" h6 g2 }& a& H9 m4 N+ ~5 pLISOLEG 译
1 B. _9 y5 Z4 f/ D0 m! L2. 《Linux系统分析与高级编程技术》
( {: R4 i8 k$ K9 K& |6 `& y周巍松 编著
0 j. ~( R3 w1 H+ Q' }6 i1 ?3. Linux Kernel-2.4.20源码和文档说明 $ B' K, d* X. J, e. e/ C3 {# r: G4 K
附录1:键盘飞梭驱动 1 Y ]: I& F2 N. R
* P4 j, `- h" |: ]5 P7 I4 ]6 @
#include <linux/kernel.h>
0 r+ ~( _9 K5 D9 b& U#include <linux/slab.h>
8 z) q9 a+ {; {( A, O1 k: n4 d% O: v#include <linux/module.h>
# N) _7 O. ]2 S" ]' J7 M#include <linux/input.h> , n' w6 s3 |! ?2 v9 p
#include <linux/init.h> 1 B. L1 z0 T4 m. j: U* e# n
#include <linux/usb.h>
5 \3 w( s- O9 Y- a+ [/ a1 M w3 u* ?#include <linux/kbd_ll.h>
8 R3 k4 s. B; Y% m) N0 C% e) |( m1 ?8 \: W! m) W% ~
/*
) z; _ J6 f# s# F3 p$ @2 |9 ^, m5 K * Version Information
# a/ M. l/ n: A; [' z */ # s3 _; z! ~0 E* I
#define DRIVER_VERSION "" * @4 l: S4 X. G
#define DRIVER_AUTHOR "TGE HOTKEY " % r4 `5 L- w: h; n: g6 a/ _% w
#define DRIVER_DESC "USB HID Tge hotkey driver"
7 \/ R* P% d7 Y7 D7 O7 B9 }) X
+ N. \- E& {* \3 e4 c( n: P' @4 F#define USB_HOTKEY_VENDOR_ID 0x07e4 . d/ ?, l+ y! ]) ~. O* q
#define USB_HOTKEY_PRODUCT_ID 0x9473
, ]. P# u4 b0 L. P3 O) E//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值 3 |& B- x! I' F( C( `
5 \) [6 E9 Q. v2 ]. b4 k
MODULE_AUTHOR( DRIVER_AUTHOR ); 8 z- B) o. e- ]0 w: Y
MODULE_DESCRIPTION( DRIVER_DESC );
- p9 v& |6 J2 R8 b Q6 B
7 g- G& g O a& O+ Ystruct usb_kbd { . q3 i! U( s- I8 F5 C J" f7 h
struct input_dev dev;
9 m/ y5 K4 P+ R) zstruct usb_device *usbdev; 9 l4 K; l8 R0 ]/ w2 W8 X
unsigned char new[8]; , u4 Z e m! P6 B
unsigned char old[8]; ; m' z# L2 k9 U3 R: `
struct urb irq, led; ( n2 g- E5 f2 m0 w$ B2 _
// devrequest dr; 2 h- m+ V% B# l' B! @9 Q
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
; F& z% s9 t" m; Y struct usb_ctrlrequest dr;
* D' u5 ]& V% w; Vunsigned char leds, newleds;
Y2 T) y6 w* G1 hchar name[128];
$ r) z m) V- F6 f4 y8 Sint open; ( |* E4 K- C4 c
};
- }: a" e3 G, b" e- T& W//此结构来自内核中drivers/usb/usbkbd..c + m4 [" k6 {3 ~5 n5 i3 M
( W2 k% D) i# T2 Tstatic void usb_kbd_irq(struct urb *urb) / X; f$ d$ T3 x& r
{ . s; }4 C+ W$ B! I6 r% M
struct usb_kbd *kbd = urb->context;
! M% p- x! }& I2 O$ C int *new;
) z. B, h! ~, V* [9 z* ~ new = (int *) kbd->new;
$ x+ V8 L+ \! _8 u0 ]$ w
6 e" W3 M% g( Pif(kbd->new[0] == (char)0x01) 8 \7 F' V. ?# g. \5 @) Z
{ 2 I0 ~% P3 v# N i; r
if(((kbd->new[1]>>4)&0x0f)!=0x7) ) P3 w9 c* j/ ^ Y
{ & m& u4 `* D! \3 I0 M& V
handle_scancode(0xe0,1);
) Y; P/ x$ b3 M1 i- z4 {handle_scancode(0x4b,1);
1 Q5 S, o2 U* `: } handle_scancode(0xe0,0);
" R; E( `( a/ G# G4 V2 Y handle_scancode(0x4b,0);
& T# {& V& R% }( C1 q}
3 ^0 q o* f( c: z7 D2 c; nelse
' S, q8 @" u; ^: }{
: Y" [( R1 w7 X) K* i' s. Chandle_scancode(0xe0,1);
) U- z, X ]2 Y. E% d handle_scancode(0x4d,1); 7 [% {7 n' f0 m5 d3 `
handle_scancode(0xe0,0);
* j0 p" D3 L+ B& s; U* ?' I% E/ D0 B handle_scancode(0x4d,0);
5 I0 _, G' b4 B& t' c3 W! p}
- I# M, X( t# B! `" p e3 R}
7 P2 Y" v5 `, p( P# J
1 P$ _) `& y( T, C$ S) t+ ]5 r ?3 J: G: O; C& e
printk("new=%x %x %x %x %x %x %x %x",
* v' X! W* E8 C3 B9 ]8 f* `kbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3],
# o6 _7 H& q" _- H9 @ p: M6 gkbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
% d; |7 l5 P& \6 z, h: B
, ^0 O8 W e" G6 B2 B}
+ J8 V: c1 W- n* E: a/ V7 J1 }9 b+ N; ~1 c" s$ v) n" D6 D# W
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
7 ?* J8 [ i4 A$ U; N5 S: q const struct usb_device_id *id)
# O) r! Y! K1 S7 s{ W. _% }6 D& v- J" B# I2 a
struct usb_interface *iface; 6 n5 G# q; Q& `0 P" |# _! L, |
struct usb_interface_descriptor *interface; 4 f+ b- e' `/ L8 y
struct usb_endpoint_descriptor *endpoint; " O1 K! ]5 k7 S) v
struct usb_kbd *kbd; 9 i3 p/ P. b0 R4 e
int pipe, maxp; . \% i: b0 W( k1 X0 @
1 n8 a. K4 I. d+ {iface = &dev->actconfig->interface[ifnum]; c4 l0 N( C* s6 ]! V& y1 Q
interface = &iface->altsetting[iface->act_altsetting];
3 b- i/ E* K$ Z6 @ K
- @4 m6 B) R0 @( H4 yif ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || * c# Q4 ^) ?9 ~* V
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || 3 M# {+ A% d$ i& V9 {+ p
(ifnum != 1))
7 O1 r( Y: `6 O{ ) i! N$ F4 ^2 B' @& h* P7 w
return NULL;
/ t* k6 i s! n' y$ p5 _2 s} + M/ [( V4 H O/ g
if (dev->actconfig->bNumInterfaces != 2)
- q" o' N- \9 L, Q{
7 @% d( C* m2 L. [return NULL; 7 i* I' ]( h3 c$ ~
}
( c T; C. u9 K, E: m2 s; W
# v5 T! V* [% W1 fif (interface->bNumEndpoints != 1) return NULL;
$ _% O# t. @; C4 O0 ~/ |+ ?9 ?* K, z& C5 A3 [6 i0 H
endpoint = interface->endpoint + 0;
3 w7 j# u$ b) s4 W! u1 p9 i( p8 K- [, @+ B3 u+ f8 Y0 `# {
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
! h* K# e% X; [ maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
], N0 J: s5 y0 R8 l' r0 ]) i' W( a
usb_set_protocol(dev, interface->bInterfaceNumber, 0);
% o+ M9 ?3 w; R l( ?; J! U' {- d/ g usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); * h+ H* k/ H* s! {8 @
1 V0 Q4 _& C& ^+ G
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
" ]8 {3 I/ J. h1 Q2 Fdev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); - a- n% w, d' ?1 M9 n6 U
! O" }' ?) l; A S T/ x$ z
if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; ! t, O5 k, w$ ~0 X& @9 U3 \9 S
memset(kbd, 0, sizeof(struct usb_kbd)); 4 L7 J: H8 }+ S( [; O
M7 i2 d; y: X2 L5 v! }/ Q kbd->usbdev = dev;
" X4 i7 c8 Z6 R6 x; k; D+ N, F1 Q) p- R' m
2 Y' \" `9 |! L8 e2 i& j: ` x FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
! ?( B. J( n2 K/ Kusb_kbd_irq, kbd, endpoint->bInterval); 9 L, z0 L- E3 k3 v, L
4 ~. J- _4 @* d; c/ y
kbd->irq.dev = kbd->usbdev;
5 z1 J g$ @% r6 w1 I6 R& d; F" E- C
- X% N# x+ j/ b Jif (dev->descriptor.iManufacturer) 4 c E0 y2 i- u: `
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63); ( v& f, o, C, T# J1 A1 G6 t8 J
7 _, s, ~3 k% b" R+ I* Tif (usb_submit_urb(&kbd->irq)) { ) B" r- v9 @- V1 F5 n. d
kfree(kbd); + J- ^. `4 z" j) G" M$ t, e: o ?
return NULL; , b0 X/ U% ]6 V+ R% y' q
}
: K2 }& \2 Y3 k M% Y. n. g, ^( A, k5 X x- ?
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", ( ~$ A" v- S. @: t: a
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
. m8 o% ?/ C- C% A0 c5 | S5 i0 t" J
return kbd; 6 T- d! r) k$ f! n a; ~6 V4 k
} ; f7 B" h5 g& g* }5 e" J
: n2 _0 A9 q8 K8 y6 z
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr) " }+ Z* c; m! A. K$ W
{ . \' h6 A) m6 d3 j) o
struct usb_kbd *kbd = ptr; ' a1 z1 Q: o; }3 i* Q( ]0 L3 U
usb_unlink_urb(&kbd->irq); , [% p. o. n* `( L
kfree(kbd); ; E0 m- r' {% Y: _3 u5 _) z
- R1 k2 J7 l/ J/ o( Q% b} ' V1 H2 n4 ?" k Q
' O0 y0 v5 R+ K$ e6 d% N5 Y( Istatic struct usb_device_id usb_kbd_id_table [] = {
( w4 p# w& x- t% B1 Z7 u0 X& R- H{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) },
( ?* I7 M! t0 _. m9 S{ } /* Terminating entry */ : z+ J+ p9 ?* r, ~
}; $ o/ Z7 f8 h0 O; L I6 B5 Z
+ l6 t9 g# t& R. y# C
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table); % l$ U' q7 `8 k0 _+ l ?6 s+ S8 R3 {3 L
/ r; N @$ r# y/ m% a7 s1 i, d: O
static struct usb_driver usb_kbd_driver = {
' x5 g1 f' H4 r4 x; v9 \name: "Hotkey",
" o7 B d2 u8 k6 vprobe: usb_kbd_probe,
7 J& A/ W; C/ S ~0 l8 q0 t3 \disconnect: usb_kbd_disconnect,
% L4 z# t' L6 e2 U& ~2 Vid_table: usb_kbd_id_table, 1 x: R6 b( R& z+ [: Q; ?% L5 P
NULL, 0 e% s/ P. t: n
};
+ }+ b! C2 @5 M
3 v* ?" k) y* @- R; o4 xstatic int __init usb_kbd_init(void) + F% P! R1 p& G/ h/ r0 k
{ $ |$ |6 h- _& W B$ d0 @5 a' ~
usb_register(&usb_kbd_driver);
2 E( i+ |7 r0 [/ A; ~1 @3 iinfo(DRIVER_VERSION ":" DRIVER_DESC); - C, r; {2 R& S7 X4 c9 S7 K3 ?
return 0; ( N& q; S5 u) ]
} + v: M, P: P$ H6 y$ S% y0 t4 @3 V
' ^. L0 v2 @( u' n Q9 ]static void __exit usb_kbd_exit(void) ' d$ b/ N# L+ x1 g. k, h
{ 6 [& Q7 a; b! h! F& D! r: l
usb_deregister(&usb_kbd_driver); ' C$ x+ E$ q! D# K
}
8 [' m6 z8 i' y& |. S' _
; w5 r: ?: t: Cmodule_init(usb_kbd_init);
8 c( f6 O8 \4 E2 D/ Lmodule_exit(usb_kbd_exit); |
|