- 在线时间
- 63 小时
- 最后登录
- 2019-5-3
- 注册时间
- 2004-5-10
- 听众数
- 442
- 收听数
- 0
- 能力
- -250 分
- 体力
- 10122 点
- 威望
- -12 点
- 阅读权限
- 150
- 积分
- -586
- 相册
- 6
- 日志
- 10
- 记录
- 10
- 帖子
- 2003
- 主题
- 1253
- 精华
- 36
- 分享
- 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,
/ s- ~/ |% D5 e. w" USB ", " Mass Storage ",
# G! k4 y& m) ]0 Z. tUS_SC_SCSI, US_PR_BULK, NULL, 9 T* Z! Y* \% U9 E" C0 O
US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE )
& ], J3 N; o7 d7 w- y1 o, D) D* w$ l
: p. U5 w5 A9 h& q1 v6 C9 k' E注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
2 S/ h5 e6 @! w% Y5 L; {* y最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。
4 s* b# a* d% g+ A3 w键盘飞梭支持 ! k( M: r. e$ Z V2 B2 i
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。
, J' W7 ]% u* G" T) d; C下面是具体看到的信息
, Q5 F: y7 |) {
1 Q+ h+ e+ J3 `) x! CT: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 7 C: ^( X1 J5 s, G' j" w
B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0 , Z8 m6 X5 V) V8 b) s
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
) ^/ j3 S7 a2 H1 \7 XP: Vendor=0000 ProdID=0000 Rev= 0.00 2 a7 O" v" a- X& J
S: Product=USB UHCI Root Hub $ m4 ?5 f5 c6 F3 v
S: SerialNumber=d800 + T* G! E8 n! T. c' r8 M
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
7 `! r& N2 f( L0 |( }2 }; |6 pI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
- J, r1 w; D: k: R. SE: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
3 I' j/ _4 M1 ?7 d" Y7 nT: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3
8 A ^5 S! d" \( e+ C3 }D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
1 a9 A B4 B. C5 t/ s0 B6 }2 g" ^P: Vendor=07e4 ProdID=9473 Rev= 0.02
+ H* M7 r8 g" F. g1 J% X1 ~8 dS: Manufacturer=ALCOR / C" ?& `/ v8 H* \! P8 w
S: Product=Movado USB Keyboard & m. c0 g W; E
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
. E3 | t# Q/ r t9 V; L" C gI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
+ A: l$ ?2 n# E' R( {$ C! x, O0 ]E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
9 c9 ^9 |1 m7 `5 o+ @3 s9 Q8 P找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中 , o5 A9 c' w9 _/ D. ~' Y/ d5 D
" e$ B/ M. z7 G! NFILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 0 _: N' z% P* U- z+ ^
usb_kbd_irq, kbd, endpoint->bInterval); ( j$ {& @" D0 R% A) W. J" O
$ @/ v' H% K1 |* C一句中实现。 8 R! o" j! Q4 d, s7 I, @
从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。
+ A% U+ k5 Y/ w2 D$ m在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。
. x/ M! |' V; N3 I0 P. o% b程序见附录1:键盘飞梭驱动。 - z7 ^- U& t/ _* a$ w3 o! r
使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。 # g/ p! M# ]! M7 ~2 ~
参考资料
9 `/ q# c# `- P: N1. 《LINUX设备驱动程序》
5 Y' w2 F+ U6 l# QALESSANDRO RUBINI著
1 U+ r7 Z# m0 H8 C+ JLISOLEG 译 ' V7 `3 d) i5 P8 \; B" I" P9 ~' i( C
2. 《Linux系统分析与高级编程技术》
* B+ p9 x6 ?' V: v6 M8 x周巍松 编著
4 [* l, H( V6 [* E3. Linux Kernel-2.4.20源码和文档说明 ! m/ @7 H4 I% W+ Y
附录1:键盘飞梭驱动 - a$ E5 \; W2 U! `
# E4 a0 y! W5 U. V. H#include <linux/kernel.h>
& \9 c7 i* i3 _' U9 s* A#include <linux/slab.h> ; r4 Z7 _3 v( z5 p
#include <linux/module.h>
$ }3 f* w$ G, ~. w: d#include <linux/input.h>
1 e( `' U/ G( H#include <linux/init.h> 1 c. u1 E3 S; i2 {+ a2 h
#include <linux/usb.h> ' ^( P' Y, q( S& _) x1 X
#include <linux/kbd_ll.h>
! c$ P% w9 h) o6 b- N" F
$ G7 N8 H* {+ z; J/* 3 w) C2 H7 R2 [! j
* Version Information " t* l) j: q( R0 w# O$ ?' ~
*/
+ G& e$ P5 ^, \+ q! C, ^#define DRIVER_VERSION ""
h$ X9 B! ?( f+ W#define DRIVER_AUTHOR "TGE HOTKEY " 4 \% m8 W! X" `; l! M/ p) f
#define DRIVER_DESC "USB HID Tge hotkey driver" 8 K- J, m: G4 M/ j" q3 g' h
( Z- r2 F" \+ P+ {#define USB_HOTKEY_VENDOR_ID 0x07e4
. Z X( V$ Z C8 J#define USB_HOTKEY_PRODUCT_ID 0x9473 7 F' r4 @* T ~4 x0 ~9 Z
//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
* x: E( o/ U1 b1 ~# ?/ b3 C* t% }4 j, J, i* L5 {: j
MODULE_AUTHOR( DRIVER_AUTHOR );
. W; u/ p; i% u# Q, w fMODULE_DESCRIPTION( DRIVER_DESC ); _& d+ R+ w8 d/ o/ O% T' B+ K
" z# r1 N2 |* @struct usb_kbd { ( H9 }2 N) z% ^, ?8 Q
struct input_dev dev; $ k {% m0 p5 z* z) d0 \) ^
struct usb_device *usbdev;
! {" i" |. h" Q: [, q: Uunsigned char new[8]; & f) o! x6 K/ ?4 ^$ T
unsigned char old[8]; T) b# a; @0 a4 `2 H' B
struct urb irq, led;
' Y0 a7 W3 S) }# y// devrequest dr;
3 Q* m# u6 x# ?' g9 Y! C//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
# t- S1 P7 [( Y+ ^, R struct usb_ctrlrequest dr; : R% m7 k/ Z, R6 T0 q) ?/ X1 c- P
unsigned char leds, newleds;
, w7 Y/ J8 _1 T% ^$ x* B9 schar name[128];
6 D+ C% z, f, e2 @$ p. t; Nint open; ) y& T1 ]. A( B7 A
}; [) |3 |" U' q) Y7 E# ]
//此结构来自内核中drivers/usb/usbkbd..c
9 T( h4 }* U0 e8 g( i3 |4 }. ?
, m: s: }8 n) z5 fstatic void usb_kbd_irq(struct urb *urb)
8 Q+ Y" \% @" P7 W{
3 b! x7 Q9 V* J$ S0 @% ystruct usb_kbd *kbd = urb->context; 3 Z& J/ R2 o/ X& x, z2 w
int *new;
4 Q7 x) f- W' Z' r P: A- l new = (int *) kbd->new;
! _- B- }( @! I. V5 C' ^8 y; y6 F. w+ [) h8 o
if(kbd->new[0] == (char)0x01)
: {( ~! P$ R" B0 o! A2 F% n: S5 y{ ! l* U$ w0 W" |6 c* o( q
if(((kbd->new[1]>>4)&0x0f)!=0x7) . k; k: H/ h) `5 O7 {; s1 `* g
{
8 h: G- R3 ?' C* c2 T2 {. r+ ]handle_scancode(0xe0,1); : `% }# S' R) y+ n' w* o# C% H m2 W, e
handle_scancode(0x4b,1); : F% X1 S* c4 d3 f% Y0 j# Y
handle_scancode(0xe0,0);
m t( D/ l* S- b' U handle_scancode(0x4b,0);
; Y6 ]7 a/ W7 B' x7 r* X' V} & j! x( s. y2 S N( s
else 7 X& |9 e: h, x* b% M
{ $ v8 j% h0 m- w* r F4 g. w1 k
handle_scancode(0xe0,1);
! r& E( n" B/ h1 S3 g0 V+ w handle_scancode(0x4d,1);
& e6 J) H: r% ^+ f" X7 B }" a0 U handle_scancode(0xe0,0); 3 a2 g) @+ `3 a9 l
handle_scancode(0x4d,0); % y" R4 s ]+ o2 k7 O1 a/ T
}
! Y$ P. N% H6 y$ a `} . m) W) c8 d! g1 h- l
6 h) A6 @- b2 P* h* \
4 O- z5 a: J# L; P9 J
printk("new=%x %x %x %x %x %x %x %x",
. v. ]9 u. H2 A/ Wkbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3],
2 x# z% R% z7 ]: x7 akbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
- }3 ?" \9 h" f3 H @: J
. p: x" Q4 _* K1 e9 G2 p}
" K( }# x- X4 W7 o! r( @* F6 V4 D: x; I
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, - o; _# M, ?) q' S
const struct usb_device_id *id) 3 H ?0 v c9 M4 z2 m$ ]! x
{
1 [5 B' ?+ _- N) U7 ustruct usb_interface *iface;
4 M7 ` v2 i* S. c0 K7 q$ E3 q struct usb_interface_descriptor *interface; & w, t% n9 R3 k
struct usb_endpoint_descriptor *endpoint;
/ W$ Y# m' Z" b7 s struct usb_kbd *kbd; 6 [1 k) A1 y% z' A7 ~5 p1 [5 }
int pipe, maxp; 1 X1 o2 d9 g& o1 V: Z* f; T
* V/ h) @% ]6 s: @iface = &dev->actconfig->interface[ifnum]; 8 R; j6 k' c& B( \9 Z
interface = &iface->altsetting[iface->act_altsetting];
) }( a3 C7 V1 X- b, a7 R# m; e E* f2 d* A, ?) U) K
if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) ||
c6 I& ^1 \1 }! M(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) ||
# M6 i$ r: \7 `) Y" w. ]6 t9 x(ifnum != 1))
- v# @5 S3 ^2 G{ + L) k4 d$ Y, ?8 ~1 N( j$ V% ]
return NULL;
( P) h* ~2 G# P3 d6 X" k& c} 9 E$ X, i" E. m4 T1 r2 p& N/ q
if (dev->actconfig->bNumInterfaces != 2) ; k! d8 X6 P# j; x* [$ v/ p1 u
{ 7 j( l* t9 [) i" I% Y9 a# r- J
return NULL;
* r- k4 ~* ^) n* X}
; @; M9 ?' x% q k" i: O+ B- O/ }) g
3 n" Z, e+ B0 C9 }if (interface->bNumEndpoints != 1) return NULL; * Z L4 X' b& |, ^& G
; o% X* \; n7 q, d S3 j endpoint = interface->endpoint + 0;
9 s% L8 u# P" D, p0 J2 `. l: r8 K$ b8 g1 _& s
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); 2 I/ X3 I; v! d0 e( }7 v
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - W; w3 R# }6 N0 `
! v$ f1 T! ^6 `, R: J/ \6 Z& F usb_set_protocol(dev, interface->bInterfaceNumber, 0); $ a8 Z7 M+ }8 _2 ]# v7 G
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
. A+ F# D5 q! y6 Z+ ~" }* T' O. r! I( F' @5 E/ C
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
2 R$ t7 X6 L' d5 m: ddev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); ( x* q* [; W9 y, c
* ^: a1 a; H1 e# |, P- I
if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; ) e+ z$ l; G) y6 {$ H( C
memset(kbd, 0, sizeof(struct usb_kbd));
; X5 `# C' S0 k5 o5 q7 |
$ P) I) E4 e/ G& n" F. Y, }, P kbd->usbdev = dev; * \3 a8 m* ?. X+ L! C- k0 o2 i
2 F: m t6 S% ?+ L0 R$ C) n* F FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
( L8 b& ]. J; Kusb_kbd_irq, kbd, endpoint->bInterval);
8 [/ Z9 A( ~+ T; e6 T% }& X$ e* p9 G' h$ ^$ l) C& N6 m! r
kbd->irq.dev = kbd->usbdev; * b6 F" s/ i8 |7 F! F
# ]7 |+ I% ^: S
if (dev->descriptor.iManufacturer)
6 v6 ]+ a- G! @) B1 ` usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63); u; \% r# B, {
2 F- B$ p0 v# d1 i9 _( B2 N8 i
if (usb_submit_urb(&kbd->irq)) {
, F- w$ B! Z8 v4 l' g kfree(kbd);
w: B) b0 c* _5 T% c return NULL; ( z& S4 P" R% |# r
}
2 ~. X1 ^6 V2 J7 @& t Z* C" ~$ t( M6 y" O8 {" l3 I
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n",
0 u' V) d6 A3 I6 ? kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
; V- F9 q. z: G5 ^1 |" u
9 Z1 h5 b# m2 S1 P2 Q& A return kbd; , ^) j& f5 Y( n/ ~' b5 `3 z
}
. S( G- Q/ P& b _! w) s) @" f0 U0 u) x( [9 [- [3 K5 I! p' X
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
$ U+ ]2 R) D" C{ ) |8 E9 l% N' Z/ B" I
struct usb_kbd *kbd = ptr; $ v. b: y/ s% e6 F6 D
usb_unlink_urb(&kbd->irq); + m1 ~5 L7 B$ U. ]3 q
kfree(kbd);
0 m: Z9 B0 ]0 `8 s# ~6 M" u* {- y9 x
} 6 V$ a$ V1 m# t
( n" U$ l' I/ {% V% U- H4 Estatic struct usb_device_id usb_kbd_id_table [] = { 5 s7 a- r/ x# I' n+ `" v
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) }, - t0 I+ S* }& |: [( \5 e# L; k
{ } /* Terminating entry */
3 u- q4 f8 W) F0 |2 A$ [}; . S; ?2 D% d* D8 z3 [% e( D, J" P) @
% F" y2 x6 `. \! ^+ _4 V; ?% }MODULE_DEVICE_TABLE (usb, usb_kbd_id_table); 0 _, \: `% B0 v+ U" s
( y2 L: E% F5 y4 g! B" C
static struct usb_driver usb_kbd_driver = {
5 N5 r. J9 k0 E u9 o4 I* {name: "Hotkey", $ _& h& R, g+ k7 M- w& A& f
probe: usb_kbd_probe, 6 f% k$ Y6 C; N, E# b
disconnect: usb_kbd_disconnect, $ N c2 y5 V( }: B4 K
id_table: usb_kbd_id_table, 3 ?$ h. j5 Y& e b; {" i1 c
NULL,
9 H. l& K" T2 c, q; D9 [$ Z, E};
$ @, e0 @2 F7 e0 ]; L- K. |6 y7 y, B G; D8 h% ^. i, I
static int __init usb_kbd_init(void) 2 s; F/ n! X& u. \2 A
{ 0 V' X3 ]( d L
usb_register(&usb_kbd_driver); / v! \" h. G1 c
info(DRIVER_VERSION ":" DRIVER_DESC); - }( t6 k3 o+ l7 h* ~; A" R* b7 R
return 0;
# `" ?0 ?" R5 k2 C- t/ G}
7 y. u5 M: F8 ~. H& y% s# D0 _2 C* S, S* |3 N( m
static void __exit usb_kbd_exit(void) 1 w* ?; K$ C q4 Q$ n
{ 5 }+ [6 L \+ j6 @1 Z- p
usb_deregister(&usb_kbd_driver); 0 J! O5 V( G) i
}
3 h; Z, `: E/ I E
8 r* S+ {8 ^3 D3 z5 G. Rmodule_init(usb_kbd_init); 5 Q% S& k) C0 f2 ?* ]
module_exit(usb_kbd_exit); |
|