- 在线时间
- 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, 5 X6 x1 u. C4 T& S( Z5 X
" USB ", " Mass Storage ",
& F1 m2 F% a6 s; T$ IUS_SC_SCSI, US_PR_BULK, NULL,
2 W9 }4 [3 o' X) \' s# w" UUS_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE ) ; ]7 W' K$ I4 G# k3 f3 E2 P
! s( G9 x9 K+ @9 F
注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。 $ I* _& b" f3 B- y) _4 U& b
最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 , l [0 N w) k
键盘飞梭支持 s; n0 o9 u: `! H6 z( p+ Y
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。
# R- Q/ `6 r! `# l1 E下面是具体看到的信息 5 P$ a" m3 a% @0 B5 O
$ C( @+ ~: u+ j" ^1 P3 J/ W
T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
& n+ @" F1 S8 Y1 o2 a% NB: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
& [9 k; N y7 B' Z" ^2 L9 \D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 ! I8 t8 o2 }7 n4 j
P: Vendor=0000 ProdID=0000 Rev= 0.00 4 ~$ m0 y/ [) U8 n; @
S: Product=USB UHCI Root Hub
6 Y) _& k9 y b* A$ T7 dS: SerialNumber=d800 $ q7 B& r F( S$ h9 _" W
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
e$ M: v2 G4 r7 r+ vI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub , E0 K3 x; D1 P9 e% Y& W I
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms 2 C( s: `7 Q: D; j0 J9 a3 m' ^
T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 0 ?+ q5 e' r6 \ k& I Q
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 * {+ m1 Q ^8 M& r% k: z
P: Vendor=07e4 ProdID=9473 Rev= 0.02 6 r N3 |6 @, h: B1 T6 m6 t& k
S: Manufacturer=ALCOR
. s& c3 S6 z4 tS: Product=Movado USB Keyboard
" x, U; l9 w9 {; a! h* }( d0 wC:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA 6 \) H/ G/ F- V
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub ( [7 @9 C& { M% p f
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms $ t) K/ B: X1 F- [; T' B- f
找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中
/ k, c3 ?/ A9 T, o- T0 B$ `/ Q- J V( W9 |$ _% y/ ]. f
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
+ i" u: l8 @9 m- J: X. P' ?4 \6 Uusb_kbd_irq, kbd, endpoint->bInterval);
2 |% { j# R1 j; M+ E# _
; h2 b. k2 D: f4 A# i' e4 ~一句中实现。
# p" c6 P3 d2 Y0 p0 H2 ^3 c从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。
! Z7 ^& N: b4 M在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。
8 k5 p' e8 x: z- V: P' y程序见附录1:键盘飞梭驱动。 ' K; R) d9 `# {) Q
使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。
( [3 N* ^$ F( |参考资料 4 v4 e1 d8 b8 Z: c L
1. 《LINUX设备驱动程序》
- {5 e0 s, W+ oALESSANDRO RUBINI著 ( K. x+ b" Z D
LISOLEG 译 : i) _' e/ N8 @, x; ^
2. 《Linux系统分析与高级编程技术》 0 h4 f+ Z5 B9 `
周巍松 编著
+ Z p' N" }8 w8 b9 q5 J3. Linux Kernel-2.4.20源码和文档说明 1 E( X% q: M/ ?2 b+ z
附录1:键盘飞梭驱动
2 k& b4 s) U* u3 s# M0 C) r
4 ?* F i- V- H1 V6 l7 d2 }#include <linux/kernel.h> & P, o8 z/ v0 U9 G* Y
#include <linux/slab.h>
! D+ `4 I* K+ k, ~6 _( z. \#include <linux/module.h> 1 c' V4 ~% z/ a1 N
#include <linux/input.h> & Z+ v1 ~4 K. v2 {
#include <linux/init.h>
/ u# s' ?& ^+ \, g" k5 {# M5 k# j#include <linux/usb.h> ' C3 F' L* E4 k4 ?) l; V2 [/ q
#include <linux/kbd_ll.h> 5 y( B# U3 ~' S! H1 B6 s; |8 t
9 t2 n9 u: D# k
/* - V" @ B& X; ~: I7 G8 J7 P6 s, S
* Version Information % R8 ^- H6 X* e' K$ o
*/
f! N( q9 Q8 T9 b7 c9 Y! s#define DRIVER_VERSION "" . h/ x! M9 P+ v6 p- c Y. g
#define DRIVER_AUTHOR "TGE HOTKEY " * C% f& P6 o; P; W6 @9 m- I
#define DRIVER_DESC "USB HID Tge hotkey driver"
8 X8 k- b1 Q" u$ W5 a$ X1 d. @ q! U8 D
#define USB_HOTKEY_VENDOR_ID 0x07e4 - X& x4 Q3 g: f1 _
#define USB_HOTKEY_PRODUCT_ID 0x9473
E1 y5 A5 B, V9 |" G4 K$ e//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值 3 \4 h6 c6 K6 N, [6 I$ x3 e
" ?: F5 ~3 Z x5 `3 v& L- G
MODULE_AUTHOR( DRIVER_AUTHOR );
. j- {$ d- J5 oMODULE_DESCRIPTION( DRIVER_DESC );
' ~6 V" _/ u/ ^: `) I, j+ F3 y8 r A5 {0 G& D( D( u( _1 Y
struct usb_kbd {
% `: r7 T/ s: [" h: istruct input_dev dev;
0 F, _& ^# e/ T/ a7 @% m* H$ ~struct usb_device *usbdev;
! D1 y$ ~- j& f2 c* A. ?( x; Aunsigned char new[8]; & W, \6 i! d* a) z6 A$ |) `
unsigned char old[8];
8 ?# ?; j: d5 H% y ?! E; V* fstruct urb irq, led;
" P" q3 l: K% O: m// devrequest dr; - l) @: o0 Y$ Q, F
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
7 G* c' Q2 b! b! \ struct usb_ctrlrequest dr; * {/ @# F+ f1 N# T' L
unsigned char leds, newleds; 3 s+ }, H" n# Q0 Y( _ @0 ]
char name[128]; 8 K& ~" Z' Y& X/ d9 H6 j7 Z
int open;
?8 {3 w* Y/ l; c}; 0 O5 D2 U/ W6 h' G! U1 s4 f
//此结构来自内核中drivers/usb/usbkbd..c
# M; ^* z3 I2 Y2 Y# `; R, n3 ~3 O9 I
static void usb_kbd_irq(struct urb *urb)
& `! K# B) i1 z7 K1 W' W{ ; N6 n1 u$ w d4 @5 l, o4 A
struct usb_kbd *kbd = urb->context; * k' h" P/ T+ X+ z: D' |" {
int *new; 9 g4 U; \* ~4 d0 F) e
new = (int *) kbd->new;
7 Q8 n2 [ `: C" x& W
' W% l# `9 T( E+ m9 Nif(kbd->new[0] == (char)0x01) " s1 ~: C* m4 Q
{
+ z0 T% J2 @- t* l$ A% I$ bif(((kbd->new[1]>>4)&0x0f)!=0x7) # V( a$ H7 U$ C
{
/ x- {( E& p! x# l! P7 {0 Xhandle_scancode(0xe0,1); d0 t* [$ ?0 i- N6 y3 j
handle_scancode(0x4b,1);
8 T; h$ M4 `, { handle_scancode(0xe0,0); 0 E$ ?4 c# W6 n7 T$ z
handle_scancode(0x4b,0); 2 p; G% P6 X- f0 [" h
} ! A* ]; `" J8 B* n$ a, c1 z
else + \( v7 B$ x$ D
{
B# q& o3 g% c7 A) ^( n( F, Fhandle_scancode(0xe0,1); $ }' }$ i: p5 p. c' I# i
handle_scancode(0x4d,1);
) X) |% d; r) x- h. l: m$ J8 f handle_scancode(0xe0,0);
0 v) _0 d4 t. @' j U, \" i& v, ] handle_scancode(0x4d,0);
( L6 T8 _4 a7 |- J$ B1 r, W}
$ K* g7 f. o, t# s, X6 v6 ~} ! H9 i) z; E4 u5 @( l) ?
) o. o3 G. z3 E
+ ^& {4 }8 F1 h2 S6 D" Uprintk("new=%x %x %x %x %x %x %x %x", + u0 @ P. u4 J. c/ D
kbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], ( }0 F- K" b {) Y0 Y
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]); - c4 i' o, s% K5 C
0 ~) X" c; N& u9 |& \
} 4 ?3 r1 Z/ N* m
9 J H B2 P# V% f* Y8 t2 |; l% Istatic void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
; E& }7 r0 ^ t3 J0 z const struct usb_device_id *id) 4 w/ W! ^/ a3 B4 p2 `$ W
{ ! [9 {5 f9 O- Q* ~1 j
struct usb_interface *iface; " R ?" U d5 I. S
struct usb_interface_descriptor *interface;
G& w' B0 D4 D! Istruct usb_endpoint_descriptor *endpoint;
* I6 u$ W4 q2 D5 @# z" X struct usb_kbd *kbd;
0 x1 D5 Q2 n) y& v+ [4 g( g int pipe, maxp;
1 Q( N, x7 w+ o4 I" M8 a0 L7 [ H' q9 [
iface = &dev->actconfig->interface[ifnum];
. }+ w- `; }% q, z" q, E5 y interface = &iface->altsetting[iface->act_altsetting]; 5 b$ r& A0 q, v1 I
4 l9 L( W" ~1 v, `# V- hif ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) ||
8 Y2 a8 {4 D" r2 f(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) ||
7 a5 ^1 Y5 [) Z+ v" H$ H2 \1 {(ifnum != 1)) - O; Z+ N8 y( |8 d0 v
{ ! S4 r8 J8 [: g
return NULL;
7 o/ x' S! M( g1 @6 |: S; t) t} 4 m n6 ~* L1 H/ U
if (dev->actconfig->bNumInterfaces != 2)
* v( U h# M& B* B a{
9 f' \ c& J% [# H: Kreturn NULL; 1 J) W8 r: ` g' S) U6 E
}
5 Y7 z& p# D# f" S2 l J1 Q7 ~( `5 W/ O1 m
if (interface->bNumEndpoints != 1) return NULL;
0 t& _) S0 X/ J4 j( a; m4 I2 G& A: m. u) q( J) o" j
endpoint = interface->endpoint + 0;
8 r7 X" W/ @* D
/ d5 I7 F* F% y pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
3 A% q" S; ~% H. K5 k C- g maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
( u4 ]9 t: T. N, c3 m- Y
+ S8 W5 F8 r' \4 v# L0 X4 S7 z1 B usb_set_protocol(dev, interface->bInterfaceNumber, 0); : L5 t. C( {" ^/ Y' A
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
8 T! a m8 U/ z1 |1 F; I+ o6 q" E4 p1 s+ f
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n", 1 P& p! C+ W1 O4 X. z9 K. Q
dev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp);
1 _2 }* _! O# o/ B9 f4 W! Z1 x- h, {* Z6 D6 Z0 L, I7 |/ U
if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
3 s7 g% U5 s2 S- j2 w% }! m memset(kbd, 0, sizeof(struct usb_kbd)); 5 p! @% [% m+ [
$ q3 L: @( Z* `5 q1 A kbd->usbdev = dev;
2 O# K G3 |' d% U( Y, s( h9 C! v9 G8 Q% y2 O1 g8 x9 G
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, / R/ S5 g4 ^; o/ R5 r/ m
usb_kbd_irq, kbd, endpoint->bInterval); 5 z6 x/ k l+ b' L0 `
( p& N4 g, N0 U
kbd->irq.dev = kbd->usbdev; $ e8 h& h$ @! K7 _3 o3 e2 [3 e# Y
% T8 w/ Z; X4 z" d- c. iif (dev->descriptor.iManufacturer)
" O/ I- b4 P1 e' \ usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63); 4 o1 ~+ x% ]1 x) c7 z# h
" m" ]) d9 \! N$ {
if (usb_submit_urb(&kbd->irq)) {
; D/ L4 G# O: T9 | kfree(kbd); ; ?5 L' G3 I2 n# k4 N
return NULL; 7 R! j& P0 o2 @2 m: O
} 8 v8 E. Z8 Q, j. H+ {
5 F+ ~: k4 Y8 \6 }( r1 e4 x
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", 2 j$ C0 g& D+ g
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
- Q% L6 _1 H" u/ B
g/ d) S; P! N& j$ }. k8 U5 K6 i return kbd; ; w" F. P5 o# P' M$ z* D8 J( F
}
( v* x# q9 @! Q4 _# K! `2 I9 t% y4 |- I5 ]" B" f
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr) , p, `3 z) Y& K
{ 9 J$ j$ O+ ?1 A6 _; M: R# D
struct usb_kbd *kbd = ptr; * B k; m5 p7 T( P5 Y& J
usb_unlink_urb(&kbd->irq); ; `" v, {$ M5 ^2 P! c& k* y; W3 L
kfree(kbd);
' ^, H: M& U% `+ p- J3 P* q$ T
9 t' I$ t: @# a) S0 b' j' k} 2 E) n5 S2 U# \0 S9 U
' ?# b! m( |, x$ I8 d7 z& cstatic struct usb_device_id usb_kbd_id_table [] = {
6 @6 ]5 ^& P2 ^6 d) q2 |% M{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) },
' t" X2 ^/ j/ u( F# q, p$ M7 J{ } /* Terminating entry */ 2 E) F! d" Q. W% v1 w+ r! c
}; 1 X% H+ D% Q. z2 l
) o& v) L0 P# @6 s7 D3 ]: iMODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
( a+ w6 O0 _% i1 C' U$ `, Y/ D; {- R
static struct usb_driver usb_kbd_driver = { 8 Z4 B4 p; |9 T! T
name: "Hotkey",
" }( j% |6 F& @$ H! kprobe: usb_kbd_probe,
# T; H0 M/ B8 T0 sdisconnect: usb_kbd_disconnect,
# V% Q+ m( l( K9 t L: B( G1 kid_table: usb_kbd_id_table,
8 C: e4 `8 P9 T4 y- S- g2 HNULL, ) |+ D7 B; u1 D1 a5 l3 S/ X3 I
}; 0 q1 |. A" r; N7 \
3 o0 T6 _" q5 A, R3 {static int __init usb_kbd_init(void)
( t$ w7 E3 Z$ R& M0 T; X{ 8 c% D2 r+ y. M# d
usb_register(&usb_kbd_driver);
, `. {. w& p; O2 ]3 rinfo(DRIVER_VERSION ":" DRIVER_DESC); ) i) R( v) s/ r- m
return 0; 2 f! `& W' J$ d6 \" i: ]! d
}
6 z9 R+ R8 D* @; X1 u! s/ V* m+ w. {
) a' u5 t9 e! p% y3 _3 u6 k$ ^static void __exit usb_kbd_exit(void)
" k/ g9 m2 K0 l, f' k& Z{
4 N- L4 c3 o. Iusb_deregister(&usb_kbd_driver);
- S! D/ u+ C# r2 h}
# d# P3 h9 U r" ^. l. F6 i8 Z/ {
! l \ p8 W+ [! y% \! O6 Ymodule_init(usb_kbd_init); - A* b- x- f! f: G; \9 f0 ]1 \# B! f
module_exit(usb_kbd_exit); |
|