- 在线时间
- 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,
% z5 ?$ e# {5 x( B) e/ I" USB ", " Mass Storage ", / x+ [% U' L& v& z c
US_SC_SCSI, US_PR_BULK, NULL,
. t, H. T6 k- }; qUS_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE ) : C' l2 w9 F8 x+ @. X
" X$ { B! O' C
注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
$ T2 U9 p# d0 ]4 }; A2 u( a最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 ( ?4 V) [4 i5 e3 c
键盘飞梭支持
6 p$ A, j1 I7 r- A0 X目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。
2 i8 G5 B/ y2 H5 l下面是具体看到的信息
7 L0 F% G7 l4 O
5 u+ v, {0 Y/ x* o8 i i2 JT: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 8 Z7 p8 P2 t9 y- x1 G3 ~* F7 C
B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
- D* K- ^# I) P, V# yD: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 6 \* c3 G' X) v# F6 N
P: Vendor=0000 ProdID=0000 Rev= 0.00 9 ~! O q$ m# i
S: Product=USB UHCI Root Hub
% ]! Z+ R# K, D1 K: o0 [1 XS: SerialNumber=d800
. G7 s& w d6 O4 U0 i' E" lC:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
8 j2 z$ o& U; x/ W6 h# HI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub . P7 p Q0 h/ b) m" t% ~9 ~8 H* F
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
$ N7 Z# _% g0 h$ `T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 3 p( w9 W: w S
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 _( S* ]* `+ v! v% L* M- k. s
P: Vendor=07e4 ProdID=9473 Rev= 0.02
8 Q7 `7 C# l. ^8 I6 X0 nS: Manufacturer=ALCOR
. ~; U+ }9 A$ e/ r5 u) yS: Product=Movado USB Keyboard - Z# [$ b5 P C! p X z
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA p" `* j2 Y$ t5 G
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub a1 l& L3 A% x6 l, q
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
( u& g* c# R3 K; p# f4 X, d% P1 k找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中
2 P& d: M6 M, o5 W; Y. |3 n( V/ a0 R- B$ I! n, z8 l
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 4 R: [* ~# ?. I8 i+ m+ ]+ v
usb_kbd_irq, kbd, endpoint->bInterval);
+ i; q8 a1 J8 H" [ |
) b) H$ t: x7 R6 ?( K7 w+ H/ y一句中实现。
( M+ M$ y# v! G' J4 |, a' r从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。 2 n3 M9 A3 k3 S V
在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。
9 O; j% I7 `- ~/ N程序见附录1:键盘飞梭驱动。
# S3 ~& W4 o4 z" H1 ~4 O- P1 C使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。 . Q4 Z; W2 j3 ?9 }2 p5 C7 @( C
参考资料 * W$ K C5 b" F- M5 y$ S' x
1. 《LINUX设备驱动程序》 / T5 t; c( S9 `( d7 n$ n2 V) L4 |
ALESSANDRO RUBINI著
: \2 p; B% Z; OLISOLEG 译 % V0 X, }; [) u- a: e
2. 《Linux系统分析与高级编程技术》
' P5 ]9 W) [% ~$ g4 x3 M+ k( J周巍松 编著
+ ]1 j, {& j/ `7 { d4 B. A3. Linux Kernel-2.4.20源码和文档说明
- H" J( H5 W% F9 m& _附录1:键盘飞梭驱动 ( D! Q1 Z# A& m" Y3 U7 q$ M2 A
: ^' i" `/ W- o: k
#include <linux/kernel.h>
: r& Z8 s) _) @5 r/ V7 O) g' `) D#include <linux/slab.h>
( ~4 S G }% [* z! w#include <linux/module.h>
* D4 T0 a& r1 Y& P* j- ~. z#include <linux/input.h> ; O$ k) L6 q& w- G7 H( ]8 G! a2 ]
#include <linux/init.h>
& Q' N. [8 N% t- x6 j#include <linux/usb.h>
9 \) m% q& u" _0 L#include <linux/kbd_ll.h> 4 j) w% J( {. h; p
/ y h! H& d5 l8 |/* % [% {, \; Y, p' J' t0 I
* Version Information
1 m8 m0 e2 \1 p3 ~6 }: f */ F5 \8 p0 Q; Z" D' Q5 R. @! z
#define DRIVER_VERSION "" % P! A y9 M0 e/ q3 c% W
#define DRIVER_AUTHOR "TGE HOTKEY " * O2 e$ @4 P$ C; Y; W# |
#define DRIVER_DESC "USB HID Tge hotkey driver"
/ k+ B/ { ^4 p z8 P
U3 I" ~7 \/ l; {1 [# l#define USB_HOTKEY_VENDOR_ID 0x07e4 8 p8 f& L, h: l5 @
#define USB_HOTKEY_PRODUCT_ID 0x9473
8 f* K% x% }5 O//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
) X5 c0 D, m& S* d+ i* N2 ]
) X9 l$ e _. x' oMODULE_AUTHOR( DRIVER_AUTHOR ); , V/ j4 o2 M. S1 M
MODULE_DESCRIPTION( DRIVER_DESC ); " D( o5 M3 T2 e
' c! r) Q4 o1 i1 mstruct usb_kbd {
/ S6 |7 E; L' u, P) X9 ystruct input_dev dev;
; h$ Q7 l/ E3 ^6 y& f; |struct usb_device *usbdev; 2 I1 {! Q* ^7 z
unsigned char new[8];
; N3 o( Q. P+ t. i3 |" p- ]unsigned char old[8];
' j/ a) S* u- \1 Y( Wstruct urb irq, led;
: E$ j1 a% a/ Y1 W- r// devrequest dr;
9 D+ D5 J0 W& S//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
0 P/ h+ d6 E9 r& q$ k4 I struct usb_ctrlrequest dr;
r) R6 m% Q( s! A2 Junsigned char leds, newleds;
9 R( v) e' w% \2 D R% j9 }char name[128];
5 P, i0 F5 |$ F: Xint open;
" k4 X: z1 d) z6 _$ q5 S};
: R0 y1 R2 i7 y. E# k8 ?8 w//此结构来自内核中drivers/usb/usbkbd..c @5 y. d3 u9 I+ w ~6 |. ]
1 u* c) l) j, P. c- Qstatic void usb_kbd_irq(struct urb *urb)
) N Q, |& t6 w- x( K{
: f. i% d6 Y% U4 astruct usb_kbd *kbd = urb->context; , }, R4 i8 ?; u# Y3 K4 N J
int *new;
* u$ ]2 {6 T: k8 s new = (int *) kbd->new; k+ m' ]9 }* i9 X/ B4 T6 P1 m9 F
8 S# y/ m: q% ^7 s+ Dif(kbd->new[0] == (char)0x01)
3 q: r* G: o' U. p{
+ ^" f8 I: |5 Cif(((kbd->new[1]>>4)&0x0f)!=0x7)
1 [* O3 H4 r& B{
; v7 ?7 W0 A7 D$ I! l: T; I) y! [handle_scancode(0xe0,1); 7 ~4 |+ @" e) x( B- X* V- f4 ]( r
handle_scancode(0x4b,1); d: d3 ~! A$ |4 t9 X b
handle_scancode(0xe0,0); , k4 d [# n8 u8 ^$ n
handle_scancode(0x4b,0);
9 \" b( I+ z+ C; i4 h) u8 k} 5 R+ y; l6 j8 u6 K) L! K
else
$ P1 C$ q" D5 A) y{ 8 X* W& A4 c& A% j
handle_scancode(0xe0,1);
* V, q6 {! t1 t9 o handle_scancode(0x4d,1);
+ m# |" s& w) u5 N) a handle_scancode(0xe0,0);
1 C) W' K# [. m6 H handle_scancode(0x4d,0); 3 b( D8 P9 `* l% |2 Q3 o
} : c7 z/ B$ X. O! d5 Z# ^
} * M5 K, k8 K# S2 j4 T6 d
/ U- |1 ^1 M+ A+ T" _1 D7 o
- N+ G8 d& e6 q0 j' `printk("new=%x %x %x %x %x %x %x %x", " R0 l5 |7 k$ `3 Z! i0 @
kbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3],
- y9 U: b6 O/ H+ ckbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
# l, N0 |% b0 B4 H4 k' n6 c/ U5 M) y* a3 }* `3 l6 I- T
}
/ T: Z2 V0 O* D( l8 \! j
1 N5 B* w) j; k8 l6 M4 |static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, # M$ L; Z' D9 b7 E) f6 W
const struct usb_device_id *id)
, A2 b; i/ u- r4 x6 P8 K- }{
- @7 ~5 H& W5 V' H$ o# astruct usb_interface *iface;
3 a* j! c$ q7 q" L9 g# f2 u# c struct usb_interface_descriptor *interface; 1 @! `0 E! g- w+ M
struct usb_endpoint_descriptor *endpoint; 4 S& c4 e( `0 ]% o6 {- {+ I
struct usb_kbd *kbd;
8 y7 B5 P' U2 [9 H- g3 p int pipe, maxp;
0 j6 g% o$ d* P0 e8 {
% r! F! S6 O7 s! W1 b* F* Siface = &dev->actconfig->interface[ifnum]; ) `: P: Y! W7 {7 D5 w7 n4 Q6 V- K
interface = &iface->altsetting[iface->act_altsetting];
! e! `& `8 j/ j8 E6 R$ P/ Q6 M6 D
8 `- `5 [! K; E( }7 g! nif ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) ||
! M2 b, f H9 a3 T% ?(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) ||
) r5 _% n5 ] N" {(ifnum != 1))
0 I+ E5 A$ Y: C5 S1 h' ^3 u8 W{
! c- X h& q0 Y* }, _( ~! I! R% Areturn NULL; 4 r( |# i) o' Q, A
} ) @& u& X) n5 \. o# t; t
if (dev->actconfig->bNumInterfaces != 2) ; h) D' t! I# D
{ r+ n& Y) t6 D7 |
return NULL;
$ c% o: t2 X T/ l} 6 q+ _* k( L' i2 t, z0 c) n
7 u6 t8 n1 q" M+ O$ mif (interface->bNumEndpoints != 1) return NULL;
. k" \" n+ u1 b$ X- F. W9 S6 w# L5 Z) Y- q( U5 U7 P
endpoint = interface->endpoint + 0; C; q; \; x. l. {5 G* k
/ E7 I* g, P( `8 O! u- c pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); ' {, ^( r) r, H# ^' T
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + O# K6 U: l1 f/ A8 z0 p, ~7 l7 J
2 f. F2 k/ [9 S usb_set_protocol(dev, interface->bInterfaceNumber, 0); # ?( w1 r$ u1 h) X4 g
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
6 M, F. q/ a R4 ~ x7 T# _% v& C
/ r! n# f3 S+ E, \printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
! A. b8 i& A' }( i. J( _dev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); ) V9 t+ p v5 V1 F
9 ~! y4 k; }' _1 y' w if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
% u* X) q- {: i2 v memset(kbd, 0, sizeof(struct usb_kbd)); 9 E6 N6 ~' _' C+ l$ r2 x) a
/ U$ q3 X, J" \0 ^* y. ^5 l kbd->usbdev = dev; 3 w/ ]$ e5 Z7 K* [. q) S
. A( }0 D) ~, G$ ]( ]/ k) x FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
5 h7 h0 F) z8 Zusb_kbd_irq, kbd, endpoint->bInterval); ) P8 {; p7 R) \! [1 P
( E% Z) j8 y7 G) i( ^kbd->irq.dev = kbd->usbdev;
0 g2 [+ u% [0 d- n& G$ v/ g# Y- u" C L( Q$ T( M% o7 ^
if (dev->descriptor.iManufacturer) & i& v* Q; K1 l# l5 _! t( }& P2 w* C
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63);
2 j) H- Y" \9 R3 O: ?+ i( D% f
2 N$ y1 r/ k$ R1 Y. K Vif (usb_submit_urb(&kbd->irq)) {
9 f* J9 ]! i8 ? kfree(kbd);
3 r) f' q) t) O return NULL; , G( ?" ^ G* L6 u& Z; c$ k3 i
} $ v' P7 ~! s4 x0 R
v7 S4 _" \# {9 Y9 F! O D0 ~9 L) `0 |printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n",
6 k" i! Y4 Q" c9 N! b kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); 9 ?6 w5 ~1 p- g# J
2 e- x2 }/ X( S, b) Z% a2 ? return kbd; ' G) ?# i& [) L. ~6 M
}
- k/ S/ k" }$ t8 x( h7 s' `2 ?
* W" V' h" @& l F, ~1 R5 N' Y! _0 Zstatic void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
! R4 C x% Z0 b8 _2 h( ^{ % \$ j H9 w8 o! J0 F u6 A
struct usb_kbd *kbd = ptr; ) z7 c: l, }, R {: u! g/ }
usb_unlink_urb(&kbd->irq); # L' X5 c% ?% W3 O" k. r9 E
kfree(kbd);
# r! W+ g9 }6 c7 @9 B2 r9 V( W* K+ x" c b% W
} " b& d, b9 u B p: H
( {$ T' S; U/ m; c4 t. A) e
static struct usb_device_id usb_kbd_id_table [] = { $ _7 W, E/ g6 x
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) },
: v/ ^9 {1 H5 @, S9 O. {0 c* G{ } /* Terminating entry */ , u( u) g( z2 W; m. _8 N
}; 3 ^& |0 ~" ^& m( q; x6 G
% O9 g+ G) g4 D. Z. p9 a- x. OMODULE_DEVICE_TABLE (usb, usb_kbd_id_table); ( S5 d% h; C2 l& S2 X4 R
$ s! ]4 Z# Y( u7 X0 m1 T1 }* \- Y
static struct usb_driver usb_kbd_driver = {
$ c4 D6 t4 h0 P! H7 G' Uname: "Hotkey",
! k8 ]+ m. G( Y L- {7 [4 q! V/ Q0 Hprobe: usb_kbd_probe,
- V. A9 y0 \4 _0 N3 m; A' Udisconnect: usb_kbd_disconnect, 2 C: w4 ~. `% Z1 G7 o
id_table: usb_kbd_id_table, 0 g0 A [/ j; J R2 G! p
NULL,
6 h7 [$ ]6 h7 R, y7 r3 ]/ K: ]5 G2 J};
2 R0 Q! o0 x% K+ H- p- |
- k! G* s( y$ kstatic int __init usb_kbd_init(void) ' r# p( p1 H* t9 s2 ?& u$ Y; Q& ]
{ . Q2 R& y4 G' b% d) I. h1 l
usb_register(&usb_kbd_driver);
" x" A" U# N( ^* @4 ninfo(DRIVER_VERSION ":" DRIVER_DESC);
4 ]) E0 A$ ~% k+ |) |. x kreturn 0; ! m' a4 ]$ w; t I
}
! u3 u, J1 }9 ]' S3 D% f4 P, ]' [, k
: M ]3 o# W5 {/ D" ~4 o: tstatic void __exit usb_kbd_exit(void) ) O6 U/ a: b: i3 |$ N1 g7 P& j
{ ! E( {) T' j2 z
usb_deregister(&usb_kbd_driver); 7 P6 y6 j* o7 {* @8 g, n
} 6 l+ c/ n, n$ H8 { H t6 P* [1 b
" T3 F0 ?& N; ]4 R- A! B* I0 H
module_init(usb_kbd_init); - [3 {0 h. t$ k5 |. [8 t
module_exit(usb_kbd_exit); |
|