- 在线时间
- 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, ! N& l& I; z: G/ B- s
" USB ", " Mass Storage ",
/ P" b# d8 p+ \" fUS_SC_SCSI, US_PR_BULK, NULL,
. Z* g0 b; H# B5 f+ dUS_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE )
& o1 A0 t) B: U' h% s
( J- S& x) h+ U: u注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
. n/ [/ A2 L, i% W最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 % v8 P% M# O) Y6 S1 `$ U
键盘飞梭支持 * I8 B" I/ D; L% P, _) r; @8 I- |
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 3 t4 M/ I ^. V% ]( P
下面是具体看到的信息
I, N! |; t$ `. e0 |1 h: ]* d1 _: v3 N, q, D" j2 e9 A4 D3 ~
T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
' G6 w5 u- ~. y# U# `B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0 " m: t& B( ^3 C2 M& F3 \$ S* M
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
4 Z/ ?8 C* D IP: Vendor=0000 ProdID=0000 Rev= 0.00 ) }; Q" m. n/ L, E8 J; g
S: Product=USB UHCI Root Hub
; Q; Y/ k8 L, x" y6 @' vS: SerialNumber=d800 2 ^! ] i: C5 i- ]
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA 8 L8 q2 g; y7 r- R
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub 1 P& `' `8 `# S3 f0 p. X `) y
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms 6 v# r+ x/ J8 f& b0 H! \
T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3
9 T# _) u1 j* F& L, i( hD: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
& K% m2 ]9 r/ @P: Vendor=07e4 ProdID=9473 Rev= 0.02 - |! z3 e# k* X& o
S: Manufacturer=ALCOR
. S* `( Z0 \( ?0 ^0 Q& IS: Product=Movado USB Keyboard
; O' `3 z6 T; L& X0 ^C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
$ N" ?* b: ]3 A2 `( L( dI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub - B M+ { H' s$ r/ Q
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
9 X3 \7 h; u, f* \" ]. X+ i8 c6 V找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中
4 U/ L+ w A% ^
4 z/ M7 z9 Y" c6 t" J3 F- [6 PFILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, % E7 b6 X3 M" v3 t- p" V, p
usb_kbd_irq, kbd, endpoint->bInterval);
2 _1 s$ k2 X' i' k" x) J' m" q, F+ `3 M( h! T
一句中实现。 8 \: {- C2 w& _7 }. U3 [. W8 A/ L
从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。
5 ^9 n. n, |/ I) m在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 ) D, Q: I; p9 _( j
程序见附录1:键盘飞梭驱动。 ! q3 i: j3 I- Z
使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。 . m' z$ u0 _, t8 W( D+ m3 U
参考资料
+ y. u. h+ F+ R/ ~0 P6 A1. 《LINUX设备驱动程序》
) X( E0 C7 G) S! {1 fALESSANDRO RUBINI著
, ]) \+ ?( G$ F, l' i, dLISOLEG 译
% x% r& M4 F9 i9 @" E3 z2. 《Linux系统分析与高级编程技术》
, p. G* `3 z7 @周巍松 编著 8 y6 W$ z1 p1 D( e3 d5 z
3. Linux Kernel-2.4.20源码和文档说明 $ Y. n" e0 f$ a8 u
附录1:键盘飞梭驱动
2 d1 X Z% x3 Q. e8 v) F
' s6 t5 L* h2 l( P/ V#include <linux/kernel.h>
, R2 m& q6 G4 D! R1 E" q* K3 f#include <linux/slab.h>
& G: e1 x1 w" x# ~#include <linux/module.h>
" d0 K9 b: F# g" J6 p, l1 s. _#include <linux/input.h> * [ |0 c2 N, V/ Y
#include <linux/init.h> K$ R2 }8 u0 R! t" x% P
#include <linux/usb.h>
9 `' F7 ^% M. C#include <linux/kbd_ll.h>
& X4 S, U a3 n
9 E7 l2 o4 n F8 y/ K/* . Q# q$ I/ u/ u) I& K6 L
* Version Information / f# d# T4 a7 x( B+ I; |
*/
+ U* J) D) Y% I7 d#define DRIVER_VERSION ""
+ I" E% U" `3 f& T. c7 {#define DRIVER_AUTHOR "TGE HOTKEY " ! t1 I8 E8 K4 g1 ?, i3 ~! s. C
#define DRIVER_DESC "USB HID Tge hotkey driver"
- G# }8 c( E3 V d* T+ K' E) O/ \- q/ D( L' P) ]
#define USB_HOTKEY_VENDOR_ID 0x07e4 ; f6 c0 f* X* J( ~$ v3 e3 j% C
#define USB_HOTKEY_PRODUCT_ID 0x9473
' R% n9 j) H5 c3 M: h& J% m9 Q//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值 # _. C4 b& T) b9 \6 [
2 P2 H+ e# q' I2 L/ }3 \$ OMODULE_AUTHOR( DRIVER_AUTHOR );
! j; y7 V# C! U3 y$ sMODULE_DESCRIPTION( DRIVER_DESC );
( y: c0 G2 M4 `. g o# m1 T2 V) s+ J1 i5 h" T& d) R' p% w0 g
struct usb_kbd { % c; f) J" K X% _0 T5 T. }7 o
struct input_dev dev; % ]* B) N$ L z+ \
struct usb_device *usbdev; , S) H3 B. w4 n9 }& h. N' V
unsigned char new[8];
; X0 t4 [0 c: ^' p) K: ?. {unsigned char old[8];
' t& c* A& u/ ystruct urb irq, led; 9 M; x. t; H. |8 Q2 }0 c" `
// devrequest dr;
1 }6 i* d/ H$ {+ ?% B' o1 g//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化 ; [ B- u$ b" i+ c) K; N' U
struct usb_ctrlrequest dr;
0 n. D1 b2 I$ S( p( F' munsigned char leds, newleds;
: L& |8 S) S' wchar name[128];
3 k: T/ f# s9 `8 wint open;
) ]# B& h: T2 P9 q8 m};
8 j1 {% [3 a, Z7 A! F% s; r//此结构来自内核中drivers/usb/usbkbd..c 0 J" \- ~ b+ X0 f' R0 W( r
$ _% z! i3 e& b$ G+ Y$ z5 astatic void usb_kbd_irq(struct urb *urb) * L( I- s8 f% V/ k
{ 8 V; ?+ T }3 @
struct usb_kbd *kbd = urb->context;
3 F4 s3 l$ L; P" } int *new; $ g( \! R; r# D' @! ]% p4 z& G* u* P
new = (int *) kbd->new;
: O( c# l" b z2 ?% g3 ]2 a4 T5 f ~7 W
if(kbd->new[0] == (char)0x01)
' y5 i; d; J* k$ f7 _- q! t{ % Z; |0 d; J* O9 ?6 N+ r
if(((kbd->new[1]>>4)&0x0f)!=0x7) + p0 K6 ~3 M9 o1 D+ D3 L# s. f
{ , X2 p( r1 |- S
handle_scancode(0xe0,1);
. Z+ w3 P; b+ }" ?handle_scancode(0x4b,1);
1 s- K% z$ t& a2 S# v handle_scancode(0xe0,0);
6 D$ d1 _# z' Z+ Q" Z9 v handle_scancode(0x4b,0); 8 v! ~3 G: X" a, z3 R
}
" K" D1 F7 e% y e2 E6 R6 J5 [else
0 `7 f) E% c) R+ B& V{
- u& P& O5 [2 `% T3 ]8 Ehandle_scancode(0xe0,1); - \& \. @- o% R# n
handle_scancode(0x4d,1); # N0 p, B" o7 v5 I5 C5 a0 Y" S
handle_scancode(0xe0,0); ( j7 u0 K% u" A) N+ E6 J
handle_scancode(0x4d,0); & k7 o6 n/ t! P' H F @: _ J# q
}
8 p( G. V5 ^& X7 i- B}
& o3 s, U7 G' Z X/ [: f% S" o5 J: l
$ B+ s/ G" W) @ k
printk("new=%x %x %x %x %x %x %x %x",
6 o* s U7 B" ikbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], & M+ c5 K7 G3 a
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]); 6 f# `' z, N3 l5 ~3 m+ m
; q. m9 x8 R. f; Z' S l; [}
, |7 D1 E; Y/ O
8 j' k1 l }$ o' @static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, , S3 g- e9 N& i4 X3 ^
const struct usb_device_id *id) " F1 I' z) h* Z8 e. a, t8 j
{ 0 F7 d& `( E! Q9 B0 u+ j
struct usb_interface *iface;
5 A" j! ?% v$ {& r1 f struct usb_interface_descriptor *interface;
' a6 R' E6 o( O$ s9 l0 N* Y3 Z+ Q7 R9 cstruct usb_endpoint_descriptor *endpoint; * |& R; \, p3 W9 |/ n! |1 P
struct usb_kbd *kbd; ( N0 V y" J: [; G
int pipe, maxp;
$ C& @& M/ w# j$ z- X
. ]( W. y" G4 a G# c, Liface = &dev->actconfig->interface[ifnum]; 5 Z7 v' @0 C, E5 l2 K5 m
interface = &iface->altsetting[iface->act_altsetting]; + e8 y+ y8 {6 m; x7 o& M
% J+ _ c& p( O+ I! O# r
if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) ||
5 J O/ F# u& B1 P, t(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) ||
7 A# H2 j; ~' b7 U# r6 S: `3 j2 I(ifnum != 1)) - B9 b/ G# {0 S, t V1 T
{ ) w, w0 d3 h% Z9 b# I* f9 z
return NULL; 6 J% ]3 ~% ^4 v) N
}
# Q2 V- ~( b& m1 T( D1 Eif (dev->actconfig->bNumInterfaces != 2)
0 G; ~( J/ s% |1 d! u{ & g, e" D; x2 ~2 \7 @/ ^7 m% S
return NULL; + _' T, r6 E3 s5 g
} - u* E, {7 B1 z0 h2 C$ G
) ? ~, U) L/ S; h- _
if (interface->bNumEndpoints != 1) return NULL;
+ J t0 M# f- g9 X
* K0 J# N2 f! e# i" r) { endpoint = interface->endpoint + 0;
0 x7 ~( O4 o9 u# N" v+ i$ m1 }! p7 i. f8 s F: r
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
' O, W2 ~% j' o3 @# F/ L7 r, C- A, ~ maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
! k( ~; ~% S: A5 J$ N. K
$ _5 x# S E( u" H usb_set_protocol(dev, interface->bInterfaceNumber, 0); 5 I) `1 S# X K+ I1 O8 G" z# I
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
, k! }3 G4 y0 m; x6 J& T7 \8 @. N2 a' {8 I8 H6 x
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n", : B, e5 v2 K4 _0 u! x6 A4 T' p
dev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp);
5 `6 `( @7 z4 K- t+ |8 c. H: A/ W' u# g8 X r; j
if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
2 J! X/ D* s0 G! d' Z memset(kbd, 0, sizeof(struct usb_kbd));
3 Q9 ^ j" M- e5 G3 O$ Q g" w; M
' z0 D l# m H+ f0 ~ kbd->usbdev = dev;
" o) N2 i$ n* }; x4 W
Y/ g! S& A8 g* ` FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 7 N2 s9 q/ `8 z
usb_kbd_irq, kbd, endpoint->bInterval);
. R+ p1 ^& D, X0 h4 O ]# P7 P* P' o8 R E. w0 b4 V( y
kbd->irq.dev = kbd->usbdev; ! h2 F' _' Y& |0 O K/ ?% F
$ M, I7 r8 f5 h/ x Cif (dev->descriptor.iManufacturer) $ ]- E8 ~; K& _/ t2 V6 D
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63); 8 }8 H# G/ x1 ?/ y. M! S% X6 u
* p9 m$ E N1 s0 \& i5 n& Lif (usb_submit_urb(&kbd->irq)) {
( v& E3 V+ }: a! P' P+ |) s" I2 M kfree(kbd); 0 c! l7 r5 D5 c2 ^
return NULL;
) w6 C8 P# k7 x# d } 8 S! X2 m6 o0 p# \0 Z2 b, k2 |
3 x- J% ]( w" ^' g
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", % Z9 U* i% h0 G! Y" }
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
4 `" ]1 T, v: u2 S& b
4 L# e* B3 U; O: i0 d9 l( B! e return kbd; . M7 ~, ?5 U7 S5 H% n( s( }* R3 i
}
& V- t+ K% j; k" x
4 f0 p3 b7 v. Z6 t- istatic void usb_kbd_disconnect(struct usb_device *dev, void *ptr) ' K3 b# V$ c& }' Y: U, E
{ ( _. E. o% D) ~. [( I) |
struct usb_kbd *kbd = ptr; 5 \% p2 H0 N3 E, G+ T* T
usb_unlink_urb(&kbd->irq); . Z! [- d" c' N' C) H0 K" _/ }- U
kfree(kbd); ! W& X% R. b& m: E6 b2 e
& y- S" }- d$ }& ^, Q: F
}
2 N/ g: _6 W7 z5 j) H0 U
. A, e6 z2 F! r# I+ j$ L; ^static struct usb_device_id usb_kbd_id_table [] = {
" u1 Q( M) }( F: f n{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) },
7 [2 Z9 Z# G: a& {: o* c{ } /* Terminating entry */
/ D* H( G9 q6 B7 j}; $ q E/ X5 ?" R
9 Q" V! b0 P# _% |% x8 x( n+ ~MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
B4 Q& P: h# g0 F5 `1 B8 `: Z
?$ u6 o* t9 h3 A0 [ Qstatic struct usb_driver usb_kbd_driver = {
+ o# ^- {2 p8 v' R/ H: j8 T$ @name: "Hotkey",
/ ?# h4 M) l" N$ d7 Bprobe: usb_kbd_probe,
. q2 Y& P7 ` S& M9 v$ D, Vdisconnect: usb_kbd_disconnect, 2 h. o3 D6 K& V
id_table: usb_kbd_id_table,
7 X" z F6 H4 DNULL,
) T; u& O4 k0 ]};
/ S2 f8 A1 p H% S) e4 ~! H/ i4 ^" {! g, B
static int __init usb_kbd_init(void)
8 i1 c) I1 l# @. b% r{
$ W2 v" b7 P3 ~6 Eusb_register(&usb_kbd_driver); " `3 r7 m- m* A6 s# B
info(DRIVER_VERSION ":" DRIVER_DESC); 4 y- L+ e& q0 P
return 0;
1 U& x9 l# w8 E1 L4 m}
( {. { v2 S( i4 l$ J- W, H, A4 L) R
8 Q3 [3 ?4 H4 pstatic void __exit usb_kbd_exit(void) : g! @! m* L* @8 r( e6 {: w- W' A
{ 5 ?$ r& b1 o4 I# F: h. E
usb_deregister(&usb_kbd_driver);
' G3 b/ a4 E7 l} ) j2 j2 Y2 ?$ A7 ^
$ N/ c* R2 K0 o$ z' Nmodule_init(usb_kbd_init); ; C( ]6 x& H% H; _8 x
module_exit(usb_kbd_exit); |
|