- 在线时间
- 63 小时
- 最后登录
- 2019-5-3
- 注册时间
- 2004-5-10
- 听众数
- 442
- 收听数
- 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, - x$ |4 O- f6 i0 O4 {3 P7 d; g9 U
" USB ", " Mass Storage ",
4 D% @' h+ |' s7 p/ yUS_SC_SCSI, US_PR_BULK, NULL, % v6 V1 X I7 B$ m! {
US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE )
; m3 n, \: G$ {) b8 L# f: t
3 p; }! ^) S7 _) Y+ o+ `: C注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。 + @$ O) s. g8 [/ F9 V) l7 s7 k
最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。
" X/ l- r* x' e& b: f! a b% p) {- V h键盘飞梭支持 1 E( d4 ~: {6 R7 w' |. H
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 ' }$ m6 `% z3 r- X- t( U' Q
下面是具体看到的信息 - f+ x. D* t" K
# j0 l) L: L6 K. e3 d
T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 C" D# Z$ M5 \! M- u
B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
2 B" w! g# t' r$ w' zD: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 ! B3 \6 p9 z w6 }: \& m" }
P: Vendor=0000 ProdID=0000 Rev= 0.00
* E9 @8 ?/ e3 N1 Z* I) j7 b. \5 }' H% jS: Product=USB UHCI Root Hub " J8 ^& X2 p5 S* j
S: SerialNumber=d800
9 h% e: x; P/ {' d4 oC:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
# S: z" e% ^; `2 bI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
3 c8 L9 \7 L; H/ tE: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
8 D0 Y5 Y) r' `6 uT: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 : c$ z* h3 R9 M" p. _5 l7 L
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 ; h0 r9 ~# A8 I( A9 `
P: Vendor=07e4 ProdID=9473 Rev= 0.02 . K3 s) {( q5 K7 A. p v T
S: Manufacturer=ALCOR 4 U+ _6 C* T1 g# o
S: Product=Movado USB Keyboard 9 N" v1 P2 `4 E2 j
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA - F- |* R: I# F# u
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub ' @3 B* r5 X( B' O' l" v
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
# a$ t. v* T6 s3 p' 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函数中
. z; y) @9 @. d4 }3 r) \2 i8 G7 d6 f% Q8 s e
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
0 {- L- \/ ?( a1 U# {8 Q% l' E# ~usb_kbd_irq, kbd, endpoint->bInterval);
( x' Y. I3 Q6 T+ i( F7 p* Q- j: V0 H* x; o$ j: A0 A$ }
一句中实现。
+ C( a: Y0 l$ Z8 ~从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。
7 R9 O6 b- q; d; J" W# K c在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。
! C, ^! N- x( |程序见附录1:键盘飞梭驱动。 8 m5 ~5 \( M) U8 S6 {
使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。 6 I5 [. V: v" W- v9 I {' j* K
参考资料 " Z: q2 i& i% i* P4 f3 @+ N9 k
1. 《LINUX设备驱动程序》 ' F% V6 v7 V1 w: Y- q, g
ALESSANDRO RUBINI著
7 r9 @. X" L# g6 P8 C& F6 h9 FLISOLEG 译
7 z6 K% c$ N+ z \) M$ ~2. 《Linux系统分析与高级编程技术》 , @4 z$ r3 x4 @' A1 W! k' j
周巍松 编著
" M6 m# V: Q; u r6 }5 d3 ^ B) g3. Linux Kernel-2.4.20源码和文档说明 0 x$ v1 H3 P6 G8 p
附录1:键盘飞梭驱动 : K" k- P. h7 V
. c5 m- L" I9 j+ p- U7 c
#include <linux/kernel.h>
8 F7 `/ f0 K) _" [& F#include <linux/slab.h> * z$ ^3 _# Z( H& [3 \* Q+ N, h' l6 s3 i
#include <linux/module.h>
5 P! {: [3 w3 G" y- r) Q#include <linux/input.h>
5 M' j& r- q. K9 ^#include <linux/init.h> ! S' a* p- B8 s: B0 g
#include <linux/usb.h>
; r3 e' y2 E+ v# y#include <linux/kbd_ll.h>
9 _# ~9 c6 K+ m; U9 @+ j5 X3 D$ a* V: i
/* 9 a0 `2 y4 ^( E4 z$ {5 ^; V; b
* Version Information R$ M3 U0 D( P5 c; B
*/
# c6 {& _( t2 V' c5 E4 Y2 _$ D#define DRIVER_VERSION "" 4 J1 I; s' |+ m" ?. B' l# S3 h: y
#define DRIVER_AUTHOR "TGE HOTKEY "
( [2 F, ]! Y+ {' D#define DRIVER_DESC "USB HID Tge hotkey driver" - L. }5 \% D- b2 u- ?4 k% ~
) P5 K3 q' ^) U: H {
#define USB_HOTKEY_VENDOR_ID 0x07e4
0 m( Z% ?% q% f! C9 b, Z#define USB_HOTKEY_PRODUCT_ID 0x9473
5 |+ @% S! G" v; K. b y//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值 $ E. g i' U' B- s
0 L# r- L( a$ F! Z. V2 R4 T- S
MODULE_AUTHOR( DRIVER_AUTHOR ); 1 d. z2 U; Z1 n& u8 |
MODULE_DESCRIPTION( DRIVER_DESC ); ( ^& G7 x: _2 ?6 L* q: y: X
, Y4 k! N6 P8 w3 T5 | ystruct usb_kbd { - U( {6 S" Y" e% C z3 K, x
struct input_dev dev;
. w5 m8 d7 U: K! l! _1 Bstruct usb_device *usbdev;
1 L1 C/ c$ P3 ^* V% q/ C+ Tunsigned char new[8]; ' p- ~% k4 r& U z! ?8 b8 N1 A" B
unsigned char old[8]; + m2 H- j O) _: M' Q
struct urb irq, led;
9 a" X& h6 I0 c// devrequest dr; & I/ D6 u7 \/ f( a! j
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
2 J8 r& q8 I, r struct usb_ctrlrequest dr;
1 h% R( u* T. @3 S" E- bunsigned char leds, newleds; ; ]; S; m) F, D) ?' C
char name[128];
2 `' }6 E9 ?( m& F) S6 @( \int open;
8 \0 {4 k- I$ I: N3 p};
) ~1 E. {0 V9 ?; g//此结构来自内核中drivers/usb/usbkbd..c
" {0 P+ U3 b8 I6 p! |1 E/ \% Z* v, a& f) c+ S2 C% s
static void usb_kbd_irq(struct urb *urb)
/ \4 E$ t; {9 x& H{ 7 {" H; r7 u& I# R
struct usb_kbd *kbd = urb->context; 1 s9 T% p4 K$ C/ M+ Z
int *new;
' f) y4 M7 n+ X, n3 w! O new = (int *) kbd->new; ! @- n! ~0 r9 r% g; l6 O/ j0 e7 V! l
! ^- j/ K6 _" V3 `" U3 Y( Xif(kbd->new[0] == (char)0x01) N6 w4 I' B3 R0 Y( c$ N
{ L; x7 \: ^% u% m5 m7 t/ F% Z2 g
if(((kbd->new[1]>>4)&0x0f)!=0x7) * W! F4 ~# ]& g& J0 Q
{
7 q: l, _4 d# s5 }( h& Qhandle_scancode(0xe0,1);
6 s+ x: ?" N. N' B/ X3 rhandle_scancode(0x4b,1); 2 I' K' O. S& x/ Q- [
handle_scancode(0xe0,0); & n; v! X7 k7 I& O
handle_scancode(0x4b,0); 8 o" R% l2 V7 t) j d+ F; h4 S
} + K$ l' Y* `( @/ a1 W2 \% ^. A
else
1 K7 d" P+ a& y7 Y5 s{
5 G- Y( g" q* K8 \2 H8 Nhandle_scancode(0xe0,1);
9 J8 a1 f, {6 X" o/ j0 ]# s handle_scancode(0x4d,1);
; f7 l$ d0 `+ e# t% [ handle_scancode(0xe0,0); - @% d. |& @: c3 U3 Q
handle_scancode(0x4d,0); & l. t; ]7 x9 _( @7 L
} : s) A" F! ?0 X* {; w; l3 O( r% I4 n
}
% S. v4 o) K. t$ n
+ U4 F D& s) L
* P# i0 s9 c* @+ y, vprintk("new=%x %x %x %x %x %x %x %x",
+ M$ F6 h; ^ _3 q$ Lkbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3],
$ R7 a$ B3 f" e3 mkbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]); " X+ f% m' ^6 U8 s4 V# Z* ~
( @; `; c. H L, X+ E}
# Z$ _; Q a- W# ~+ L6 Z1 d7 L0 Y% t8 V( B( _
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, ) p! B, n! a3 n. b" B2 z
const struct usb_device_id *id) / c- V$ { ~ l0 ~/ Z0 H
{
8 ^5 q0 D3 ?( w* N2 N# }struct usb_interface *iface; * y* D, c% T0 }0 E% g7 n7 j! \
struct usb_interface_descriptor *interface; - y% X' w' k! r& ]) [9 h9 w, S# d- V& ?
struct usb_endpoint_descriptor *endpoint; c0 Z+ w$ w! n& E8 D
struct usb_kbd *kbd; 3 b+ m! W# M7 m# k$ U, ^- P* k
int pipe, maxp;
- }2 F5 Q4 V9 u0 L- B8 ^4 \6 C+ Q+ k0 c1 |/ i. K
iface = &dev->actconfig->interface[ifnum];
- ]7 q. y7 |( v interface = &iface->altsetting[iface->act_altsetting]; , t4 I) F! F. c6 `- X! ?
. x1 C2 ^& r1 F0 Z2 ?if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || ) j- B+ O0 I& H0 ]' w, d; |6 q6 t) f
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || % o2 j6 X! ?* i. J* { w
(ifnum != 1))
* c2 ]% L, q; s- K{ + L$ Y7 _0 b; O+ i3 I/ g6 ?7 n
return NULL;
- N1 k, ~/ U: ]& a( o}
3 t( c, q; |$ ~8 j( zif (dev->actconfig->bNumInterfaces != 2)
4 X9 F6 T; C0 {; H$ k9 n$ W) i, {{
! |4 u+ z; Y) Z: t$ M `return NULL; , |2 u6 Q+ _6 W0 q( d" S/ Y- E
} " M, k, L" y+ S c' `7 I
- L s. ^2 d- u F" v h
if (interface->bNumEndpoints != 1) return NULL;
+ Y7 N' Y5 m# u7 R! N! F; Z- _7 ~8 C) K3 f( W1 q l3 K( p- s5 M
endpoint = interface->endpoint + 0;
$ i* M& S" j$ O Q: X: l+ p/ ~% G7 c% y; j+ h6 F% s
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
* b7 C3 V- p+ W' G+ I maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); ( n9 V" V/ g* a0 A. o2 E7 g
2 ?' `7 g( g1 X4 B, R3 T
usb_set_protocol(dev, interface->bInterfaceNumber, 0);
5 ?* R6 S: r8 {" g usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
i3 }6 X4 B) v1 g6 e4 D0 {. Z
5 u! y5 u8 P5 h4 b" J/ L+ T3 F! Dprintk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
- A1 `3 ^6 J7 l4 @6 o" \dev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp);
/ E4 H' v5 o. x/ f x
0 t9 ~( x, p! Y9 n m if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; $ p: j9 e" _; j% r/ T
memset(kbd, 0, sizeof(struct usb_kbd)); 3 A, N- W; K) ^' C
4 y) \( T; g+ J9 t
kbd->usbdev = dev;
3 B8 g. Y4 X- E6 y; A% `, U- s3 G% n/ f- |
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
6 a" ~/ L/ B0 T! U3 |2 d0 Z. d6 jusb_kbd_irq, kbd, endpoint->bInterval);
+ ]+ C2 W7 ?7 x: N* d) K- @* n) P2 ?2 r5 Z( ]- u* V2 c
kbd->irq.dev = kbd->usbdev; J" E- t0 C" R
$ z, z& c b. R
if (dev->descriptor.iManufacturer) 3 ~: z: F- _9 X; P: H+ }# P
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63);
( W. a8 g. k$ R
$ @; s, g \0 l8 A) sif (usb_submit_urb(&kbd->irq)) {
- f- G$ V$ y$ y$ W1 `# V kfree(kbd);
" |" U2 w8 o: q" v. y, m. G# g$ g return NULL;
* P! F! k0 v! o9 V& R& x9 S }
* |$ D; G' V- H3 A; h; e4 l+ [1 ^! M) u
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n",
* `8 |5 J" i- d! t' ~2 d. a9 x kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); & y! g4 _2 Q: C% V
! m1 K4 Q9 Y! r' R9 ]; { return kbd;
, r% q' n9 Q% l& @( h) \} " I% T5 B9 W/ X) {9 n
* X5 ~5 t2 X ?/ I* m
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
8 }& T* q& e( H' W7 N5 F/ a{ * s% Q) W* k5 n
struct usb_kbd *kbd = ptr; ; N9 q* Z6 }6 j; B7 }
usb_unlink_urb(&kbd->irq);
" A3 L6 a' V5 G# F6 I- @+ |5 | kfree(kbd);
1 J4 Y" P& E: r# T' f% W. v
6 q7 j4 q, z# O1 h0 l}
: i- \4 J: I. `' d1 b
( k6 P0 H6 [- l5 w0 Q# I! b% Sstatic struct usb_device_id usb_kbd_id_table [] = { $ f& i% A0 _( ]9 M; U
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) },
- z% S) a8 k. C; y2 J$ x- o, ? E& o{ } /* Terminating entry */ : {% Q$ Z' Z- O R% N
};
4 a" h7 |% i0 L# X. O
% J3 _6 D; s; c' RMODULE_DEVICE_TABLE (usb, usb_kbd_id_table); , s* U9 S3 i% t, \ `1 s8 k
/ A8 O: i: s+ G" v: t( K, pstatic struct usb_driver usb_kbd_driver = {
; A7 [9 c: Z0 p' N( x9 P( V: Vname: "Hotkey",
. [$ @% Z7 D; [probe: usb_kbd_probe, : U' X3 p; i r7 h6 g+ x$ l
disconnect: usb_kbd_disconnect, 9 X/ \# p0 X3 H" S( f5 G' h
id_table: usb_kbd_id_table, 5 Z9 t9 [# |! y1 @. Q$ s2 z% p
NULL,
/ n$ P5 ^* H/ L c};
! a/ |5 O8 e7 S3 Q. y+ o# \# ?9 t q& Y
static int __init usb_kbd_init(void) " _1 ?* }- k4 [5 r a: ?6 r
{ + N1 G# l; d1 A4 m9 n
usb_register(&usb_kbd_driver);
- q0 O) Q) e9 u2 [info(DRIVER_VERSION ":" DRIVER_DESC);
8 ~9 D$ e. b0 G3 ~return 0; ! G8 T% m3 j2 t& g8 t- I/ y% y
}
) O+ d1 v- O' `1 D& m/ R& v& ~1 o3 `; |4 ]3 a$ y
static void __exit usb_kbd_exit(void)
. v; _+ x5 @' Z9 f( _{
+ j, K0 \1 }: u5 L" b& Z3 Yusb_deregister(&usb_kbd_driver); 8 p3 ~5 x7 E$ a- f" w
} 2 v. E y0 b( e9 F( g
, l$ ^0 ^1 ^- H, i, c) d1 y; Z$ h* ?3 Jmodule_init(usb_kbd_init); ) ^2 G2 f3 K. d) r2 V8 C# h2 X2 I
module_exit(usb_kbd_exit); |
|