- 在线时间
- 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, / Z0 b: o# T! }; G! k" m: H# @
" USB ", " Mass Storage ", ! q5 V) \0 K* W$ _
US_SC_SCSI, US_PR_BULK, NULL,
. N' I( @2 \% b* q* M+ q* TUS_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE )
- L. j9 j# K' B" v9 k% _! \; ~( N2 \; T) ~% x8 g
注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。 c$ W$ K1 I2 q! \- B8 F' k+ K
最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。
8 h8 }3 G* e& O8 l. a1 j键盘飞梭支持 + d! k v+ }6 n0 ?
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 % z4 E+ S2 W8 E/ V$ ^0 ]
下面是具体看到的信息
9 r0 U: n" [! E0 [$ T; m/ g" t5 u4 y. v, w
T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 ) O& a$ F! k1 c0 n- `
B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
) [* S1 \5 a1 F7 N6 x" ?& @D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
$ v3 G! B4 B S$ FP: Vendor=0000 ProdID=0000 Rev= 0.00 q8 y( y6 k; O3 p0 d! I' N
S: Product=USB UHCI Root Hub
5 O7 k! d& h/ B: M4 BS: SerialNumber=d800
( Q+ \1 }) f' M1 d; `C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA ; N3 {; Z% {; Z
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub : @7 W/ I A1 J+ C3 r- W5 `, |
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms 6 ?' Z* c& J* D- y
T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3
' W4 f6 e' T4 m* X3 P4 R9 wD: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
$ _* G! I/ ]- PP: Vendor=07e4 ProdID=9473 Rev= 0.02 * u* b0 _+ o+ l; E; X! Z, d; g
S: Manufacturer=ALCOR
, b* V7 |) }( x0 q+ Q9 O' OS: Product=Movado USB Keyboard
/ L. t" a/ L: \" k5 IC:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
, E0 F. P) A, UI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
4 c4 V5 x6 p3 Q# Y" c( l( h8 WE: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
! x1 E# B( f# r5 ]9 {% D找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中
6 A2 ^, ], V9 d3 y; W9 I ^, _- s2 x3 R1 m2 @8 N7 |7 T- x: U7 A0 R
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
; s8 \/ V3 T. {2 m% L6 \usb_kbd_irq, kbd, endpoint->bInterval);
; c+ f \( _2 n1 j! \
! `3 k$ O9 {% q1 d$ \一句中实现。
* f8 j h$ s% Z4 b% w从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。
3 C6 a/ ?* A7 Q7 a8 c/ ?在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。
1 A6 G+ ]; a) W( b. y% U' _程序见附录1:键盘飞梭驱动。
7 k! e4 L/ N( h f+ M f0 V2 _使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。 / H- s& J' p# E2 p
参考资料
+ R7 h7 Y+ J0 Y* s1. 《LINUX设备驱动程序》 * {9 q0 E0 W9 C
ALESSANDRO RUBINI著
# T; `. v& r% I. d3 oLISOLEG 译
5 u- Y: _9 L* M8 X- }% V! g2. 《Linux系统分析与高级编程技术》 : S: x6 h, @' |$ |7 x" O
周巍松 编著 1 M$ N" ? W% v+ e# t- ]! Z5 ^, m
3. Linux Kernel-2.4.20源码和文档说明 # J7 y" `! a" n$ v o
附录1:键盘飞梭驱动 ) u5 N( Y6 {+ q; q
% t1 x# @% `# y+ u; D+ Q
#include <linux/kernel.h> * @, O8 q7 k5 X4 l6 y" g' `
#include <linux/slab.h> & y" o1 i* j3 R/ I; [
#include <linux/module.h>
) q% r9 S9 s# l8 W& P4 S#include <linux/input.h> + _! [7 o1 M& @- l* A5 ?' I1 T# X
#include <linux/init.h>
4 ^3 B+ n, _. f) e) l#include <linux/usb.h> + y* L6 L# T0 z! k |# p
#include <linux/kbd_ll.h>
# r3 i7 ~4 }: {) K8 j" c" X/ ?1 q
/*
$ b! T J! |6 q2 \. d' F) O: t1 r * Version Information 9 @$ i! K$ _2 t& v; D6 }! y
*/
8 Y# `3 f7 f( K! Y$ i#define DRIVER_VERSION ""
/ v9 _! `+ m8 e#define DRIVER_AUTHOR "TGE HOTKEY "
2 S& R7 Y; C% r6 Z" [7 v/ M( D( B#define DRIVER_DESC "USB HID Tge hotkey driver"
) Y7 q+ k& I+ S1 ~$ m& T, a5 b- B* {2 ~; g4 J
#define USB_HOTKEY_VENDOR_ID 0x07e4 % X1 l6 }4 E* w5 a8 ?( R2 a+ L+ o
#define USB_HOTKEY_PRODUCT_ID 0x9473
+ ^& {+ W3 e+ q( o# S- X" c$ o//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值 3 q5 X4 [ c% |. ~. o. w. F
: L: L! q4 I- c% j7 y Y0 KMODULE_AUTHOR( DRIVER_AUTHOR );
, U" n4 W4 J; H4 ]MODULE_DESCRIPTION( DRIVER_DESC );
0 m/ W- h- Y4 J
$ O1 i$ E2 H# Y0 L# j7 r% G6 Zstruct usb_kbd { , s1 L; {3 L* ~1 x
struct input_dev dev; 9 n! z1 Q2 f; s& O9 E
struct usb_device *usbdev;
1 K# @( N" z7 r; F. d6 Dunsigned char new[8];
( `& o7 ^: u, S& p3 c3 o9 v0 w" Aunsigned char old[8]; & W3 Q6 B- l6 W5 Y/ z; i# G Z: a2 t8 t
struct urb irq, led;
! ^' u) i @' Z, s, ~% S// devrequest dr;
7 y. [; w" a7 H0 t: ?4 q7 Y9 y//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
( F* @) b8 |3 Y# ]$ m }6 t$ ] o struct usb_ctrlrequest dr;
; I3 s! m8 o, Q, Y2 B; @unsigned char leds, newleds;
0 c7 i8 _: w! t+ I- h ]# s1 Jchar name[128];
; V- a4 d+ L B1 I/ F. @int open; 8 z8 X% t9 }5 l. Y; b: o0 ~
}; / W& e# P4 w. q# H# d, r2 S
//此结构来自内核中drivers/usb/usbkbd..c 4 X; Z! A/ i% { a+ e
6 z0 ^( U- f4 B
static void usb_kbd_irq(struct urb *urb)
% Q+ w; }9 E* x5 W{ - f# j: S( Y/ T6 O4 L
struct usb_kbd *kbd = urb->context; 4 K, F0 Q$ k- i! _6 C( K
int *new;
# d6 f2 n- B& N new = (int *) kbd->new;
9 t! B) C/ ]( n7 F
+ J3 ^: `* y3 W F3 g; Gif(kbd->new[0] == (char)0x01) * \0 s I* e% {
{
. s1 ^: u! ]/ m1 N- f$ {( gif(((kbd->new[1]>>4)&0x0f)!=0x7)
+ |7 v" M9 e1 Y: J{ * i. d5 ] T3 u7 p* u6 Y
handle_scancode(0xe0,1);
, z- |. A" S8 D& f# M: `' E* Ehandle_scancode(0x4b,1); " z) g2 [& c) i/ z+ H, a- |) y
handle_scancode(0xe0,0);
) I3 `" e: F/ Z/ ]# w& C handle_scancode(0x4b,0); ( n: z& D% T. ~# [
}
" j" G. i5 c* g$ H& K; celse 9 z! ?( D6 }2 o7 `1 G1 r5 c& m0 X
{ 6 j6 x7 J8 A; N4 ^* S% _
handle_scancode(0xe0,1);
. g9 P7 L# E& ~7 _: o handle_scancode(0x4d,1); / Z! y9 X- r1 u
handle_scancode(0xe0,0); 9 E6 o$ p* E+ W0 I
handle_scancode(0x4d,0);
7 Q. F. z4 s$ V$ C: I7 ?} - G5 ]- F; g% ?0 ]
} - a0 f. a) z$ n) C) w0 C
" z/ T* i3 U; l8 z, Q. O' W$ [( W* u" w6 r6 n9 O( M1 a
printk("new=%x %x %x %x %x %x %x %x",
( B$ [* ]& \* X& k& u0 W* Bkbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], + C5 G2 [7 ]) p' x
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
/ R% |9 R/ l7 B) B+ o7 ~' E: n* t
) Y4 C8 T" w& Y' d( z$ ~/ D}
) Y) p! ]) g( h7 h/ e8 n
! y" X7 R, g6 m! m. F+ H9 {# vstatic void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
. d1 s2 ^7 C, E7 c( _# a( h6 x const struct usb_device_id *id)
+ Q7 x# ]) h% N2 s{ # D% W9 ] S/ T1 X& W
struct usb_interface *iface;
; B- }- M6 e0 k5 c struct usb_interface_descriptor *interface; . t, a7 v# F, Q- F. N
struct usb_endpoint_descriptor *endpoint;
/ q5 Q8 Y6 i& K4 F( ? T struct usb_kbd *kbd;
% T- c+ F) n: @. \. n int pipe, maxp;
5 n/ ]0 F, p2 c! [7 U# P o' ?5 B( ?3 _" [; `
iface = &dev->actconfig->interface[ifnum];
) s" r4 r# c) P6 ~( P8 Q: } interface = &iface->altsetting[iface->act_altsetting];
/ c1 R1 H b* z. ~ v. }+ H5 a; b! E( g& z. ~
if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) ||
7 [( ?1 c! F) j0 j1 m; r(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || 5 ?1 e; @9 l) }3 H% Q# |% A4 p
(ifnum != 1))
2 ]" p- g& g( I( t+ B$ F% S{ 9 Q) D+ D% d# E- X5 p' D' t; q
return NULL; " T, e. z# c+ R
} ; j; T% ~- H0 r( B* W# c' n
if (dev->actconfig->bNumInterfaces != 2) " l2 s7 M& x! h9 @, [7 J) \8 |/ N/ @
{ 0 [9 Q2 x. [$ `7 b% N
return NULL;
- l0 O: q: ^) ~- s( T1 l} # S3 _4 {7 g6 v
7 E' g( y- U K/ G4 {) K3 ` r
if (interface->bNumEndpoints != 1) return NULL;
E" U4 C0 V1 P; z, T8 w: D2 t: U; i5 k+ [4 {
endpoint = interface->endpoint + 0; 5 ?9 q9 R9 _. @( o1 N5 f
! g' H8 q* O' e5 `4 p
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
@/ k! I/ N: y3 d+ x maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
g, ?+ f) L, z4 Q' K. c0 M4 S
: u1 U) Z8 K% W- U7 T usb_set_protocol(dev, interface->bInterfaceNumber, 0); + S" g" L, J) ^/ c
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); 0 {( X: g# U1 c5 [3 K+ Q
7 i* [+ _, g; a% ]/ _" l( C
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
6 y5 o. }- Q1 W) g/ qdev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); 1 h7 v7 y6 ?, R0 ?4 W
5 g( }! Q7 h; Q% h' U! j7 x, H! j if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
+ N5 e' L) N/ O' `0 }- c- { memset(kbd, 0, sizeof(struct usb_kbd)); / K; P. n8 V( @7 a) K9 ]. [% h
5 m5 x3 c5 g6 d* q/ m7 E kbd->usbdev = dev; 8 l( T- K1 f$ K- M$ J6 g! x6 B
; @) n# U! ~3 A) s* W+ M9 U FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
p0 \9 G$ j0 X3 t+ O0 nusb_kbd_irq, kbd, endpoint->bInterval);
2 e7 Z! _; c/ O" e0 T
+ a6 |6 ?$ E9 R/ Gkbd->irq.dev = kbd->usbdev;
- v7 L* \2 y( ]( n! d4 ?+ y
; k$ [5 Q+ Z0 e) K! [! q Xif (dev->descriptor.iManufacturer)
$ b3 @: W+ e* |* @ usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63); ' T/ f% J0 ? E. y8 f" A; p: X
, z3 p* T: o" q# C o' ?if (usb_submit_urb(&kbd->irq)) { # q/ }5 ^9 P u9 X
kfree(kbd); ' g2 p/ K0 n( f) e. j3 f
return NULL;
; K! v4 j% \0 a7 M! ] }
# x6 K. Y$ k' u: F$ l, n; B
( Q- q8 r$ B+ F$ g' G: J3 Y# f! iprintk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", # Y) Y. Y# h3 Y3 u% Y
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); % F# z% P2 s8 |) Q8 y; ~: Q
1 z7 E7 U3 }% _7 _8 Q' ~0 K
return kbd; % o! b9 [' p0 ]- O* [( {% E
} 4 e6 F, B2 z% }4 O( d
1 }6 @, Z; Q v/ v% Y3 C, d2 l
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
* p0 \% F3 s- h, ]6 A' t; i3 ]" P{
! G) Y0 X: `: Q6 m5 O9 }0 L% Istruct usb_kbd *kbd = ptr; 0 h) D/ b% z- t+ i$ I6 l
usb_unlink_urb(&kbd->irq); " N* h3 Y$ M- o5 H6 s* O. ~
kfree(kbd);
* G. ~3 C7 _3 n/ S8 H, P: ^
4 F) R+ {3 }, q" f! z- r} & _8 L- N& D H0 X
2 F8 Q* J% G' H! B$ G6 L( }static struct usb_device_id usb_kbd_id_table [] = { 3 o) S5 X* d/ i9 o. Q( C
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) },
; |9 e" P# U5 R( }; \1 L: `{ } /* Terminating entry */ # m3 |9 O! ^ @
};
: b, F$ Q7 j. H3 v0 j5 M( \* @2 O4 @! r8 o
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
, ~5 ]4 S4 _5 T% M2 w: Z7 P1 p* K+ k. A7 ^
static struct usb_driver usb_kbd_driver = {
# W8 c* N! i8 L& R2 Q0 kname: "Hotkey", 9 U5 d1 s8 u O- u' [2 D4 y0 y2 l' g
probe: usb_kbd_probe, - c4 A |* ?1 @8 V+ p( H9 `) t
disconnect: usb_kbd_disconnect, ' ]' _" z$ C4 R8 s3 c% Y
id_table: usb_kbd_id_table,
; q) q/ S& k) l0 ~5 }- ^NULL, , ]" d3 ~+ M, K* W4 x
}; % N1 ^& b) {2 U2 @
, e$ W1 U, ]- y; u/ I- s- D/ a
static int __init usb_kbd_init(void)
( J1 ^+ a5 o, q# L" N4 j& ]7 _{
0 @9 z7 S: D7 v3 l6 [usb_register(&usb_kbd_driver); 6 u; F; l9 R7 c' v0 g- w! ~
info(DRIVER_VERSION ":" DRIVER_DESC);
7 u: E$ q9 v0 g, y# `8 Creturn 0; / w% e5 {8 q6 ?# c5 L: c
}
# z) C, o: W; t1 z$ g1 l l" j1 U6 r9 C# Q" M7 U0 h+ f
static void __exit usb_kbd_exit(void) ! g5 H2 P, f: u7 f4 ], C
{
% \1 }! ^; E/ `0 b# {9 c. lusb_deregister(&usb_kbd_driver);
) k3 Q, V( v" X, _} ) S, I8 X/ G( V [+ i
6 k# Q% F7 h' r! ?+ U+ Umodule_init(usb_kbd_init); 4 e8 ?; N, A3 R0 p7 e, c& Z
module_exit(usb_kbd_exit); |
|