- 在线时间
- 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,
% w; C, p1 \7 `' f4 u" USB ", " Mass Storage ",
6 H2 a8 i) r. k3 g; WUS_SC_SCSI, US_PR_BULK, NULL,
. {5 \) U1 a4 g. B. oUS_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE ) / v! C1 h* J# G# t+ Y- F
1 u' @' P6 y( t
注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
1 y* i! }; B% p: z5 p0 n; |最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。
4 r" P$ m: E9 L6 v键盘飞梭支持 4 g3 S! P2 K; j* h! A! E N* X
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。
9 Z& ~& \- S2 \8 x8 a下面是具体看到的信息 ; g2 L O8 t& f% R: s
% C; B5 k* w0 DT: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 9 h' b& q! Y! v- [8 O( S
B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0 $ A" i3 I4 M2 V V( R9 ^
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 , }! E3 ~- T, p8 N( B
P: Vendor=0000 ProdID=0000 Rev= 0.00 $ O/ R3 a: m8 c; H
S: Product=USB UHCI Root Hub
8 B+ H. S' Z# F6 aS: SerialNumber=d800
8 V o0 V1 J" Z+ PC:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA 6 ]) n3 |+ S n/ w N
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
) b- ^( ?; L+ D9 h ?E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
- e* V3 Z5 d. z9 t |: ^T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3
& e1 U5 G S3 W0 g y% lD: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
- p" Q) J# J4 R6 X1 h0 `) \- K$ KP: Vendor=07e4 ProdID=9473 Rev= 0.02 0 c; _/ C: a/ [( l
S: Manufacturer=ALCOR
2 T6 M9 f. |/ u- W6 N2 a- Y' ZS: Product=Movado USB Keyboard 8 u$ t" O# B1 Z) [3 k) {& |
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA 5 Q g1 W% R0 ?) U
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
5 `6 K' z. V9 ?- C$ \4 j* ZE: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
- j0 j" e# d( W2 ?" ~$ S找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中
( s8 C+ e9 i4 k- t4 p3 E5 _* P) k$ B1 h9 J* c: m
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, $ r5 ]; ]$ Z/ B r6 K" x" N; P
usb_kbd_irq, kbd, endpoint->bInterval);
- m# R5 U2 X/ K( H# K2 }
1 |. O t* R) I! p9 Q/ `一句中实现。 9 v5 V0 ?8 Q* N) S5 N( x
从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。
( h( m* U9 ]+ `, M6 X在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 & I5 T1 |) o E2 L7 L7 G; l* p
程序见附录1:键盘飞梭驱动。
4 L& e5 t4 \$ e7 R使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。
" X- u4 D1 B# r+ y参考资料 / c* y) S3 X) b, ~" k) n- V8 |
1. 《LINUX设备驱动程序》 6 }7 B, T) R3 C) @
ALESSANDRO RUBINI著
. r$ ]( Y: m1 g! h$ S8 ]LISOLEG 译
1 y) y$ y3 T$ Q0 ?' Z2. 《Linux系统分析与高级编程技术》 / |! o( E5 Z% h. e& M, k
周巍松 编著
2 A4 |6 |1 ?: q* a/ k$ n9 G3. Linux Kernel-2.4.20源码和文档说明
1 |1 g, Z/ Q! w( J- f! C- v附录1:键盘飞梭驱动
2 H7 p, }, P" e4 N! m; p) }1 T' g% h/ Z; B* V3 {4 M5 I! A0 i
#include <linux/kernel.h>
% h: s1 i/ a+ W, Q#include <linux/slab.h> # j5 @2 s3 f9 g6 i D; r
#include <linux/module.h>
0 S) z6 s, b' h1 D) y#include <linux/input.h> - ?, k8 j% l3 e7 c
#include <linux/init.h>
7 W7 L& @9 H- y$ p0 x#include <linux/usb.h> / G2 A; c2 H" [6 W0 {" A# b) \! D# l
#include <linux/kbd_ll.h>
/ ]3 b5 z1 s9 m0 k1 c9 O/ X- }0 G# }; Y0 w6 V
/* " l$ T' Y$ U2 g/ V
* Version Information " r. \ o8 D0 h& x( ]' i4 u
*/
* \& T- {+ u! ]0 o! R" E1 D#define DRIVER_VERSION ""
5 Z% X9 f9 |' v* u$ p: T#define DRIVER_AUTHOR "TGE HOTKEY "
0 z7 ]( Q: I, |6 C& ]9 N: a; W/ t#define DRIVER_DESC "USB HID Tge hotkey driver" * K% h1 c0 u% ]
?5 |1 F; Y4 B4 |# a7 y" v2 d& J#define USB_HOTKEY_VENDOR_ID 0x07e4
1 w6 r) w0 E- j( Y/ v4 k' D#define USB_HOTKEY_PRODUCT_ID 0x9473
7 a4 T. r, J4 e//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值 / H9 r$ o+ r2 k1 F% k: c' ]
6 g4 Y, e2 v( _0 b# AMODULE_AUTHOR( DRIVER_AUTHOR ); 1 C& W# t: J3 \4 w! r C' N
MODULE_DESCRIPTION( DRIVER_DESC ); 3 H b& u. B8 b9 J+ `2 M6 |2 Q% e
+ K+ i7 c" E: u( M8 w
struct usb_kbd { ' ~% y! T k! N9 c; ]! i
struct input_dev dev;
9 T: C, Z! R( q; C# `3 B; mstruct usb_device *usbdev;
& N! u' R3 c$ Sunsigned char new[8];
* I" D1 _1 R% v: s$ t! Zunsigned char old[8]; & P$ q% y' B' K
struct urb irq, led;
$ ?. Q. o7 S, ]1 ]* l// devrequest dr; 4 x; Q3 F- h* o4 B$ }1 K' ^
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
; a: s2 ~ ?7 I) I7 u& x: d* ^" |; j struct usb_ctrlrequest dr; ) D' A. _( E+ \/ j; W/ s3 \: G
unsigned char leds, newleds; 4 r% u7 `. l) u$ Y; X8 M
char name[128];
- j5 H) _' ?, {& \ R9 H3 w% {* }int open; ! [* E8 h7 Z) v6 q! l# t6 p
}; 9 e9 [( D2 u- \
//此结构来自内核中drivers/usb/usbkbd..c 0 k/ t. m! F) ^; c; ]& Q9 w7 L
3 S/ I2 y# j0 K6 Ystatic void usb_kbd_irq(struct urb *urb) f1 a- {! G# I& ^$ Z
{
0 J# v( x! L# s3 t1 N. B- mstruct usb_kbd *kbd = urb->context;
# t( H1 c$ R% D2 G; a& u int *new;
/ N( B$ C8 F8 t. b2 h new = (int *) kbd->new;
; n2 q: }; o" _# R# j8 J
* Q4 s/ X- v8 c2 Bif(kbd->new[0] == (char)0x01) ; g8 l# ~% l, q5 z: S- v
{
5 Q& n+ {6 w& ]4 g# [if(((kbd->new[1]>>4)&0x0f)!=0x7) : H* L+ k9 m5 n, L7 w& C
{ 6 I: z6 f, K0 C" b0 o
handle_scancode(0xe0,1);
# B& K6 k8 w0 {" t5 e+ ehandle_scancode(0x4b,1);
% Z' `5 W, D* P9 e$ Z7 |7 ]3 o M handle_scancode(0xe0,0); e$ r5 k! A- z/ d1 z) y8 Q
handle_scancode(0x4b,0);
! z7 M9 w+ Q( l3 N1 {* }, |7 Z} & H* N1 L, E* G, U1 X
else / q* Q! w, J) o- A1 j4 m
{ - a' l# `, ]9 X; J
handle_scancode(0xe0,1); ) K/ g+ L* D& F
handle_scancode(0x4d,1); + l) r- v/ |! Y" H! Z
handle_scancode(0xe0,0); * F- \+ v& j+ A% I9 \$ L( W6 R
handle_scancode(0x4d,0); , D s3 L/ D4 q- P2 g
}
8 _2 ^6 y* |+ a8 v} 8 Q1 S7 Z' s# r8 b5 B3 u% h
; U8 t0 x" H+ a
# I3 p$ o6 L9 w* h3 S# X* x
printk("new=%x %x %x %x %x %x %x %x",
5 b0 h+ I2 `2 s1 x2 N( Gkbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3],
; Z) \. V7 A0 y- l; ?$ {: Ckbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]); ' Q( A5 W# }6 {1 c1 |
0 ~7 Z- R- U* B- p
}
$ K0 H6 n0 ]2 l) M! d( C9 i7 \! n! t1 [# R+ J6 C3 t
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, # ?+ C4 \! ^, T+ j* G. ]) z3 x5 P
const struct usb_device_id *id) j# q' D6 V# H. t9 e* B, ~0 E
{ ; }9 ^& y! Q9 H% ]7 h
struct usb_interface *iface; $ p/ U( M3 a% P3 r6 Y
struct usb_interface_descriptor *interface; 1 U! a2 k7 V) h9 |' o
struct usb_endpoint_descriptor *endpoint; 9 ~ z' ]( j1 b
struct usb_kbd *kbd;
a2 ?2 p. g" l" ?- j int pipe, maxp; ) H+ I3 s/ E) b
+ w% E& h7 S, h: xiface = &dev->actconfig->interface[ifnum]; % H3 n6 D' P/ n! x0 Q1 O3 E" C
interface = &iface->altsetting[iface->act_altsetting]; 9 |5 e9 i& T! E ^! n; v" k. ~
2 \, r3 a( d0 c4 T- x
if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || / c$ o" R i E+ {2 `( D
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || 4 L( \6 I, w0 q7 [
(ifnum != 1))
: u2 R5 ]6 d5 C7 I, U3 O' i{
1 n' k5 c! Q4 M! Areturn NULL;
; ]6 I$ Q+ I& x5 |3 N' c" y}
- J" K2 h2 \* M$ R$ g) g9 g- Tif (dev->actconfig->bNumInterfaces != 2) 6 f. ]$ p- R5 q2 m5 }* D
{ 0 S. u: s0 \8 b- \# l
return NULL; " _* }+ g6 n2 r; \
}
4 Q/ r2 f# w# L: ?
- I" e$ ~6 {. Bif (interface->bNumEndpoints != 1) return NULL;
g! I0 ^* e; H; W% n
) B: t' W) b: ?# k2 l% M) G$ x1 S endpoint = interface->endpoint + 0; " p% Q" ~/ X7 T
) Z$ |! E+ z: e; x. X) U
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); 7 v+ ~7 R' E/ {( q
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+ z2 T- X# @4 o( {
8 Z9 P H6 q& ^9 z6 R7 y usb_set_protocol(dev, interface->bInterfaceNumber, 0); " _$ o$ e$ \; V, |) |
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
0 w; X: M0 a& N8 |' r9 l$ E/ \# I: W" Z3 p
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
2 I; ?( v; P/ [! idev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); " r! h, D# M) A
( V$ p8 @( p+ T! b. O if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
/ v" G6 y# k+ _! T7 ` memset(kbd, 0, sizeof(struct usb_kbd));
- r p1 [ V- `/ e% ^
; Y% [+ U+ U7 q3 n! A kbd->usbdev = dev;
* I: I0 N$ T7 B8 M* ~6 f( N
# S( \+ X* Q6 Y* }5 _% D FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 2 o# M, p2 T/ J T; F/ t! V, x
usb_kbd_irq, kbd, endpoint->bInterval); # c4 u6 a* E6 q/ n2 x# A
* R9 f: U- [" a. G" z
kbd->irq.dev = kbd->usbdev; : e5 B7 P8 Y; t
o) \" |, p$ c) iif (dev->descriptor.iManufacturer)
" }' y0 p! k! Y0 _, } G3 p( l usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63); . r# N# |: Q2 c9 C# h% @
6 t! w4 G3 _. H! f9 f' r) H$ R$ kif (usb_submit_urb(&kbd->irq)) {
" h2 j. Y" O, [4 B, B kfree(kbd); " [6 T7 p: }8 }+ i8 Y
return NULL;
5 U9 h3 j( i2 j) u. m, X; n }
/ w m. J* w s# ? V5 V3 p+ B$ @$ ~! M" r# B
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n",
+ ^( I+ x' E5 s kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); ! R! i$ e+ x5 y* D/ S
% I0 m) H5 W5 }* D. f3 ]
return kbd;
3 u# D$ @# k M2 W" j& o} , p; e; B; o- V5 B2 f5 w$ A
' O' x8 y( W6 I5 H1 p9 Dstatic void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
! _' u" | s. o7 Q{
% `4 p% x( N9 W c% _" g( ^struct usb_kbd *kbd = ptr;
7 s2 W! q" o0 ] usb_unlink_urb(&kbd->irq);
- S0 U# O5 W% h% X6 I kfree(kbd);
+ L u3 W' p2 @+ i- J( O4 p# U" W5 Q2 G P
}
$ d1 i+ i& y& J0 Z( r- z+ `4 W. {8 {$ B
static struct usb_device_id usb_kbd_id_table [] = { ; w2 F6 O3 N2 z0 V( b u: r( b
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) }, & g' }% ]' X, P+ Y+ ]; V
{ } /* Terminating entry */
9 d# ]5 V8 k/ {0 R};
6 ~' Q0 T3 [3 V5 Z( F/ u5 E7 ^( }8 _& I) F
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
- C" J# U* z" @$ ~5 R; b- b0 G# T q# p. U: O* ~
static struct usb_driver usb_kbd_driver = {
& X+ [0 p7 |3 S0 @+ X! q5 g1 Qname: "Hotkey",
, j+ k* @/ D6 ~4 O' L' Bprobe: usb_kbd_probe,
i6 M" F$ X" Y* Ydisconnect: usb_kbd_disconnect, . ?# w# F/ _% G
id_table: usb_kbd_id_table,
& ]8 C% w+ R. D; M/ |7 oNULL,
7 c) K; M, y; D3 e& ^- q t};
4 A$ E) Z* x0 ~3 X. Y
+ x' Y5 E* K5 }/ Nstatic int __init usb_kbd_init(void)
/ ^* v+ y; d5 L5 x+ B v. P{ * p5 y, v: Q) g2 I6 \- Y! S
usb_register(&usb_kbd_driver);
! z7 {* S) D6 _* F3 ~6 g$ tinfo(DRIVER_VERSION ":" DRIVER_DESC);
: a9 A8 m/ M* [+ _2 x% w/ Ireturn 0;
$ ?2 o' k# j( b5 Y}
7 }9 i3 a5 c7 F4 [; V$ r" S K: X" x( n9 ?' j2 t" z5 X
static void __exit usb_kbd_exit(void) 9 O- Y! D, T5 |) ^) ], ]
{ 0 B1 ^6 ^% z# R% C1 M6 Y9 T
usb_deregister(&usb_kbd_driver);
! Y- J8 ]- v! I7 B6 F% j$ m! z}
% [$ Y: K/ A7 S0 u; j; b, [) u: O/ m- }1 i! u& X2 w
module_init(usb_kbd_init);
0 L/ V4 V0 r8 }) |module_exit(usb_kbd_exit); |
|