- 在线时间
- 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,
( V. l7 j6 w! ~! c0 K" USB ", " Mass Storage ",
8 J* ^# b0 b' I4 ~ R* U: j: mUS_SC_SCSI, US_PR_BULK, NULL, 1 L, A/ g: _7 R& u+ V2 X
US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE )
& Y. V. p% Y% w: C6 K6 O5 `) ?1 R: r8 ?
注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。 + i2 T! e! @- N
最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。
: E, ^* s( R/ i) `9 E) _$ i6 n键盘飞梭支持 ' m6 V! p3 d, F4 n6 Q
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 5 ]9 o( b2 _8 x) i" D
下面是具体看到的信息 5 {/ ^; b, m: q$ B
# P$ S$ w/ m$ @% ?% z: cT: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 / v' g) W; N# T( W
B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
" _1 S1 Z9 @% ZD: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 , K$ r3 H9 ^; [1 C m5 ]+ h8 Q8 `
P: Vendor=0000 ProdID=0000 Rev= 0.00
# S$ E q; L8 Q% v' R# ?- o% KS: Product=USB UHCI Root Hub
8 h8 A; T8 G, J: l! BS: SerialNumber=d800 7 E9 j& Z w" A1 ]: W* u$ V# z
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA # T: c& m' u* c" {: h1 c
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub + ^' W" s5 C9 y d: o @
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms 2 Y6 `# R5 K& ?6 f( P _
T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 2 L4 R. \9 l: t/ E5 C
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 9 n8 r4 G- W7 d( `9 y& t o
P: Vendor=07e4 ProdID=9473 Rev= 0.02
9 V) f9 m7 E$ E" Q" {8 l* KS: Manufacturer=ALCOR
/ D: E- y& S) YS: Product=Movado USB Keyboard
\6 J1 d$ [# }2 v% I. ?C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA , q5 r& z6 l3 J& Q. j2 D* M
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
! n, A0 _4 [3 R# Y9 OE: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms o3 g- c! ?) [6 `9 M3 E
找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中 ) {! h& J* C/ k2 H1 K9 Q
( T( _ U* v2 Y( E0 F9 z$ o& \5 ~0 M
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 0 I8 @! g% {; Q! Q1 V: h) {9 T
usb_kbd_irq, kbd, endpoint->bInterval);
6 ^* B- r, ~& k0 N7 q5 F
7 A. c' M' K: ~+ s; S5 g一句中实现。
' a5 p5 S, m) a2 ?$ w) b从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。 2 K& y6 f" G2 l9 [% s- n
在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 * a. j a. O1 \: ] J
程序见附录1:键盘飞梭驱动。
( k) z6 a0 H" E# P; ]! ?使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。
% r3 S: |) R% S: @参考资料
2 G- f: J, Z) Z3 n4 C" D% h1. 《LINUX设备驱动程序》 ) x0 F8 l; p2 ^) L3 M3 W, n
ALESSANDRO RUBINI著 : S0 @& P' d" p N3 E. ^7 O
LISOLEG 译 : w a/ k; H( O" F" d) S3 D
2. 《Linux系统分析与高级编程技术》
3 T! M3 I2 s4 w. t9 R' F* D周巍松 编著 ' c6 ~: b9 K9 ~% d+ A6 p) h5 S
3. Linux Kernel-2.4.20源码和文档说明 ) \* c) H1 a5 Y4 w2 ?8 L0 p: e
附录1:键盘飞梭驱动 Y& e3 l% ?$ a5 c6 Q' c9 N$ ?
# A9 s5 |9 t, v0 T' n: b
#include <linux/kernel.h>
" s$ n! q) [3 d: g' {$ F" v#include <linux/slab.h>
9 N' ]; H) D( G7 i5 N#include <linux/module.h>
0 m4 B" {) Z: E( v/ t2 B9 w8 c8 z#include <linux/input.h>
1 j+ h' ?, A3 \! b#include <linux/init.h> ! z; ~$ Y( K' R* t5 p
#include <linux/usb.h>
8 a2 r6 J# l9 o( U4 ]#include <linux/kbd_ll.h> - c" g; Q! k4 S3 H' q' t# |5 i
: \0 w; l" Y8 u6 P0 M/*
- U) A- K7 G9 ^9 {9 j * Version Information * u& p" {& ~7 _
*/
7 a. m5 ~: `+ t c9 e/ S#define DRIVER_VERSION ""
* a6 _. t$ w( h; Y$ G#define DRIVER_AUTHOR "TGE HOTKEY " 6 ]9 Q) ^& X) w5 J: F( T
#define DRIVER_DESC "USB HID Tge hotkey driver"
' x5 Q4 ^$ a" {& h; @! q. N6 I( Y7 C: w5 V
#define USB_HOTKEY_VENDOR_ID 0x07e4
7 S: M3 b( D3 Y#define USB_HOTKEY_PRODUCT_ID 0x9473 ' x4 E" S" t. v( \+ ]5 O' t3 C
//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值 - A; T; \) A0 a) `1 J2 C7 R
1 Z# O6 ~2 z; n* g) T+ _% p5 HMODULE_AUTHOR( DRIVER_AUTHOR );
8 e$ W6 o* ~0 Y( iMODULE_DESCRIPTION( DRIVER_DESC ); 5 A0 K! K7 M' Q7 `7 t
- b N2 Q& |" {5 M% Gstruct usb_kbd {
( }% m4 ?$ A5 h$ F1 Ostruct input_dev dev;
- u1 [4 ^ M3 z3 `# q8 hstruct usb_device *usbdev; . Z2 B5 f! \7 _0 ^( i. k6 o
unsigned char new[8]; $ g# X! n5 S+ w$ L- Z) D. _
unsigned char old[8]; 6 c0 |9 n0 R6 k. a% U/ y5 \
struct urb irq, led;
1 L2 v8 i0 N! l// devrequest dr; " Y5 q. l7 y+ a6 T) v* p
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
' `) h* T/ d+ Q4 k- d4 b4 N- W& i struct usb_ctrlrequest dr;
/ P' x7 a3 i$ _) ]) Xunsigned char leds, newleds; - ~: J% c, ?- ?2 u
char name[128];
7 W5 o0 A% F( {& I# Mint open;
. V) d0 e8 g7 e" l% r}; ; k+ z/ E8 V- t
//此结构来自内核中drivers/usb/usbkbd..c
, | D) z5 V: r/ I, \; c+ j0 |1 V. x) ~2 h
static void usb_kbd_irq(struct urb *urb)
+ y% _9 S1 ~3 W' |- T+ x% M V y{ ! j& W3 x+ ^0 o |
struct usb_kbd *kbd = urb->context;
+ e. ]$ v# \% R( O* d, s# R int *new;
0 Z6 A, |% \% ^7 }$ k' Q/ ^! ` new = (int *) kbd->new;
' ^. C: N' |: E8 w# K- o( k# \3 {2 ~; H l" f$ e4 c9 \
if(kbd->new[0] == (char)0x01) 5 r6 l3 y, p: I8 T
{
5 A% W; M4 Y, b7 w# O6 Lif(((kbd->new[1]>>4)&0x0f)!=0x7) 5 s, B# W9 F7 F' C! M$ w
{
& ]# R {0 i# E8 s1 Q3 X' lhandle_scancode(0xe0,1);
* M1 J$ ^1 o! |' y1 X5 p/ \( g0 whandle_scancode(0x4b,1);
2 U6 ^0 b4 O% {6 c handle_scancode(0xe0,0);
4 T$ \2 ] Z& l9 @ handle_scancode(0x4b,0); 9 C' `# I, t1 k( r
} + H" W8 p; k; a5 ^( E
else
0 e$ C9 [* i; j, H5 b6 m* ]% A( R{
; E+ i1 P5 s. c3 u8 D: hhandle_scancode(0xe0,1);
4 t9 P+ }! }/ q& m/ s handle_scancode(0x4d,1);
) P7 Y) k5 h4 a8 D1 h L! a9 S handle_scancode(0xe0,0); 6 T6 E( U+ r/ Y. s4 g
handle_scancode(0x4d,0); 8 m* V7 R u+ ?* k, l
} 1 z/ ^' A. u* _( W7 H, F1 M- |, H
} , r: {6 M, @5 L, P; c# y
) G) Q- I1 v! A: c+ ]/ ~& C1 p
6 ~! e7 a7 w9 Cprintk("new=%x %x %x %x %x %x %x %x",
/ d8 q w7 X' n+ h2 g; qkbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], 9 w( k7 b# N Y8 n% o5 [
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
1 F6 V5 o+ c! I9 ^
7 i0 M* Z0 C0 `1 w& s. {* n' G}
( G5 t* K2 W+ @9 ~6 r3 h- ~$ d2 a8 C3 _4 i3 j& i4 f
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, % A( c- h# d/ b. p" C' O4 _. B7 h
const struct usb_device_id *id)
}, e. `2 e8 v6 [' h# `3 ^{
! G+ b% D5 l% u1 w0 cstruct usb_interface *iface; ' |( e7 d1 T# W% |- `. J
struct usb_interface_descriptor *interface;
1 H8 R9 f2 h! s, G: b" B) Dstruct usb_endpoint_descriptor *endpoint; 5 {# _( \9 u3 ?0 r: _6 \
struct usb_kbd *kbd; . q( q Q8 ]' `- X" ^
int pipe, maxp; l; O l- o% _: ]( E
: h/ c: k3 m8 |' i1 ~1 j1 ciface = &dev->actconfig->interface[ifnum]; ( H, K& f2 l4 c& \
interface = &iface->altsetting[iface->act_altsetting]; 3 d& x2 ?- J& c L( z1 \
# f0 B& k V H' |' Sif ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) ||
5 |" F0 d& B& S& ?8 |(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || ( e) P ?; M& K8 H' i; L. \4 z
(ifnum != 1)) 7 S0 P) B* C6 c$ ^2 H+ A- E
{ ( o5 H: T6 v* @( s% J* d
return NULL; ) A! C* c3 j5 ]+ x# {- o
} 0 H7 j- R: n) W# e( I; e( K j
if (dev->actconfig->bNumInterfaces != 2)
% @% r; ?8 }5 w9 e{
( K# t+ d: V+ c' Z) f1 G. _* Yreturn NULL;
9 O# M; F( m8 h8 _2 A. u) q} ( F6 Y; p- O+ o
2 i1 o: Y* k* t# n$ c) W$ l' B ?$ G
if (interface->bNumEndpoints != 1) return NULL;
3 w7 p! a y8 V8 S/ u6 \) Z T: @5 ^
endpoint = interface->endpoint + 0;
! k8 a" X b+ |3 x5 L2 Q6 l5 M) U1 G% e( H8 ~, Z+ R' }, d4 [" K
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); & E5 V% _+ N, P9 q+ k9 D- A
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); ! t( U, n/ b% P3 P: _6 |" Y1 w# _8 N
- x/ a; e# b4 w9 w/ r
usb_set_protocol(dev, interface->bInterfaceNumber, 0); 9 c2 k o7 O e# p' m8 t7 q
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); * R0 V* \" D, V
& y( y' F6 p# R! a0 _3 `printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
, F" ~5 j) F/ I: A& vdev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); 6 |6 q# H4 z6 S" M; w: U
7 y" T' ]2 B; H
if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
0 ~8 N# ?) c4 X1 m) S- i. b memset(kbd, 0, sizeof(struct usb_kbd)); ! M. Q% a+ P; G4 w- B
) W: r- k x6 D: V* H) ^
kbd->usbdev = dev; 0 B( \4 B: W: @# J: a+ t- Q% ]
0 f+ c: s! t# a6 x" O$ ]+ m3 Q
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 3 J* m7 Y& d$ U2 q
usb_kbd_irq, kbd, endpoint->bInterval); - E) q; I5 [$ O u! }
& c; x+ _1 }; m' n$ Q
kbd->irq.dev = kbd->usbdev;
* z6 J* k0 r: W4 K6 p7 Z
1 e# E+ m6 I7 }if (dev->descriptor.iManufacturer)
3 x; g3 m3 k/ l& a- C usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63);
; W/ @0 c# U5 R5 R: @8 j: m) t q! x' ]5 m( h: h A0 X% p1 h8 Y
if (usb_submit_urb(&kbd->irq)) { * F- c5 w9 P$ A% l) O, p. R
kfree(kbd);
3 u" [: e- n. S return NULL;
/ f- U* k# s! i1 t! K" I. y: X }
2 c5 t4 N& @' `5 O- S6 J _% k
* n& W1 T! }, m) @$ B7 O- [, Iprintk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", $ k9 f5 S, y$ f: A6 X
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
) u1 y9 X$ ?* c3 w3 G X! _0 \1 ~/ M6 Q0 l8 v$ g
return kbd;
8 g+ \( [ O/ Z2 E+ p& p0 X& s} + @/ C) i" \( w* U* f$ w( H
) C$ W0 i& q% Ustatic void usb_kbd_disconnect(struct usb_device *dev, void *ptr) & T# W9 q: A8 J. k# n" r
{ " S6 |. K( c c" N) z$ Q0 F' [. ]+ S# g
struct usb_kbd *kbd = ptr;
) I$ W" E( W4 L" M2 E0 e usb_unlink_urb(&kbd->irq); , c; {3 f( M) \+ M
kfree(kbd); 5 c$ G) l8 n" P2 @0 g; w3 f
8 u6 c: W% ^' M5 I- ~
}
) M: P/ C1 ^4 |9 A
# h! M3 c) R: p$ Y; O5 ]static struct usb_device_id usb_kbd_id_table [] = { " m( q. ]2 L( c) W# \' @0 z4 Z& p
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) }, 0 M1 H. g8 P/ i9 k, R+ R( a, V
{ } /* Terminating entry */ * w' d* C. t$ X5 ?1 v
}; ! V9 a% z& w/ `6 @- ~
; Z. [$ H- _3 S. ^9 C+ YMODULE_DEVICE_TABLE (usb, usb_kbd_id_table); ! {9 e5 ^8 z3 C# ~( r8 I
0 ~9 k7 }. L4 l; N- z$ S+ U
static struct usb_driver usb_kbd_driver = {
$ l* a. C9 w- C+ k* }1 }name: "Hotkey", . Q. M8 g; |3 F; w9 r
probe: usb_kbd_probe, 1 a# r) B1 W8 V2 T1 d a
disconnect: usb_kbd_disconnect,
1 N/ r' R. W M( t7 K' oid_table: usb_kbd_id_table,
. I8 u% D6 ]- _5 } rNULL,
: V3 K8 @% o) k' H; e- M+ H/ V}; / m. V( i |* { G
+ Z9 t( q$ A# K$ f, b) istatic int __init usb_kbd_init(void) & y" O7 N8 o3 \+ I
{ " U1 u2 Y% E2 f( X
usb_register(&usb_kbd_driver); ) N1 u! U7 W) z+ p; x" h0 _# {
info(DRIVER_VERSION ":" DRIVER_DESC); d9 u' M2 D) n6 x
return 0;
* i: e5 N" @2 c} 1 x% o, U8 N/ N- m) z3 F7 k: ~# c
s$ t/ Y( E3 h9 u) ~0 c4 Jstatic void __exit usb_kbd_exit(void)
1 r5 K( F9 P& M' M$ m{ # _4 D1 O0 j8 \( n- s4 B8 Q; q
usb_deregister(&usb_kbd_driver); ' v1 W! M. n9 u4 }3 P: b
} 7 W# e# ^ S$ {; ^% n! q- y& P& a
+ b1 p( z8 f# |4 B* B/ n) \
module_init(usb_kbd_init);
. n( N1 n% c0 T2 i H! Umodule_exit(usb_kbd_exit); |
|