- 在线时间
- 63 小时
- 最后登录
- 2019-5-3
- 注册时间
- 2004-5-10
- 听众数
- 443
- 收听数
- 0
- 能力
- -250 分
- 体力
- 10122 点
- 威望
- -12 点
- 阅读权限
- 150
- 积分
- -516
- 相册
- 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,
& ]$ J3 N$ y& @( j' ~1 k) M9 ]" USB ", " Mass Storage ",
$ O S% n# X* h, K2 C0 eUS_SC_SCSI, US_PR_BULK, NULL, : ?: a( Y6 p5 D7 b. D! C' u7 j: E
US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE ) ) t) i0 b2 g2 ]; A, l5 ~! `
- \. V; D: F$ @' ~注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。 " U6 p2 B* ^7 a* T N# y
最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 1 _( \. D. S! T
键盘飞梭支持 4 ^8 l% s [& @ R
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 & I* ?. n: B# l, k
下面是具体看到的信息
9 I% T- }# ?7 B/ ~* z" ?* q h9 f8 X0 x$ t5 m5 p/ M
T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 : g2 p* ^( h' y" b& x/ F
B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
& z4 u& y& y2 Z9 ~9 VD: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
/ g% i5 m" O0 p$ _# mP: Vendor=0000 ProdID=0000 Rev= 0.00 # W, g7 f0 u" f. D0 L3 Y" v
S: Product=USB UHCI Root Hub # B+ Y0 ?4 {5 t% ], o
S: SerialNumber=d800 $ J! W* C6 A; C4 V3 v2 {! t
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA & v( x$ M9 {# {/ ?9 Y4 A2 h
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
& \. R9 m/ }+ C# k8 G% ~5 b! J7 M* ?E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
; u; N" u% T" _- p* `0 ?3 a8 B( hT: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 % [" O& j5 H* s1 c9 W
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 ; r ?9 R: @/ i' X5 p2 q
P: Vendor=07e4 ProdID=9473 Rev= 0.02
( O$ O. _& H" `4 F s gS: Manufacturer=ALCOR , c+ M( Q, ]! q. M+ f% ?
S: Product=Movado USB Keyboard . ?2 k/ j# s8 c- {; S
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA ! H6 N' c# f! \- F2 y$ |" x5 x. Q7 N
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub 9 T* R8 u. t: O- z- H
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
5 Z: q/ E/ i7 x找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中 $ x+ N) V Z" n7 ?, X% K- {
8 j5 V; E2 |" [ g7 c1 I7 dFILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, & }$ l: \% d# z8 g( p* _1 i
usb_kbd_irq, kbd, endpoint->bInterval); 7 z: [5 ]1 Y& P' e# ?) E3 K6 V3 w4 J9 e
& D9 u' L- c8 x- t, v2 t一句中实现。
5 k* d& O. i1 M9 Z6 r从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。
/ @& t( m! F' i) M& H' T在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。
0 C1 f: t. _9 i! A9 b( ^ S9 h程序见附录1:键盘飞梭驱动。
! k. F5 ^% u/ Q+ N* d使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。 # b% K' e( P$ }7 W) t% E5 ~+ k3 f2 ^
参考资料 ) X; G; ~+ B, Y5 w, r, h
1. 《LINUX设备驱动程序》
& x- r: Z4 ]8 O) kALESSANDRO RUBINI著 2 j7 {5 j, h2 G- c, i [
LISOLEG 译 1 i' I+ d$ n/ L2 u1 G: |8 ?
2. 《Linux系统分析与高级编程技术》
- t+ B3 S7 _) J7 n( l周巍松 编著
: Z2 F/ Z8 ?! r3 F5 n2 D! H5 }3. Linux Kernel-2.4.20源码和文档说明
. n2 R9 \' K; |# l+ x+ a附录1:键盘飞梭驱动
- e. Z( E2 G% P+ E/ u; v
1 _: p7 K4 t/ s3 t7 ^#include <linux/kernel.h>
. _$ J/ Y1 u+ f+ P$ t* I#include <linux/slab.h>
* X# [& g3 N7 w* V) K#include <linux/module.h> ! g' L( Z! w! l! v L
#include <linux/input.h> ) N0 W; q& t( {% c& R- O/ X! h# |
#include <linux/init.h>
) k* J3 {! h) j0 D/ n ^, A: S#include <linux/usb.h> ' M. @' u, i( _& @ ~( l
#include <linux/kbd_ll.h> ( m1 L3 M( k: S
9 F$ a3 z% Q" |. T% t
/* % A) x b8 G0 G! H' P
* Version Information
* w) ?3 ^7 o* i; y9 j7 s */
O+ V, S) ^4 y0 o* z#define DRIVER_VERSION ""
4 M+ K) B" {+ ~, D5 t) S3 W& |#define DRIVER_AUTHOR "TGE HOTKEY "
$ `* t4 F+ ]5 x5 [, y( m2 z#define DRIVER_DESC "USB HID Tge hotkey driver" 3 K1 ~! c0 o( p/ X4 V. ]/ ]3 _
* m; j2 d: b; |
#define USB_HOTKEY_VENDOR_ID 0x07e4 2 A4 q. F( }6 @$ Z& S1 V- l
#define USB_HOTKEY_PRODUCT_ID 0x9473 / p" i% n3 Y7 ~& i& m, m2 [$ o- c
//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值 . K8 G2 [* R- l9 g: ^
" {. i d8 t+ H8 k: K2 c& ZMODULE_AUTHOR( DRIVER_AUTHOR );
6 \( e) D* t8 w7 j* Z1 _MODULE_DESCRIPTION( DRIVER_DESC );
0 v) f' k+ w6 @5 p- d% ?
: Q9 l. K: W& r! X9 }' j; ~1 @struct usb_kbd { " q9 r$ \! r9 Q
struct input_dev dev; * G* } W/ B6 n/ n" v( d1 y! L
struct usb_device *usbdev; 2 g1 @: w/ e1 x0 ?6 w3 I+ Y1 U3 I! U! A
unsigned char new[8]; ! g* v# I& {+ @9 ]6 L
unsigned char old[8]; 9 R3 ?$ }( t" C7 i% |
struct urb irq, led; ! v m9 ^0 O8 ~* l6 I( n
// devrequest dr; * _, k9 p; h5 ^ `# o2 S
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化 . k) X9 [/ I6 j& i5 Q$ l- o9 ?0 ^3 B7 m
struct usb_ctrlrequest dr; 9 _. S+ H* M7 O/ f3 C
unsigned char leds, newleds; " W9 V* F5 }. a
char name[128]; % V# G' W- q3 h6 d/ V
int open;
9 ]" t( ]+ O& E- c+ h9 V% G}; , [ B+ i" X/ T1 u
//此结构来自内核中drivers/usb/usbkbd..c
]+ [6 R: y- ?0 k9 e! T! c7 ]2 T6 Q/ k! e
static void usb_kbd_irq(struct urb *urb)
7 ]6 G0 p' g# f{
, S4 t$ t6 p8 T# s1 jstruct usb_kbd *kbd = urb->context;
7 [3 n) t, w. R5 Y7 I( v6 G int *new;
7 l! T3 @, w% x$ N% t new = (int *) kbd->new; . l7 w$ J: ~, x1 {! {* z/ o3 V
& i3 z9 n, D$ X6 D' I! Sif(kbd->new[0] == (char)0x01)
$ x" g' U! K8 Y& g( s. `; f8 j' A$ Q{
" [, d7 m4 @/ Sif(((kbd->new[1]>>4)&0x0f)!=0x7)
* Y( | r; k7 j{ * A8 e: J* |; \
handle_scancode(0xe0,1);
& j& g4 y% l& y# s: nhandle_scancode(0x4b,1);
4 W S2 n5 F, `9 f; q1 h$ a. O handle_scancode(0xe0,0);
9 i6 [! K, g: X" v handle_scancode(0x4b,0); * I, A% J* n$ \1 s4 K3 [
} 0 S# C R; f8 e# [! b' j
else 9 w) Q0 _+ R0 X4 k: d' v
{ # i5 }. t+ o! j n x. k8 r9 F3 ]* S
handle_scancode(0xe0,1); * i2 h7 w- _, T* G' e$ R! e
handle_scancode(0x4d,1);
M, |, R7 N0 M; F. q. q handle_scancode(0xe0,0);
9 s1 k" v, k- |$ k% n. D handle_scancode(0x4d,0);
+ r% M% R3 V& B$ N- o}
8 F9 W2 S- x @8 z} 5 ^( [* U Y, H& O+ L4 S% M# V3 Z& k
1 G# U' d# b/ z e
1 j# z+ h% h- t' ]' x( {printk("new=%x %x %x %x %x %x %x %x",
0 n6 q( \/ y( [# ]. Q! Gkbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], " p1 B7 U& V' R, A$ [
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
6 o# I& R/ U! Y. f6 A, p& u( H5 ]0 O/ m/ H* b
}
2 j* i( D8 H3 g- C
5 d" s* ?7 U- n6 n' Q U/ V# C. K2 H8 Astatic void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
, d9 Q# D( I# t8 g const struct usb_device_id *id) ) X2 b# X* _$ b u1 @2 r8 l: f, b$ i
{
. Y* d/ k0 J8 j8 x/ G1 l6 xstruct usb_interface *iface; ( Z* H& g D6 k: T
struct usb_interface_descriptor *interface; 3 w. Y% }( ~. h; R; i, n$ W0 }
struct usb_endpoint_descriptor *endpoint;
" _% ?$ s7 h+ y0 S# @* d' m# { struct usb_kbd *kbd; & |$ U# }; u9 k1 e4 i/ I
int pipe, maxp;
2 _& G+ y) U& r1 a2 W9 ^( j- O- d
0 N3 B! I9 @$ @( jiface = &dev->actconfig->interface[ifnum]; . j, ?& H" A* c" G( w7 Q) h
interface = &iface->altsetting[iface->act_altsetting]; 8 P4 W a% J' U) }* `$ Q) l' ~ o
- m9 l& Q. p, zif ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || 8 C# _# @% g1 N0 W- g! I, b1 v
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || - o9 O/ n$ F! a+ R2 ]" @) A' `
(ifnum != 1)) : X, f& e+ a4 I4 L) x0 o
{ 3 T4 G& o- L4 L$ `
return NULL;
. O1 z0 p: _6 k' d$ h0 b2 g: z} 9 |2 u. n7 G9 p6 O+ P; L: d
if (dev->actconfig->bNumInterfaces != 2)
, T4 G7 C3 r( r% M/ ~& N2 e{ L' o1 x z+ {/ J v/ e
return NULL; ' j( V1 r1 y- x. W/ E7 G' k
}
* d0 W& x! S- ` x! ^4 i8 @$ x: r1 B
' L! y6 [' P! b. z- Fif (interface->bNumEndpoints != 1) return NULL;
2 l- _$ {' c+ C1 Y- l
8 w- Q4 X7 @ S1 o+ a3 [ endpoint = interface->endpoint + 0; , e$ v6 ?. M9 e% I5 \. c! w4 g
9 h/ o1 |) g$ |; U6 k1 {2 L4 e
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); 2 n4 }- x/ q+ A v# `9 |! p
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
) p1 K) ~5 r6 {2 `( h( i* W9 o2 V6 a; T; q/ ]9 D0 g
usb_set_protocol(dev, interface->bInterfaceNumber, 0); / T( Y7 m: H7 J0 x6 e
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); 0 ~/ d6 E* t9 z3 }
9 J5 e, `: ]" j
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
& V" M) X' B& O& Z, M; idev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp);
# M5 y* i% c1 }, t/ w3 ?' p- E
' j# L0 k% \. w a* y if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; 8 r# |, D8 k& T1 d; h/ v
memset(kbd, 0, sizeof(struct usb_kbd)); ( C& k# m, G- O5 {: g, m
, l, t( b' L: \+ Y' U5 r9 l$ S$ c
kbd->usbdev = dev;
. t0 p" K$ |) I) i; ]. H. q. j4 r1 J0 D) s- g" p
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
, o" N' @" a" w& T: dusb_kbd_irq, kbd, endpoint->bInterval);
/ }5 m1 a: p) Q0 |9 O
, _3 ]& P2 i( M) Okbd->irq.dev = kbd->usbdev; * C# L4 c, i) v6 B, S
2 U! m3 W( H7 `1 `; I$ rif (dev->descriptor.iManufacturer) 3 k% t3 Y+ ?# d' d8 h/ |
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63); & l9 C. H8 m' V) g/ p# s/ d) K) ~
( q9 y) ]( q% i, s( m" l5 _
if (usb_submit_urb(&kbd->irq)) {
M4 E. y8 s2 n kfree(kbd);
( c: @/ V% C7 Y* A$ @& d3 V# @, d return NULL;
/ z$ G) ~. T/ @* b5 L( s }
( @: Z. \1 {9 S0 K& K: _5 ~, ~0 ^2 a
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", Y, \; b' K. U4 B, L! Q; V: n+ K
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
) M+ ~2 X. ~: R& }% e8 p; f/ n: E& z
return kbd;
# E+ r4 L3 @; Z3 d: v" l} . ~/ }2 }. g+ k& u. X0 A+ D/ S3 t, B" B
6 x- y) s$ u5 ], i" e0 d9 O' Vstatic void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
( x$ s- z2 B4 ~$ O( d{
# P6 d) \ C1 G D7 q, e% ~struct usb_kbd *kbd = ptr; * f4 G1 C; ~; n# p8 O2 |2 U
usb_unlink_urb(&kbd->irq); , w( M3 W. \* i
kfree(kbd); 3 v) r8 L: c" x. X) K8 _" C
& j, K2 w/ g4 S& m1 T4 J! F1 |
} + T8 V4 [1 u# V1 p
4 S; e g/ {1 e# b7 @static struct usb_device_id usb_kbd_id_table [] = {
& W) X1 Q. s4 ~{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) }, . V' L% i" N- ^2 G* ?' ]# e0 u
{ } /* Terminating entry */ 1 W6 W+ @, M/ F( Y/ z
};
6 g3 @" x" [3 ?: H# y2 n4 `
. Z, X% o- J, I2 A& S% I. X) [MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
+ p# h# ~: x8 ~5 [
5 c1 X1 ?% P9 e; ?+ S$ `static struct usb_driver usb_kbd_driver = {
3 q- B6 U( P9 i/ E- I) ^3 W# vname: "Hotkey",
y% C: u( P( m) r m& d" |- Q) ?* Tprobe: usb_kbd_probe, . ]# c8 n6 n) i2 W4 T: \+ {
disconnect: usb_kbd_disconnect,
( Z' o- Q2 N6 g1 c% }id_table: usb_kbd_id_table, ' q+ ^- P# O+ @3 c* E
NULL, 8 W4 z7 A( n3 u. I9 q: R1 K0 t) v
};
; c0 B9 Z2 @2 v; i3 v+ t8 B! C1 D5 U" M" B4 v
static int __init usb_kbd_init(void) ' \, v5 ? U/ n3 Y& A
{ 6 ?6 r+ x, @2 N# z
usb_register(&usb_kbd_driver); $ ]+ o. A: G1 B$ Z+ }# w Y: r
info(DRIVER_VERSION ":" DRIVER_DESC);
4 T, R, D# V, ~1 U1 ireturn 0; - u+ z6 P7 [% U8 A# s, r
} : x, }( f% i8 N/ l
0 P$ s9 h# z1 q) K ^/ ~static void __exit usb_kbd_exit(void) 6 G) x- U; w7 b, s+ t
{ + G7 e" Q X! E. ?5 x
usb_deregister(&usb_kbd_driver);
' ~, c9 m! R# G) S& \ j: W* T4 R}
8 U7 s3 ~3 c4 o0 q6 a- u- Z2 i( A% e2 R- w7 ~3 l
module_init(usb_kbd_init); - L/ z" \6 R- Q/ m# N
module_exit(usb_kbd_exit); |
|