- 在线时间
- 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, + ~. Y# K, ^, [, Z; {9 V, g
" USB ", " Mass Storage ",
2 K" Q1 n6 J) tUS_SC_SCSI, US_PR_BULK, NULL,
3 s3 u" ~) Y! P; Y$ b4 A# {US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE )
1 ?9 R& Q8 K( e8 H3 S1 T& E! k$ N3 g+ z! i, U8 n
注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。 % `; B. F' S; e7 G/ _8 Y) u' U
最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 ! x% H+ c! ^; b
键盘飞梭支持 , b) ~) C0 z7 b* S- B+ M( e. R
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。
" u4 G: A) L( \9 X! `+ N# {7 t下面是具体看到的信息 % ^8 Z+ m* I# s) a9 K7 |
0 C9 G" Q5 i2 s7 h3 p9 z" o* dT: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
! D7 L' U+ p. m6 t7 y/ AB: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0 & E% M8 V5 }$ a+ A3 P
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
" H1 M* h. l1 @) t6 K. t7 M. i3 MP: Vendor=0000 ProdID=0000 Rev= 0.00
H" O2 G+ `5 _1 r' W& YS: Product=USB UHCI Root Hub
( |) z9 |6 G; Q( AS: SerialNumber=d800
7 x' C; ^0 C2 |& _C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA % H$ M a. H8 U1 P' |
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
6 l( }- C* M3 D; JE: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
- U B/ Q3 F3 Y4 K5 pT: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3
" J7 S, s+ W7 ^) Q1 ~D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 7 C, ]( G7 g: e3 c1 |5 }# o
P: Vendor=07e4 ProdID=9473 Rev= 0.02 7 C; E; d1 K6 v( q( v: m) O
S: Manufacturer=ALCOR
0 L5 O# E. q$ B DS: Product=Movado USB Keyboard 2 a9 k9 ~9 _- A( j( j) N
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA : B& z ^0 o0 a, Y
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub 3 S& u) p) \3 f2 @ N1 X
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms 4 ?0 Z& b/ `. X+ }6 W
找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中
2 c1 E# }* [" Y# L3 u. |
6 j; r$ w3 G& j8 c9 _% t8 [FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 8 E! u, G8 q7 {; `* C* d& r0 G
usb_kbd_irq, kbd, endpoint->bInterval); 9 v* `9 S6 _5 }" ?& C! q( b
4 z2 y; E$ ~; x! E一句中实现。
) `3 e1 L" }. O8 G& q从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。
6 o( [0 x& d! G* _7 ^; m/ d8 d在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 4 _) A8 V& Z$ c; m# \- p r
程序见附录1:键盘飞梭驱动。
. Q6 y8 h% J% U" X3 F0 P. l9 j* H; N! @使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。 ' l9 r4 @6 H8 U
参考资料
. d, @0 N) q. Y5 ^4 t& u1. 《LINUX设备驱动程序》
1 _" u. O# x d, xALESSANDRO RUBINI著 7 X/ Q. Z; b6 X7 k! b
LISOLEG 译 : n. }' K# d* b+ H" D: x
2. 《Linux系统分析与高级编程技术》
6 k2 x3 d" ], k; ~9 W4 D$ u. o' o# n周巍松 编著
) I3 Z$ C# A2 Y' |: |) F3. Linux Kernel-2.4.20源码和文档说明 ) k. R& L$ p% S4 y- i9 Q
附录1:键盘飞梭驱动
m5 m! g3 Z4 \+ j ?8 Q$ {8 r) W; v1 G0 c; @; V9 P
#include <linux/kernel.h>
6 W1 z0 o* Q5 H; T- X- a$ z#include <linux/slab.h> / N$ ~( F5 o; Y, D
#include <linux/module.h> 1 p( [( T. _" ^" q3 {! J& D) v8 }
#include <linux/input.h>
9 u; {7 O$ F& @$ j#include <linux/init.h>
; |, H/ L8 ^. {# ]) y- R9 P" T6 t#include <linux/usb.h> 2 r4 j+ C3 N! Q Z0 d
#include <linux/kbd_ll.h>
+ K" E6 n( _1 G0 T9 N+ y
; S$ `+ B1 [, `3 v4 N/*
' O, q' m. f5 e! M * Version Information " I4 `% h! x% B6 s% o
*/ 7 l! Y. b" }! J0 j: [
#define DRIVER_VERSION "" " q0 j( _. M. K* s! b2 {# q3 ^& `
#define DRIVER_AUTHOR "TGE HOTKEY " ' ~8 j" S5 P4 }& U# u. ~
#define DRIVER_DESC "USB HID Tge hotkey driver" / k5 q5 P: |0 {" p" D' f
: j3 p/ R* e0 j7 r' o. a0 K3 ?( ]) ^
#define USB_HOTKEY_VENDOR_ID 0x07e4
8 f! }: h/ r8 F! p# l l4 V#define USB_HOTKEY_PRODUCT_ID 0x9473
8 w0 E& @5 p. y' M//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
! ?7 r: P! h$ G
0 e+ ?; E1 V, N3 o8 NMODULE_AUTHOR( DRIVER_AUTHOR );
# X* z1 a; V4 }" A2 ?! WMODULE_DESCRIPTION( DRIVER_DESC ); 1 A( }% E* j$ U6 m0 ?8 S# `/ ?
$ ], r# |6 r- @ \" c# u! estruct usb_kbd {
4 g6 D1 o0 i- Q7 O7 l2 j9 gstruct input_dev dev;
; j" l+ G% O3 c5 J1 Bstruct usb_device *usbdev;
' x& ^+ _8 j9 d& Zunsigned char new[8]; 5 [7 P8 y; C2 L
unsigned char old[8];
) q: ?2 m: g. g0 a6 j7 fstruct urb irq, led;
; {0 p% H: M @& N// devrequest dr; ! g5 C3 w* }9 E1 o) U: p+ B- W
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
! y9 l. ?- o6 m" f$ Y struct usb_ctrlrequest dr; 2 F% l' e) u7 @. @ r0 P7 l
unsigned char leds, newleds; - o. {4 E" M5 Z8 m
char name[128];
/ x" I/ U1 S4 M- v6 v/ O: qint open; ! h$ I- E1 }2 u, U) a; a1 h. c: R
}; , h9 A8 z1 t! c+ j$ G
//此结构来自内核中drivers/usb/usbkbd..c " g4 ?4 K8 J7 B% P- x0 ~
- N7 z- @: v4 y1 Ostatic void usb_kbd_irq(struct urb *urb) ( l8 ^4 W% F8 }
{ : u1 x# ~( X9 Y% E7 J
struct usb_kbd *kbd = urb->context; * G* T$ V' Z5 L7 }# W6 K- ?# n: K
int *new;
$ c) ~7 B3 d) l3 u* J4 ^6 L new = (int *) kbd->new;
$ T: K1 u! X' V. G2 p
# ~8 q0 ~8 J# y. x) ~- jif(kbd->new[0] == (char)0x01) 5 @. E1 Z5 J# v# B: b+ X
{
+ n3 u. p$ F7 W7 s- gif(((kbd->new[1]>>4)&0x0f)!=0x7) " s- d8 c! N( d
{
8 }4 t7 M; A# E5 i6 c. whandle_scancode(0xe0,1);
2 }6 `, ?3 e; z/ a. T5 @8 Vhandle_scancode(0x4b,1); ; |$ s( } s9 h) G" i2 h% I9 \
handle_scancode(0xe0,0);
0 l: H) S B( G- Z0 _6 } handle_scancode(0x4b,0); 4 h ^5 Z& p2 p
}
0 K) g2 _1 v# E/ z# I$ lelse
: ^; e6 W1 L1 F& \+ q' z! @; j1 r! L{ 6 p. |8 `+ T K
handle_scancode(0xe0,1);
1 }7 r+ ?# Q* H5 ~) f9 U0 U9 S Y ?+ u handle_scancode(0x4d,1); : e- y- w6 i' {: l
handle_scancode(0xe0,0); & E- `" o- m% t
handle_scancode(0x4d,0);
- f' V" R+ i! ?% h+ |3 C} & ]8 q" R/ `: \9 i8 S
} 3 z8 i; F ?& U; Z* q
% \) v8 T- c9 u' T3 p1 x e3 [ O$ B) ^% }
printk("new=%x %x %x %x %x %x %x %x",
5 y1 M) I/ M9 W+ O( X* o& W8 lkbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3],
6 [/ y$ D! \+ ?7 K8 E- ~* \* fkbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]); - y3 [8 b! g6 C" \# {
# z! h9 l% ^' Y9 x4 v' X9 X9 Y
}
, j6 {$ n! g f3 w* R
q6 e4 `. v+ o8 x# fstatic void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
3 |1 D: W' c/ z3 Q3 [! r const struct usb_device_id *id)
/ ~% V4 A/ J" ^; R{ ) ]' C2 K( Q6 x% N
struct usb_interface *iface;
$ {5 S9 u8 ^& ?- h struct usb_interface_descriptor *interface; + u3 |* g6 r" E# j" }1 Z2 R
struct usb_endpoint_descriptor *endpoint; ( ~" j% t4 a8 s% \9 P
struct usb_kbd *kbd;
1 [5 V0 H/ N/ o. f, O4 U int pipe, maxp; , s$ l7 {( [# S1 ]5 I/ \" g
1 Z- Y! B& U2 S' b0 L& Z
iface = &dev->actconfig->interface[ifnum]; $ c" q, a8 L9 F: j4 g5 L M; E
interface = &iface->altsetting[iface->act_altsetting];
R# n s/ F! b7 Q/ a; C
( R5 Y+ q7 F Y) j( B: rif ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) ||
3 e' R9 y; R* C% G5 C: Y. D: `- ~' Z* b(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) ||
$ P5 ?6 y) {( ^0 u4 [* x) P% ?(ifnum != 1)) ) g+ Q2 X+ Y9 w9 n# Y! ^
{ 4 Y+ ]; y5 d) B0 @: p) r
return NULL; * P/ \3 h$ |% a3 H
}
# B6 o& j: R9 F7 j& k% \if (dev->actconfig->bNumInterfaces != 2)
; g7 ^. `% k6 e9 {5 |{ ! ^2 `! ^" @, o
return NULL;
3 I* o: X) E$ y) B, Q} / z- r; k- L1 n: W$ L* z' |
E4 p' k" w( T' [; _6 D
if (interface->bNumEndpoints != 1) return NULL; % T ~- _, Z' Y. K
; y1 t2 a( K2 Q; X7 Z! K. B
endpoint = interface->endpoint + 0;
& P( v+ y! @6 r* o) O( M: X% `. d3 D" X
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); 0 J; Y8 q/ M: f- Z4 i
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
; l9 ?" ]% g* q: \6 Z% n/ r" e: v, q0 _$ F& Z
usb_set_protocol(dev, interface->bInterfaceNumber, 0); $ r T. }4 Z3 a6 D$ r
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); " r2 @& j% m9 i4 K7 B, D0 j
+ X& v6 j4 U6 {/ C7 m- }2 S
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
# p! E+ a* V) C; L7 h W$ wdev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); , D7 K+ f6 q% Y
7 L( Q. h) D: c) [5 M& u+ U" W if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; ( b: C0 x1 D/ @" M. f$ S$ j
memset(kbd, 0, sizeof(struct usb_kbd));
1 u) e8 R' n5 o6 }
5 t! A/ l9 l' k# y/ }3 l kbd->usbdev = dev;
2 |/ z& i+ N! k+ p' P
n% |7 E! h e) @, M x3 v FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, , P) P8 k0 D b& T% r
usb_kbd_irq, kbd, endpoint->bInterval);
% l$ O& K+ \: m6 P2 H- Z# Y
' N6 l5 x+ Y5 ~0 M8 Z* W2 okbd->irq.dev = kbd->usbdev;
& J4 d% K6 K0 l" Y
7 P% t- F. w# Z. G& yif (dev->descriptor.iManufacturer)
2 ^" Y6 ~( ~" b( x' v usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63);
/ T, L( I) B" {" e
% H6 v# V7 r$ r6 U- B( F* n5 u- o* D$ aif (usb_submit_urb(&kbd->irq)) { : D- w# x4 u; Z$ c) d5 D" g
kfree(kbd); 0 f+ a: ?& {; h0 z' @! [
return NULL; - s6 x5 o$ p; j6 |! U7 ~% f
}
& u9 p& X% ^$ M" O; x
$ x' s+ W. [* q( ]$ kprintk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", - y1 F! T& e! `# T* S+ [
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); # w* U4 l$ v" l+ J
* z9 D( X8 z! s6 p3 U return kbd; K- @; f; \/ |3 K# a! J
}
5 H# [) j4 L- a' l& u5 O" g; y+ a
6 s* M6 B. S$ K7 i' b4 k' cstatic void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
7 d3 P# p4 e: F3 U M/ g{ . O+ h( G; I; L( z+ i" ]0 B
struct usb_kbd *kbd = ptr;
6 j# I8 Y" K# k6 N0 v2 A usb_unlink_urb(&kbd->irq);
# W- ^" f+ |0 z0 s+ R0 R. D kfree(kbd);
q) z% j! P) }) ?0 z% {( p
! F$ q: |9 b4 Y$ M+ R" B# f}
/ X, ]6 O5 R" p3 Y1 Q9 o( s# y8 Y8 B
static struct usb_device_id usb_kbd_id_table [] = { : @: |. q: k5 a8 x3 f: i# C S
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) },
9 B; A& n2 k) Y" R9 |{ } /* Terminating entry */ " X# g7 `: {' M. U
}; 7 U- S0 ]3 _" e. {/ Z' M
% f/ V: |3 }+ d( N2 ^* p& LMODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
5 e( @4 a# Q) o3 j7 O8 u: A( H$ d8 r5 j; I1 U
static struct usb_driver usb_kbd_driver = {
4 y% m* K! ^% w* y# c! H; [9 \name: "Hotkey", 5 a5 K( [7 h3 Y% L4 M1 P
probe: usb_kbd_probe, ; n6 i6 h/ x( {9 l6 _+ X
disconnect: usb_kbd_disconnect,
, q) [8 |# M! Zid_table: usb_kbd_id_table, 5 C5 a3 k$ d, m" w' b: Q% J
NULL,
8 _" J: r$ n; |0 h/ m}; 8 T& z& k2 ^( r" @# A4 ~. O, Y
8 o, n" u% s( ]4 x+ }0 y' U+ ystatic int __init usb_kbd_init(void)
, f/ X$ ^) ^& }& r{
. H4 P; \. a% {" W0 R+ y h5 Eusb_register(&usb_kbd_driver); 3 Y# n2 z @' u. }
info(DRIVER_VERSION ":" DRIVER_DESC);
, X# E$ k; ^. d- V- O3 y2 D+ Wreturn 0; $ j/ Q' u& V5 g7 k# y
} 7 Z) F0 g% s1 u
3 Q0 f z) F P' l7 u( v& ]" h
static void __exit usb_kbd_exit(void)
9 A. q% N, b( Z{ 0 x8 {* ^* u9 x$ x6 d0 y
usb_deregister(&usb_kbd_driver); 0 J9 o/ W* D+ M: M6 X" k+ l
} % g( E1 J. A) m" N" l; p. P8 z3 l
( n n4 x! [# F7 amodule_init(usb_kbd_init); + u: v/ l g" b$ k4 M0 w4 B
module_exit(usb_kbd_exit); |
|