- 在线时间
- 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, ; I$ a. ? v k1 K( [
" USB ", " Mass Storage ",
7 M/ \; Z( i/ rUS_SC_SCSI, US_PR_BULK, NULL,
! G$ J# k# S9 b! uUS_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE ) 7 G* s) I1 b% `) @' s( B5 n- }* q
6 n# b: z" ~; z注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
5 o) J) J& V" z; ~最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 * c* J7 z" b6 r6 J
键盘飞梭支持
, N/ k4 Z* h# P3 t目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。
; `9 q& _; }# R+ ?5 Y下面是具体看到的信息 / a X2 {7 k% m2 X- M# ^: I
3 I) M1 c/ M) P: i8 `3 [6 @T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 6 t& g6 H' S1 N
B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
0 V+ J7 y! w6 N/ o3 JD: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 ; c7 x) y. r+ q9 j5 @
P: Vendor=0000 ProdID=0000 Rev= 0.00
) h' V/ [; M8 }1 T9 C, NS: Product=USB UHCI Root Hub
/ d& ^7 [: i; ~S: SerialNumber=d800
2 @' @8 X+ e3 i& c6 R* F# ~2 sC:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA - j d& c G5 @: H, l, P( I
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub 1 n `% P' I! `; P9 I$ K0 o
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
$ [( W7 ^) k* c4 S" o0 vT: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 , w& b/ ~& e) d7 c% n$ h, ?
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
. U+ q# \# F' x4 g0 K) q1 yP: Vendor=07e4 ProdID=9473 Rev= 0.02
% f0 H6 O$ Y' ~$ P: F$ {4 o5 JS: Manufacturer=ALCOR ' ]6 A- t( x" J4 O
S: Product=Movado USB Keyboard 8 D4 ^3 X. t+ D+ x' Q1 G
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
, `5 B) M' B V: fI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
0 j7 f6 D0 w7 i! d- x# }" X* dE: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms % c/ M( S. ~; B' C6 H! }
找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中 ) x6 S8 W! y" D
& R+ a; F) N; q- l$ ZFILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, % j! j- L# Y& F/ N8 X# T
usb_kbd_irq, kbd, endpoint->bInterval);
1 U/ V8 T2 j Y9 ]% e% j5 U- w; Q' B/ n+ J7 t
一句中实现。 5 X& W/ C- S2 G* a2 R& |/ D a! A4 d
从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。 5 l0 g5 s& d8 X* Q) j- A( W
在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 & t; K/ X# `- v' Y" [* r! t
程序见附录1:键盘飞梭驱动。 g! w3 ?. Y, M, o7 s
使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。 0 M; Q1 V( l3 a" Z W+ M
参考资料
1 w6 z8 a0 ?8 @! G8 y1. 《LINUX设备驱动程序》
9 r2 o# }% ?7 N rALESSANDRO RUBINI著 ' t) s# q+ I _. H+ }; {
LISOLEG 译 & }0 t+ _; i/ J" |
2. 《Linux系统分析与高级编程技术》
8 e8 i1 x4 |/ z周巍松 编著 ) H9 t2 q9 z$ Y; I. N; o7 A
3. Linux Kernel-2.4.20源码和文档说明
1 O: t! y1 C/ d5 ~( t1 A+ x. v附录1:键盘飞梭驱动
$ J( d8 R& |: R5 X: u, X$ \4 f, G5 D9 Z* X- Q
#include <linux/kernel.h> 3 `: G7 d, a+ J! ~, p2 Y
#include <linux/slab.h>
7 ? T5 h7 P2 H* d3 X#include <linux/module.h> 7 D, K8 m* B. V3 f& C$ K
#include <linux/input.h> $ k r& u( V. D4 v$ Y
#include <linux/init.h> 5 o; Z, C! Q! K
#include <linux/usb.h>
+ e$ T5 d1 e& S/ T#include <linux/kbd_ll.h>
! J1 {0 g" x9 f7 m$ S7 O$ \, X
& _; j7 c" v; K1 x: [/*
# {, Q& Q6 ]! T9 R * Version Information
- n, i7 x0 k8 B9 s! t4 G, S */
6 T# l2 \% F+ X4 b/ p u( ^" g#define DRIVER_VERSION "" ! ^# K) L% I- A
#define DRIVER_AUTHOR "TGE HOTKEY "
8 _3 r5 U3 |& ?3 i3 ^$ H7 ?#define DRIVER_DESC "USB HID Tge hotkey driver" ) r! k3 t. {' X. |. |" z
" i4 n* d5 j( m+ L- g% z
#define USB_HOTKEY_VENDOR_ID 0x07e4 ' T2 h: {* c: H
#define USB_HOTKEY_PRODUCT_ID 0x9473
- S3 D# V8 U- Y$ ^# [//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
: f4 I, Y7 d" c8 d( r
* i" E% K/ A/ N3 ~8 v1 hMODULE_AUTHOR( DRIVER_AUTHOR ); [; C8 B+ Q+ ]; X+ z m2 K, }6 t/ c
MODULE_DESCRIPTION( DRIVER_DESC );
. @' T* P$ l- \( ^7 i0 u/ [+ y6 s6 Q# Q2 Z: d+ p( ?, s
struct usb_kbd { 7 z$ [5 M. G4 S' y2 u
struct input_dev dev; . w: K" ?, F) m' C/ B) @: ~9 ?
struct usb_device *usbdev;
# v2 E$ ]6 U5 c3 munsigned char new[8];
, \9 t% C7 h) n6 \unsigned char old[8];
- G% B: k% b8 M1 B1 {9 ^; kstruct urb irq, led; 6 D1 y7 x+ K) _0 p! y
// devrequest dr; 0 s! K. c; j+ M! R" |/ } b
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化 ' s1 A' P" ]! S9 ~* D5 K0 Z
struct usb_ctrlrequest dr; * y1 a6 R. ?4 X. L2 z5 V
unsigned char leds, newleds;
% d, e1 }7 n& A6 E5 p/ M. _; |char name[128];
5 o/ U" n* |( l* ^; B3 Kint open; 7 ~0 r9 S4 P& N$ X
}; 2 v8 q6 h4 n! B& V/ K! w
//此结构来自内核中drivers/usb/usbkbd..c . C) }; [# A1 R- p* W
. N1 E ?/ _+ ?
static void usb_kbd_irq(struct urb *urb) : B' q/ g; `, C6 H
{ 9 i. c7 L# {4 c# @, h
struct usb_kbd *kbd = urb->context; & _5 R7 `8 p/ `2 d! N) `
int *new; & t4 P3 ?6 H- k( L5 V
new = (int *) kbd->new;
2 @/ f+ b3 w. J7 B2 n, w3 _& b9 H% c, O/ B9 d* }/ Q3 C
if(kbd->new[0] == (char)0x01)
- u0 r3 v( y5 z" k{
! c4 U; y& W. `3 q5 e( Pif(((kbd->new[1]>>4)&0x0f)!=0x7)
$ z0 T5 N5 U1 z1 x{
8 _( Q1 C1 N+ J; a' f0 yhandle_scancode(0xe0,1);
) s3 _# l" J% V5 h W" }. m6 F$ Xhandle_scancode(0x4b,1); " m3 Y' T0 C: L; V6 T0 v
handle_scancode(0xe0,0); 2 Y/ \! U/ I) R# h0 m: \
handle_scancode(0x4b,0);
; b- L- B/ |0 ^1 D' {7 D6 t}
) ?' R: M0 H" f) f1 {else * T, z: I8 v0 _2 c( d! S
{
% W0 j, d. P- N; Nhandle_scancode(0xe0,1); , _3 u9 u: ]: o( k j+ p! U( L) l
handle_scancode(0x4d,1); 5 [) g- ~9 j+ Z- e2 O
handle_scancode(0xe0,0); 6 l: z- q: Z4 [$ N! H
handle_scancode(0x4d,0);
* U8 G" x" Y% Y1 H) Q( I( n- E, Y}
! \7 M- p' S+ D) x2 ^} ; m' [! C4 Z/ E! g1 J* g
: \$ J& l( u7 o' F8 M' a( ]9 c
- E- T. `; o* `' w6 C1 K( pprintk("new=%x %x %x %x %x %x %x %x", / I' D) A6 Y u7 H% g' d: ~# j- W
kbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3],
5 W# S. U1 Q# k/ n; qkbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
! I' A( n( o2 `5 @ V
5 l; U# m2 k, _$ N' l0 I} + h# T" n3 U# X: `1 G0 ]- f
/ @/ D' B% J% x; q, u Gstatic void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
, }: k7 i. _4 ~$ B# J3 J( s const struct usb_device_id *id) ( ~, v6 N+ {& V% Y/ L7 S& b& ]
{
/ w; Z K2 I4 @8 E5 W9 N! Estruct usb_interface *iface;
) i/ h# c% [, ~ struct usb_interface_descriptor *interface; ' p7 \: o* ]* ?* s/ B; l
struct usb_endpoint_descriptor *endpoint;
, j% ?5 S% P/ H1 a( C struct usb_kbd *kbd; $ ~+ u9 c1 V) d5 U# n5 [
int pipe, maxp; 5 U1 a% r3 b# J6 I9 p
4 \5 q6 \$ k* w6 b! P1 B; ?iface = &dev->actconfig->interface[ifnum]; 6 |3 [# C& l/ D$ L! L
interface = &iface->altsetting[iface->act_altsetting]; ; ?$ L6 ]/ r3 r2 h' G
1 B; f+ I) }5 E) w% ?9 P
if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) ||
" G( p/ [. a* s(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || ; V% p: {6 n) S) J& Z% j: g
(ifnum != 1))
% R. h* D& t" N$ Z; Q{
* q- E3 o' D" j6 F& Dreturn NULL;
$ f4 `/ ?! P9 ]; m& s}
8 q0 R1 D, g5 Dif (dev->actconfig->bNumInterfaces != 2)
& r0 m; V+ U% O2 L6 P5 J3 i{
2 B# ], _5 \ v" t+ _, preturn NULL; & S" c( j( ^( ?$ Z/ T# @
} ( C6 e& u5 s. e* u$ I/ w6 X' W; \
" X$ }6 L) B. i1 Xif (interface->bNumEndpoints != 1) return NULL;
7 o0 K( R7 F! r1 {4 g% ]" `4 n& W, y: m. b* [3 a- E
endpoint = interface->endpoint + 0;
6 s; h |8 ?4 @: i9 v+ ] j% V$ }! @" l( |6 z
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); 5 {; ~* C/ Q' i+ l+ T$ R
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
9 ^9 C( j( @9 H, J9 S* i5 U
) n. {" e1 { P; ` usb_set_protocol(dev, interface->bInterfaceNumber, 0); 6 x0 b4 \( C; C5 w0 ^2 n
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
' @% b! ?: m: A9 f6 i1 ~! D6 u, c9 q8 j8 V" v, @5 m
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n", . w" z' m& ^! H# D
dev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); / u# _! e( _ g& r% ]9 B; @; k# ^
8 p, I2 c# Z" c7 `" _ if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
# F* i0 m4 K6 R4 { memset(kbd, 0, sizeof(struct usb_kbd)); 0 d( z( w& G. p) H( K! ]
! ]5 A: {- C$ V$ Q4 C
kbd->usbdev = dev; 2 e) ?% [2 l- P/ G+ A7 |; l8 h, B: _1 {
, J# d- ]* s- o5 S8 \/ X" w FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 9 ^% g6 ^/ S7 ?4 J8 r9 f+ h3 O$ ?+ q C
usb_kbd_irq, kbd, endpoint->bInterval); * H% C6 h0 v2 I, l! w% {+ J$ q
' t3 y4 c( S- F( s8 F( o. V6 K6 Akbd->irq.dev = kbd->usbdev; : |, g s6 C( U) H1 {/ d- C
( h( [5 J" \/ c4 d
if (dev->descriptor.iManufacturer) ! i6 [* F; D! A% B9 y
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63); ' G& N* J5 @- a/ ]
8 V0 ]/ S% D- k
if (usb_submit_urb(&kbd->irq)) {
) O) s; q r$ S& m kfree(kbd);
6 u5 |. L, e4 {7 L! | return NULL; : J( j- k0 k+ d8 W$ n8 I# S
} ) Z/ g l# e, V/ v9 Q0 R
/ |0 p2 a \& w2 u5 p+ [- h( D- o
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n",
! u! X. X- S1 r6 N* m9 b' J kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
6 O/ X8 S& i. i }6 o
* D8 o( ], h* e return kbd; & H3 `. n/ Q' j' r" ^
} 5 Y- S2 H% y/ C. G6 Y9 E
6 a- y% z3 m% Cstatic void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
, \, i* a' z7 F{ 2 Z$ F: C. S5 }2 f
struct usb_kbd *kbd = ptr;
# E; Q. \9 M$ g) b usb_unlink_urb(&kbd->irq); ! \& c4 f$ P2 Y
kfree(kbd);
) N7 @8 Q+ T4 Y$ w5 O! D, n+ @/ {" O! v0 C* b3 T2 c: x
} , A5 u" L# p: E% l5 Z# ]+ ]
: b8 [4 ]0 C3 m
static struct usb_device_id usb_kbd_id_table [] = { 6 {4 |/ [7 h' T- Z
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) },
* x ]6 y' N- j- y{ } /* Terminating entry */
R, Q7 s5 l" U; z; `3 |9 l- b$ c}; ) h; R9 F9 u/ T3 x
6 E4 M+ ?- n! N( k7 I# f+ O& a( T& b! s) kMODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
& u& @! W* t2 T& ?2 M* o
2 D8 R. h. `" j" e W s) g% u2 tstatic struct usb_driver usb_kbd_driver = { ( \: N/ b* _4 a
name: "Hotkey",
1 k8 G) M; O y- {- S) \& o g, v& j! Dprobe: usb_kbd_probe, + I, u9 K2 u9 m L5 e; u
disconnect: usb_kbd_disconnect, 5 m, \8 B7 S& l0 @' x$ x0 A
id_table: usb_kbd_id_table,
: ^- f) Z3 Q. }; h& CNULL,
% r& @: k1 U+ W1 h5 \}; 8 P1 f& y J1 C! q# b
9 ]1 q# @ \5 |' W' o, Jstatic int __init usb_kbd_init(void)
' M1 |) C% L: z8 y2 O1 e{ % w @% b2 V3 J8 H7 N
usb_register(&usb_kbd_driver); 9 |* \' x+ e) b; H2 ~
info(DRIVER_VERSION ":" DRIVER_DESC);
`% Y3 K" J2 E' S) qreturn 0;
" m% h: A3 Y& q4 R5 y}
' R" F9 y! ?! R$ ^+ F; P' d1 Q2 w/ ^. Q3 l) `" Z
static void __exit usb_kbd_exit(void)
$ L8 C; c3 ?! d, w0 w- j1 N: b{ 0 ^& D- j, Z$ N$ t) V) M( X; _, J! I8 \
usb_deregister(&usb_kbd_driver); , [4 O! I' ^) U$ u3 K$ z2 b
} 8 b/ u) w' ?3 ?0 J) w0 f1 q
8 Y$ i2 W! s/ K5 `( P0 x
module_init(usb_kbd_init); 1 N7 y& }2 M! C" E4 V/ `8 R# ^3 U
module_exit(usb_kbd_exit); |
|