- 在线时间
- 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,
1 n2 H2 {: @+ ^/ K9 C+ D& m" USB ", " Mass Storage ",
/ Z' {/ D& k" m" M/ A, z' AUS_SC_SCSI, US_PR_BULK, NULL,
7 E! V3 _" [' x* D; b: K4 ]% {9 yUS_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE ) d5 T9 F! v& n- s5 ]1 m( I# X+ L
; f1 p7 p# C% ~2 _: o2 N
注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
8 Q# R& V2 d3 n H最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 - h, U0 ?& J3 j8 `/ m. N% p
键盘飞梭支持 1 D5 f3 Y4 O6 Z& @6 R
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 # s+ E- k7 b9 Y) ~2 E6 ?
下面是具体看到的信息 P' k$ g* U0 q$ O/ ?9 d
% s$ F q& {. D0 y1 M+ x" o; \5 yT: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
7 ~& B- v) S( b9 b @: O( wB: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0 , }( Q/ P, U J
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
" i4 a$ s( H9 S2 qP: Vendor=0000 ProdID=0000 Rev= 0.00 1 D! i( d* B. H
S: Product=USB UHCI Root Hub
4 y! v! H3 Y$ I0 F, N2 GS: SerialNumber=d800
$ B. h0 k5 r6 t( Y6 VC:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
: H$ V- b1 W# R- u5 wI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub 6 i5 V+ t5 S+ @: _/ h1 N7 v
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms ( H/ g* X! u3 J
T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 * d' T0 p- N# Q+ m; S1 J
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
0 d* E$ E' U/ u, pP: Vendor=07e4 ProdID=9473 Rev= 0.02 0 I- e" M- U$ H
S: Manufacturer=ALCOR
9 X/ w4 [/ ^0 d) A, D, X$ m' C+ ?8 qS: Product=Movado USB Keyboard
9 d+ D: X4 d- m3 s) h" d( F4 _: cC:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
5 E2 e# s4 o' ]# N$ e; o2 ]I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
( l4 H" ~/ z& M4 LE: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms 1 @7 X0 G/ G: n3 J% U1 O
找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中 + G& U& X) v0 g" p. I+ N
- ?9 ~) _ R J9 J3 L9 ~
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
/ N3 u; t! N1 wusb_kbd_irq, kbd, endpoint->bInterval); # U# W3 U9 q8 Q4 k
* X/ u4 H! P" S5 e4 O2 x( @
一句中实现。
8 T4 j1 G' s3 x; ?从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。 4 T( b u& Q9 t7 b: c, R7 v8 G
在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 $ k' o& y( v8 n6 h
程序见附录1:键盘飞梭驱动。 5 [7 A' n }5 S x
使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。
* b1 u3 K6 E$ \# g9 l参考资料 7 H. Q+ ^& J8 t! {
1. 《LINUX设备驱动程序》 ( a& S' x$ i' `
ALESSANDRO RUBINI著 ) I$ `/ x w `+ G- h1 I" m6 s
LISOLEG 译
@0 j/ B* K2 g' w! K( ?$ J' N, [! I2. 《Linux系统分析与高级编程技术》
7 R! Z) ]2 Q+ e" b# }$ r周巍松 编著 % F& e, B; V4 [, f9 `* R! k
3. Linux Kernel-2.4.20源码和文档说明
& J( B* g# u* N3 s5 j- O& ~附录1:键盘飞梭驱动 ; H8 @- Q g; Y7 W! `
" ^. x0 p1 t: U. j
#include <linux/kernel.h>
' R x7 K+ E1 _. b# e) W& X( A. c! p#include <linux/slab.h>
3 X1 r# X" E+ c3 u K. o; _9 Y3 P% E#include <linux/module.h>
/ r* J- [$ j; x& X3 W1 y1 A1 f! y#include <linux/input.h> 2 e* C0 P! d+ h
#include <linux/init.h> $ E: U& L6 I9 ?) Q) I
#include <linux/usb.h>
. x4 w. a: P5 b! x- p#include <linux/kbd_ll.h>
8 r+ Z5 \7 T; c: g. c9 K$ f( U' C1 ?! @2 m! V5 K) L
/* , \7 a. K6 M+ d" U+ c
* Version Information ; d1 x- o0 y- W7 m
*/
4 {- w- t6 y0 a% d. x3 l/ k5 m1 ?#define DRIVER_VERSION "" # y3 h& `+ D: ]
#define DRIVER_AUTHOR "TGE HOTKEY " . H/ G! I' }4 g0 K6 D# y5 ~% D
#define DRIVER_DESC "USB HID Tge hotkey driver"
1 M( U2 [2 ^9 b6 P
/ b# h3 L% P4 t#define USB_HOTKEY_VENDOR_ID 0x07e4
) ~) J/ l S& y( l+ H. `#define USB_HOTKEY_PRODUCT_ID 0x9473
- }' l2 ?% J) i$ |0 l. D3 R( ~//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
$ C" N L W5 w+ D c8 g; b6 d
6 A) T5 D. V- }- y& gMODULE_AUTHOR( DRIVER_AUTHOR ); 2 [% @" O" q7 c
MODULE_DESCRIPTION( DRIVER_DESC );
9 h; n2 Y2 [9 Z5 j0 @0 I8 f9 _% r3 c! K! m
struct usb_kbd {
2 R) b& V* @5 H W: Pstruct input_dev dev;
0 i& X* i! N6 |8 A+ N- E! Bstruct usb_device *usbdev; ! S5 T: s# Y; ?9 c" M- N
unsigned char new[8]; & d8 }0 W3 ^% E4 ?8 Y5 \. T0 |
unsigned char old[8];
4 a: q. d4 b( Y8 {$ _struct urb irq, led;
/ K1 c2 m- Y% ^( Q3 q// devrequest dr; ( i7 @* L3 m* [# ^# Y% U
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
8 e4 l+ @# J+ b0 r struct usb_ctrlrequest dr;
0 h! ]4 i+ Q- f6 v7 tunsigned char leds, newleds; 6 ^8 M5 r' T, ^& C, x
char name[128];
" I& J: F2 n4 {1 t; k5 Hint open;
/ l [7 Y7 y6 y# ^, _3 |) J}; % ~0 j" w: t" |5 `5 W- A
//此结构来自内核中drivers/usb/usbkbd..c 8 K- K- g" F% {0 B
2 q4 y6 D: a" p9 z6 t, [static void usb_kbd_irq(struct urb *urb) % r4 W% l9 F* W+ w9 I3 x
{ * N1 E1 e' s4 L8 q0 Y. p) [
struct usb_kbd *kbd = urb->context;
: o) q: U6 q; P3 Q0 m int *new;
" u) I3 b+ E9 N; P2 \ new = (int *) kbd->new;
/ b! ]' y3 B. u* p5 v# ]1 G) q5 x8 P7 k
if(kbd->new[0] == (char)0x01) . f; L5 p4 v) ]* B6 q& {
{ 7 b U$ [ W1 c; R* _: L
if(((kbd->new[1]>>4)&0x0f)!=0x7)
! P- \1 [/ C) M) N4 g7 W{
0 m3 [/ z6 N0 y6 thandle_scancode(0xe0,1); 4 C# M7 B. y0 E" ~! ~
handle_scancode(0x4b,1);
- u; p* L A/ Z2 l2 \ handle_scancode(0xe0,0); & p0 _7 [& I0 S) j5 P
handle_scancode(0x4b,0);
4 @! I0 b7 {9 [4 Y}
j) ]. j% I5 s6 Gelse
8 n0 g8 k% z) D: W+ o{ 6 Q% N' F- a! X1 g7 G
handle_scancode(0xe0,1);
t& F2 E8 B' c4 [4 l/ U handle_scancode(0x4d,1);
. b. s. M7 |3 L5 @" X) J1 f _ handle_scancode(0xe0,0); . |0 n7 q ], P0 k- }+ w& w# D
handle_scancode(0x4d,0); ' \9 q5 x% r4 N, z4 Z
} 5 m5 q* {2 d, _* Y: H
}
7 N5 p* e" p$ |/ V, W6 t6 x2 e$ i" b# t! w
( p }7 s! M# @printk("new=%x %x %x %x %x %x %x %x", " D( n* _) p1 |# u2 u% N1 Y4 o
kbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], % Y# u2 F) w$ k) j: ]
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
. x9 V) Y- w0 d& j0 E6 W6 j
2 M G' ^3 D% X& ^- b}
: ]* @. }9 i8 x3 b$ C8 C
) y3 I G5 u5 X, U& xstatic void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, ! U- U) b& y, h0 h
const struct usb_device_id *id)
& [+ [7 {6 R" T2 }* l5 C{ . u0 H! e& b: u8 ]0 c& z* d6 Y) h
struct usb_interface *iface;
W3 u |+ @0 R: _( \. N8 u5 L struct usb_interface_descriptor *interface;
- z8 ~+ H; j" O8 [; N5 [% T( Tstruct usb_endpoint_descriptor *endpoint; + c+ h1 B/ a; E3 _: c. f! U
struct usb_kbd *kbd; 9 N( p* Q3 q, h8 U
int pipe, maxp;
, @# G" N+ {) ~7 f% ], S* U+ |/ I, Z5 \5 v$ H0 H
iface = &dev->actconfig->interface[ifnum]; 2 k! Z; }, n) @5 g/ T: C
interface = &iface->altsetting[iface->act_altsetting]; / R) {% C8 q0 D6 Z$ ?
0 k a+ J9 m' l$ D1 U4 a* x# U5 sif ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || 1 r3 n; [% c% L9 w
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) ||
4 b+ M4 R8 v8 F(ifnum != 1)) 3 w' S- `7 G$ L
{ # m: ?2 a5 ?5 E! @/ X% E$ n
return NULL;
N9 X" ~/ q5 W9 [}
- o/ P6 n" q% ^" ]; Hif (dev->actconfig->bNumInterfaces != 2) % d! a4 |. T8 H: w5 y3 K
{ . W$ n+ N; q8 G& _& g
return NULL; 0 W8 s& x) _( m6 j7 ^
}
/ a2 p& Y l7 u) G& {1 U- R8 {% Q1 n+ T- Q
if (interface->bNumEndpoints != 1) return NULL;
7 v; ]& n+ c1 a6 E1 d" w5 K1 N- r Z$ n# a2 l1 ?
endpoint = interface->endpoint + 0;
0 W" M m0 [' K' L6 f4 }. Q& T6 o* v& Q( S0 @1 T: k% ?
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
! ?7 X9 [" h% ~2 X# B maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 5 u- H- C0 a1 z. o
* x+ i+ `! O# E- }6 Y2 T! b usb_set_protocol(dev, interface->bInterfaceNumber, 0); " E" w* q) R* W- Z* J; F1 t
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); 7 u% b! M y( C# C8 a$ _7 t
9 G! d; U" \ j4 ?
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n", 9 {& w) R A: {
dev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp);
+ H8 i t* ^8 n$ ^8 f( y1 [- P
) e Q. E7 J A( @: f5 c( B if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; 5 u* v& g" f N% d
memset(kbd, 0, sizeof(struct usb_kbd));
; |) d1 S! w7 H- ~" `/ q9 K$ g: C) R3 c# k' P
kbd->usbdev = dev;
) Z4 I( w N u4 q: [8 V, d; s$ p: A: ]6 `$ g7 K6 F
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
& \4 V9 N4 Y! J- iusb_kbd_irq, kbd, endpoint->bInterval); 4 v& n5 z5 q8 T
% A$ ~+ c) ^ B3 k) k# `kbd->irq.dev = kbd->usbdev;
+ |' t/ D1 Q8 _3 u) M6 Q4 L- z4 o% m
if (dev->descriptor.iManufacturer)
$ T" A" _& w, \" s+ s usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63); & H! G0 t2 ~- U& A. R+ i+ x$ e1 i
A K+ T0 t( @: K5 {' g
if (usb_submit_urb(&kbd->irq)) {
$ `/ {9 F! D& K kfree(kbd); 9 L1 }& X* Q3 p' O0 |
return NULL; " u e* K8 @# V, E
}
9 h5 i1 u( g1 o' n# A! |9 V; E k) [* \
& f9 B" y- k g/ L( e8 {. @printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n",
, f1 U- X: v8 Y2 C) d" C ?8 c* o kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
: ]7 \! Z8 p, u. I8 Q! X o+ f1 X( l% v
return kbd;
* X I7 ?, y4 r) m' V$ C} $ \1 s) P' {9 Y# _# `( x0 S
+ I: F% n; O# C* h) I6 J
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
7 ^; ]& {4 j* T% j, U{ % L8 T# J7 s% A) v: a6 @7 i2 e1 |
struct usb_kbd *kbd = ptr; * }" W/ z( B4 f' |+ s
usb_unlink_urb(&kbd->irq);
& _" n5 ~3 Y5 p& r( ` kfree(kbd);
[+ y+ Y8 U6 {: [) v( D) G" F }/ N; Q$ q$ E* ^4 m$ h* e
}
) m# h- l/ H$ {) l" c+ [) p( ], |' ~
8 v% C" o5 [1 D# Pstatic struct usb_device_id usb_kbd_id_table [] = { 2 a5 ~# s. f+ n" B3 J' e
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) },
" {, m E9 e1 H3 [, }8 d{ } /* Terminating entry */
3 S) o2 y0 A- G% K( v$ Q5 I}; + n/ X' l1 w. A
& F; u' s7 V; r |
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
. Y' k- z" W6 B" f# \$ [! Q" e. ~/ a/ Y* ]; s6 [. R
static struct usb_driver usb_kbd_driver = { 8 M* ]' J8 Y% t
name: "Hotkey",
' o, p$ p6 y/ w8 N; |8 a$ X- eprobe: usb_kbd_probe,
5 L8 L. s& q: @# |$ Vdisconnect: usb_kbd_disconnect, 8 }4 H9 D Q" ]6 S
id_table: usb_kbd_id_table,
- z$ {; v0 Q% |NULL,
, i/ o- C, ^5 w* r% e; Y/ k}; ) Y) y, m; t/ G) K$ F S/ r
+ R( H5 h" S. o _# ~/ V
static int __init usb_kbd_init(void) 0 f$ ]7 Q8 g% X+ C' _
{ # t1 Z8 }4 I. e, c y* _ R
usb_register(&usb_kbd_driver); 6 w% I+ d! U, ?* D
info(DRIVER_VERSION ":" DRIVER_DESC); ( O& W/ W/ {7 |% u5 y
return 0;
6 n0 K$ y% @0 o& ]: {} ) g, C( i9 c# t$ K' p1 n' s0 v' j
) n- E. y/ R) p$ T1 p9 J: ^
static void __exit usb_kbd_exit(void) 8 Z" N' s% Y. s: g! Z _
{ $ x" H; s- B. M7 |. U8 }3 Y
usb_deregister(&usb_kbd_driver); z! A X5 M3 r, g V
}
3 j2 I0 d$ t1 l
# p* w M! ?! w Z) qmodule_init(usb_kbd_init);
' J; w' Z6 z) X' [ k' `2 lmodule_exit(usb_kbd_exit); |
|