- 在线时间
- 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,
! V! Z, m5 d4 }9 y) K" USB ", " Mass Storage ",
% |. J+ C8 y$ s2 |+ [& rUS_SC_SCSI, US_PR_BULK, NULL, & F9 ]) Y$ r8 t; P
US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE )
6 F2 H8 W1 i2 S/ }9 c. c. {3 v! }( t4 j, j' \4 W1 e; Z
注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。 6 [' ?( n. c. |* _ O* N
最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 0 N L% g( e3 r$ }% {! A/ X$ m6 W
键盘飞梭支持 4 o4 L0 o; b7 h' q3 u$ J# x) P- k' i
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。
" e# T/ U1 n% p: }9 D下面是具体看到的信息
; {& Z* J% k0 _% l H% O
" H$ z/ T0 I6 `T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 / X% M( z- h% J6 @( o+ @ q5 e
B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
+ ?- m3 V5 d% G5 }6 I" {5 E* Y4 ZD: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 ( s" k A$ c L( ~8 ]: h! Z8 R
P: Vendor=0000 ProdID=0000 Rev= 0.00 ! X6 t1 v a g9 m4 f1 t" }3 ^# L) d
S: Product=USB UHCI Root Hub
* h9 K! \& v+ ?& ^2 ES: SerialNumber=d800 + ^$ F- G; ~3 j. Y
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
6 }* Y$ |1 f. l/ a9 YI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub 6 a- H+ b2 W* F- V
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms a( f4 ^% f% ?% g( t& A
T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3
, c! X* R, p1 K; ]D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 $ ~6 B+ m$ t; f5 t: \- m
P: Vendor=07e4 ProdID=9473 Rev= 0.02
' b7 D* E. o5 Z- WS: Manufacturer=ALCOR . g5 R: z' ]5 w0 z( a; T. w
S: Product=Movado USB Keyboard / b: U+ z: \! Z. }! s1 G8 A
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA & k6 [4 p# ^/ M$ _5 i
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
; b7 I( \2 t) C g9 xE: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
0 Q: D1 s! x3 E% \" z找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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 J" c. f- q2 p1 F/ ^' c
0 h# M' R5 O' M1 kFILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, , v: C. k2 D5 N& R3 ?
usb_kbd_irq, kbd, endpoint->bInterval); ) ]% s2 T, D$ r& {, c: v/ G* c' u
8 l1 j |0 }# z6 A一句中实现。 ; v3 V9 C2 L# \4 g
从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。
( h: X' C# N. Q4 l" y3 S( t在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 5 Q; ~5 I8 C% x) O
程序见附录1:键盘飞梭驱动。
! u7 Y7 I: I B使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。 & n: S" r+ D% G0 A& j$ J- F
参考资料 6 H8 J2 I: V( @3 x
1. 《LINUX设备驱动程序》
* E3 G' m! i5 C. j" l# KALESSANDRO RUBINI著 1 P: y/ R/ U8 a3 r& F5 w# T% ^* Y
LISOLEG 译 - x/ q) P5 {! H* S3 h4 `# M9 V
2. 《Linux系统分析与高级编程技术》 z9 g3 J- u* h% I$ |: H) O
周巍松 编著 0 B$ [. z8 r5 K( X6 g- c* F
3. Linux Kernel-2.4.20源码和文档说明 0 I( H/ a) |8 J/ y! {4 [/ O
附录1:键盘飞梭驱动 1 h& \7 Q+ ]5 }* r+ j
% Y$ e/ K: T# J0 X: F#include <linux/kernel.h>
, L G7 j* A; r" }, b+ s8 c#include <linux/slab.h> 9 N; I+ R! q+ W5 _
#include <linux/module.h> 4 q; G$ H! N' u# V/ `/ T
#include <linux/input.h> ; P5 y9 u2 H% K) L
#include <linux/init.h>
s2 B% i: F# q1 u f& V#include <linux/usb.h> ! ]. {, K/ y) l; P) s3 ~, v
#include <linux/kbd_ll.h>
+ s2 ^9 k% A; Z- @) ?: a+ K
" e, G5 {. \) V1 L/*
R6 b }& s2 r" p * Version Information
$ m8 j }5 C0 v" u& a$ G */
9 ^ f0 Z8 x! A: Q+ m#define DRIVER_VERSION ""
a# {" r* k& ?( d' X. n#define DRIVER_AUTHOR "TGE HOTKEY "
# O E- }" w% y3 `#define DRIVER_DESC "USB HID Tge hotkey driver"
- G' B/ o h1 t/ ~. m) k% J* x1 r6 Y9 F3 ?
#define USB_HOTKEY_VENDOR_ID 0x07e4 4 N8 ]( U$ G* U
#define USB_HOTKEY_PRODUCT_ID 0x9473 ) u8 _# U3 ?# W* S4 ? ]/ i) N
//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
4 W) u# w C; G9 R* E$ ]6 b G' d \: V0 h+ o) ]
MODULE_AUTHOR( DRIVER_AUTHOR );
0 l! \ q+ n G8 XMODULE_DESCRIPTION( DRIVER_DESC );
( X% X, V. m- w, ]+ z2 q8 ]/ s, |( o
struct usb_kbd {
# h% |4 t1 A( P8 v; L+ k" U& s$ fstruct input_dev dev;
- L U( b \# ^struct usb_device *usbdev;
" i7 }8 h8 e1 c" ~+ Bunsigned char new[8];
5 D m' W3 `8 A4 Q. lunsigned char old[8];
0 i! O9 r- y+ m5 Cstruct urb irq, led;
9 I: e' p! z4 {( q0 M! i" Q// devrequest dr;
. [2 d8 q1 h* K9 s4 a" I; C3 ^//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
' I0 e; B6 |' y2 I struct usb_ctrlrequest dr;
- b* t$ G/ p1 v1 ^0 f+ Junsigned char leds, newleds;
! _0 n: k3 e- U1 x/ dchar name[128];
# x1 w; K6 F9 n/ |4 @' o' vint open;
! M# r4 {& Y+ o, E: Y6 `};
, v" c: M2 k+ D Y, X//此结构来自内核中drivers/usb/usbkbd..c
6 U0 D- I: v d) k1 J; _/ l( I5 [+ G" s" v
static void usb_kbd_irq(struct urb *urb) ( W5 q9 f) C; O4 ?
{
" {! T1 m$ o& _. x+ ^5 dstruct usb_kbd *kbd = urb->context;
; m! y4 w% P6 a e% R8 |' S int *new;
- M8 r" s# ]- F% m; X9 } new = (int *) kbd->new;
. g# |& L" i: {1 v4 f. k5 ]! n- S- L* Z' C& ]
if(kbd->new[0] == (char)0x01) ) L0 s) E, E. s! b. K: O
{
9 s5 ]1 v" m L hif(((kbd->new[1]>>4)&0x0f)!=0x7) . i$ L0 q) T) X, Z% r; ?& X
{
+ T' q! O" Y0 A/ A' f, q1 Chandle_scancode(0xe0,1); ) \+ b0 A3 s) {" U* Q8 |: T4 o
handle_scancode(0x4b,1); / h. l9 J; i/ J- c
handle_scancode(0xe0,0); 7 u8 {" @) O; q3 W c0 H
handle_scancode(0x4b,0);
6 I6 b: [8 w y8 V}
$ T- x: }. W: _0 Yelse
6 c3 I/ F, \5 ^' o9 E{ 4 C4 ?# v* h' D0 I% P; b
handle_scancode(0xe0,1);
6 x: x+ j# t) a handle_scancode(0x4d,1);
* U% `: j" u- x. d handle_scancode(0xe0,0); 5 ^' ~# z& j3 s. P( t: A$ z
handle_scancode(0x4d,0); 1 z8 j3 P m2 J3 \
} + [: V( k6 @9 y* n8 q s: i
} - X9 m! z$ H5 z; {* S
4 V* _+ Y; l9 X' F; t4 o6 Q% J' c! p; Y+ r1 d
printk("new=%x %x %x %x %x %x %x %x", ( u1 ~9 u# ~2 R8 ]3 p( _
kbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3],
+ c7 m) k/ Q* f# Ekbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
6 R! @- D3 Y8 a2 x4 ?9 I+ t$ }
( \- m+ S8 A2 p} # u; E4 r0 I1 V# ]7 W4 t/ {/ f( n
# r1 n& k+ {! F6 `% g$ [& H
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, . A( s( w; d, B, @8 H; b4 H: b. f6 G
const struct usb_device_id *id) # ^8 z+ ~% n7 ?9 }* G, P7 B* `
{ ! j, _* @9 e t/ A6 P9 c' l
struct usb_interface *iface;
; J" w2 Y' |2 P7 Y6 E. Y5 k7 ^ struct usb_interface_descriptor *interface;
; j' d, E8 k& |+ m$ C5 tstruct usb_endpoint_descriptor *endpoint; ) ?( j4 ]3 g2 S/ o; |( m/ r) A
struct usb_kbd *kbd; , r( F$ X: e& K$ z' W
int pipe, maxp; * I9 U/ T2 A2 L
o# [, B) j. |: ziface = &dev->actconfig->interface[ifnum]; & I' U3 @( ?5 M5 w# ~2 S0 q
interface = &iface->altsetting[iface->act_altsetting];
. T" ]# p5 [8 m7 A$ ? f7 r8 E8 r. q- N) Z
if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || ! V1 Q* m2 D& K$ a8 b: {5 [( i4 C" x( S
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || ) @& x. H9 q) _9 c6 ~& m0 l
(ifnum != 1)) # [1 |, r# @% E+ k+ f1 q4 d
{
, {+ R# r1 J9 h1 Y" Areturn NULL;
4 h# W b: h) G! r' a} 2 y! ^* Y: U2 B3 D
if (dev->actconfig->bNumInterfaces != 2)
+ C8 i& Z( v% w- L9 z2 n5 r0 H{ % I5 Q2 A" n: I1 K0 {
return NULL; 8 N8 d. h* i& m1 _
} + J) w. R$ _+ T5 J6 B2 v2 L
% T7 k; Z$ L: r' Y- k* l
if (interface->bNumEndpoints != 1) return NULL;
; a6 Q! J# X1 ?, C/ t$ {. X+ i9 M7 ]% j/ A4 Z
endpoint = interface->endpoint + 0; Z0 Q! \) x9 O$ e
; y/ N' F2 ?- L% H0 \! B7 ] pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); ; c) M/ z+ b- i% {; I
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - E4 f& q; a$ u. O- l
9 @6 P5 f ]+ P7 e2 Q% N% X usb_set_protocol(dev, interface->bInterfaceNumber, 0);
. g" E6 v7 V1 o+ _ usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); 2 f0 x& t1 @) S. i& H1 f/ A
; N1 F' F$ L, O
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n", 2 A2 m7 t$ E) {+ q* `- K4 S5 O
dev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); 9 ^8 H- D9 K& H" t& N9 ^
* F' [7 n8 y* S" p [3 { if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; / k: S$ S+ c6 L
memset(kbd, 0, sizeof(struct usb_kbd)); % g2 C5 |6 f7 j9 B1 K: @
: t* S5 P" X! D
kbd->usbdev = dev; ) I6 S1 _/ Q/ n
5 Q9 i2 S( l7 ` FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
* ]7 L8 M) {+ |8 C$ ]+ qusb_kbd_irq, kbd, endpoint->bInterval);
& `7 Q; F# A, K: `$ i: _) t5 g+ G: q+ G- e2 O+ n6 o: J* r
kbd->irq.dev = kbd->usbdev;
. R; J6 z2 D5 S! G V$ E' T7 q
, i# o' [: z6 C- J/ t6 i1 Nif (dev->descriptor.iManufacturer)
) w6 \, X, I* [" K( f) L usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63); : m( {+ J% P( O5 f! L: i
5 z/ x5 I8 C, n1 r! K6 Xif (usb_submit_urb(&kbd->irq)) { & s. a. Z5 o8 C' b
kfree(kbd);
5 i3 x' p* E J# q8 D; s return NULL; ( t" J( c8 ?/ T& G& l
}
0 Z9 o5 N" r5 e( O+ R! G' x9 M) g8 [
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n",
% o6 v' j/ k5 a4 g; E kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
! R& g( P5 O( M+ v7 j' X% g
5 J: | Z8 c1 O return kbd;
: v$ l+ `! b7 |: d5 q9 O( R}
6 |8 W9 e8 @( l* w1 _$ |% v% M$ p" K- V5 T
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
8 L6 J) C2 N1 Q- E2 P6 u1 o{ " w9 H0 w* x3 c" u, x
struct usb_kbd *kbd = ptr; " R- O1 r, k$ N
usb_unlink_urb(&kbd->irq); : `$ A) K. w# Y0 w
kfree(kbd); + S) g1 }* t1 F) j8 o9 z1 g, q
8 I: D% N% c$ O5 C% {$ `}
7 X' d( L, D9 n) c) F' T* h9 t9 V' c2 @! F
static struct usb_device_id usb_kbd_id_table [] = { * m7 ` ]* W5 ?/ b" E
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) },
, {# W; X6 K( W{ } /* Terminating entry */ . S. F g; e5 v: l2 P; f0 V
};
% t, C6 t' k. D; b' R& u% u; \7 g- P4 @' |0 F
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
; \3 u; p# ]+ z+ p) t# t$ p- `; m
static struct usb_driver usb_kbd_driver = {
' U2 ]; ~# {& sname: "Hotkey", 0 V Y0 O% T8 B6 h! k
probe: usb_kbd_probe,
$ h7 }9 h# u9 hdisconnect: usb_kbd_disconnect, 2 L8 {+ a' Z/ T% @; w" G! p
id_table: usb_kbd_id_table, " q% N2 a1 S% C+ T
NULL,
& I1 T! G6 ^+ a& I4 P0 H0 F};
' t a9 V9 n3 R
0 K. k* i, a" `5 rstatic int __init usb_kbd_init(void) * F4 R, ]: H, |5 [, f: p1 z. K
{ . t; J6 H2 L1 P. N9 K
usb_register(&usb_kbd_driver); + i* z0 r/ X1 C* Z8 l1 Q4 U/ X
info(DRIVER_VERSION ":" DRIVER_DESC);
: r* m% t( q. z7 Q4 F rreturn 0;
' b# P' p I2 [: q9 O4 a+ {} 6 Y1 k+ |1 d# W e
" s1 _' s' D' P' E: M& A9 o7 I
static void __exit usb_kbd_exit(void)
i( b. @, `: _- o( ^% s5 b5 s{ 5 G! R5 _; s2 d3 @: b D% r) H% J' S
usb_deregister(&usb_kbd_driver); 5 t& k" P! [( o! \5 q6 L _
}
- B. y3 C: t8 p
$ ~) j! X0 i) `4 L; nmodule_init(usb_kbd_init);
. P" S2 F! J0 Q, n$ Y7 Pmodule_exit(usb_kbd_exit); |
|