- 在线时间
- 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, . \% G) ]7 F* D. h
" USB ", " Mass Storage ",
) s( E" k3 |. Y) BUS_SC_SCSI, US_PR_BULK, NULL,
% A* _8 t9 [8 k3 bUS_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE )
- F: e' i% ~* _1 g- S# K
* J/ r4 E. @5 d+ x' X1 @" _注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。 5 n" j; ]5 A& z1 T4 Q, D' F
最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 : z8 r+ x: x2 o! d, r3 |" O
键盘飞梭支持 3 n+ S7 o$ s6 M6 M
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。
/ z I1 O3 ^- q( o/ {9 o下面是具体看到的信息 5 q/ D, P9 ]+ i: q" R/ {
3 e/ O1 B- Y5 b' }* C7 C8 s6 m' ^: sT: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 S% P6 Y5 O: H$ j, o) ~8 |4 q
B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
2 w( S9 R0 w, N" |D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 1 e {$ |. ?) V' b' o% x3 b0 T+ [3 F
P: Vendor=0000 ProdID=0000 Rev= 0.00
5 c% n6 u3 W; M0 lS: Product=USB UHCI Root Hub
- \1 A* R" i3 y2 ^- cS: SerialNumber=d800 5 t7 n( Y4 e( E8 `* e
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
: S0 @- ~/ _7 l( z4 BI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
) L( N. O" ]" @4 h" m5 [% @E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms ; w. Z8 m6 r9 T* }( m/ m) J/ j2 L' t
T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3
) h3 f9 f# t# m* b9 ^D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 ; v ~3 M* S! ?1 j3 I, @0 {
P: Vendor=07e4 ProdID=9473 Rev= 0.02
0 K- J* j" T d. x; g" RS: Manufacturer=ALCOR
, u! G+ L, b- uS: Product=Movado USB Keyboard $ _3 q2 J' m. u& d7 p6 U7 y
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
- w3 D& A8 h! S* rI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
3 L3 B3 x' n9 w- w7 b; m: d! T, qE: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms # R& r! C: p- s' X2 [+ i
找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中
9 q& w4 ~& R3 Q/ _! u- i# C4 d, v% @ x- D: W1 C1 c" c% x
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, ( O+ B3 y _1 l
usb_kbd_irq, kbd, endpoint->bInterval); & E0 E' P! X3 ?; M ?& s4 M
/ O8 A; U$ V/ ^/ m- Q- ~( M
一句中实现。 " I) D: \$ U) o4 z) }/ I
从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。 9 K' T$ M8 m" d7 @! `: e3 y
在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。
1 R* P7 k3 \8 r程序见附录1:键盘飞梭驱动。 ' r2 U, ^. S) _) y: l7 C5 o
使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。
1 ~5 j1 o! N" H' V, f: i, z参考资料 D, k0 M( u Y3 w/ u6 }$ w9 m
1. 《LINUX设备驱动程序》 1 g; b! P4 F6 W, O- a- m/ q
ALESSANDRO RUBINI著
$ l! S9 ]. F! {( x1 z1 H% vLISOLEG 译
. X. I* V" l+ c# w' ^) P/ c2. 《Linux系统分析与高级编程技术》 & x- n, _" V; ?% M! Y
周巍松 编著 3 E8 e& f' V! @# Z: i4 @2 N: n
3. Linux Kernel-2.4.20源码和文档说明 # z, q" |2 ~7 h# J$ R( m
附录1:键盘飞梭驱动
! E+ ]! d, ?6 i4 ^ R1 H3 o5 @# P* R% F/ m
#include <linux/kernel.h> & K) }7 L. _% G, C. B8 ]/ _+ c5 p
#include <linux/slab.h> " Q/ K1 ?3 Z7 D# O% w+ h' W# [
#include <linux/module.h> 5 O9 Z1 n" g( z' [; Q+ l
#include <linux/input.h>
0 h y3 ~) Z# y) x9 j#include <linux/init.h> 5 K) q/ d4 p% a. p' Y# l% }! Z
#include <linux/usb.h>
4 q; C2 N* O; Y3 A* `#include <linux/kbd_ll.h> ! r. U/ S0 p1 U/ v5 ]
' j; t3 O' `4 O9 K2 S/ k4 r# w/*
6 a% }) g! @5 |: U! N* [ [ * Version Information
5 X& o4 l2 M- n% C& D */ % E- Z+ D2 w2 F& H
#define DRIVER_VERSION "" ) S) `+ c# x( ^8 A2 u; h2 t
#define DRIVER_AUTHOR "TGE HOTKEY " & p5 |4 S v0 I5 d- @4 ]$ |
#define DRIVER_DESC "USB HID Tge hotkey driver" 5 T+ Q/ Z3 \' o; {5 k
4 {" W a/ W+ Y. W#define USB_HOTKEY_VENDOR_ID 0x07e4
3 e- `; V" c3 O; O$ {; Q#define USB_HOTKEY_PRODUCT_ID 0x9473 ; Y. C |2 V' w4 s8 B2 o6 k6 ~$ ]4 U
//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
$ q, p- B l2 U- j6 p5 K' Q' S% f. Y `
MODULE_AUTHOR( DRIVER_AUTHOR );
( o3 u6 {; f$ Q! yMODULE_DESCRIPTION( DRIVER_DESC ); ) D4 g$ G. m9 f# f
6 `* S: L/ ]$ i% q
struct usb_kbd { 2 [8 Z7 e4 X* e+ P
struct input_dev dev; - J n1 M* t( d
struct usb_device *usbdev;
% {% B: P4 T9 W1 Sunsigned char new[8]; 9 l5 I( [9 x. y) W! g$ S
unsigned char old[8];
+ b2 G. P; p1 M! f% \% ]' ^0 I7 gstruct urb irq, led; 2 i7 j* o9 J: t: b
// devrequest dr;
4 A; Y& g) o6 i- t9 d e9 f0 J//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化 0 q: ?. z* u4 \" s$ n0 F S
struct usb_ctrlrequest dr;
- C3 S7 j0 F# S+ Q& y) S6 @unsigned char leds, newleds;
7 `6 m! }" t" C% N4 f* S1 fchar name[128]; 5 _% T0 M% Q( D0 S
int open;
1 R5 a5 f1 g4 c( R}; ; t5 x3 h; ?$ e! t# Z
//此结构来自内核中drivers/usb/usbkbd..c . E2 f% `) ]; T8 n+ v0 {
7 M2 j1 ?9 G. @# h
static void usb_kbd_irq(struct urb *urb) + d$ [& H+ }# f+ Q& p; i
{
( n! ]/ {/ Y% o2 vstruct usb_kbd *kbd = urb->context; & w& e# G! f: Q5 ?9 e; d
int *new;
* I# U7 `/ r4 o, ?% @9 ]4 A! j% m new = (int *) kbd->new;
* X) u1 X. ?% i6 j7 a2 }/ X% o1 Z" l9 a! w3 c, s4 `
if(kbd->new[0] == (char)0x01) 9 h8 ` }3 \8 n: w8 Z; W5 z
{ 4 A8 F# s, e# D) ^$ u% J7 x' Q" ~- E2 n
if(((kbd->new[1]>>4)&0x0f)!=0x7)
& x3 Z* _ k" U# |& M+ ?{
, o3 m' x4 k& ?4 e: Z' Khandle_scancode(0xe0,1);
8 G7 s% f) L/ u1 lhandle_scancode(0x4b,1); # x" i- I0 x; |$ X2 v' e
handle_scancode(0xe0,0); ( ]* ^4 J& {9 v7 f& ?7 P+ u
handle_scancode(0x4b,0); 5 J" A3 @" K& u. U
}
1 @; @2 f9 L2 kelse * x, G7 q* U+ h- V3 l/ `/ H# f
{
3 v1 Q8 r& y' w! a1 y% J: uhandle_scancode(0xe0,1);
- W. J* d$ Z4 ^; [ handle_scancode(0x4d,1); 1 ~5 y* x4 n' v7 W/ o0 H
handle_scancode(0xe0,0); & E* ?* L, d! J. d
handle_scancode(0x4d,0);
0 V' `) ?% j# L/ b. ^5 @; X}
4 l& s8 [7 T/ R}
) @8 f/ u4 l% Y- l& u2 M+ ]* L3 ?1 ]% p2 Y9 ~. a. k2 F$ W8 Y. {
: g( E# S* P9 D. z
printk("new=%x %x %x %x %x %x %x %x",
1 X8 o' v& L" \1 e4 v7 bkbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], & z7 B8 i' T; n2 Y9 F" y
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
" N% `9 \ g: Q8 D- v+ o8 z2 a
% Z+ i! Z" Q X8 H5 M}
3 J' g) { ]6 k% X7 O/ J3 k1 |, \; E4 Q3 x9 L- s
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, 7 ~' h! ]. A& d0 h" O
const struct usb_device_id *id)
1 O) Z4 x9 s2 ]4 `2 E0 t- {! @{
: A9 h: o5 m( n; O7 v( T# gstruct usb_interface *iface;
6 g8 z9 ^& }: x6 d) W struct usb_interface_descriptor *interface;
- N0 w$ o2 N; _) F% D8 D& g T0 Mstruct usb_endpoint_descriptor *endpoint; - E+ \9 a1 n8 t5 B* @) I) c
struct usb_kbd *kbd;
* R/ O4 ^3 ]1 b, k int pipe, maxp;
$ E+ S+ M9 K$ n6 j2 ?+ \5 M& N: J F# P, x: Z
iface = &dev->actconfig->interface[ifnum]; 9 ~) {8 H' o. r0 E
interface = &iface->altsetting[iface->act_altsetting]; * Q& h8 {5 p1 v) Q' G) _# p; _. \
, Q* f" q1 m* S7 H6 Q9 M
if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) ||
/ w" M6 W7 l# U( @4 [2 M3 z# N(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) ||
' w* |+ g2 b, m(ifnum != 1))
# Y; N( |7 z6 T' q3 J% n- I, `{ - E8 _' z8 |3 K6 ]. c3 Y
return NULL; 3 P* v( [6 |; g: e5 p
} & } B7 b. P& n/ W) S2 s( q1 I
if (dev->actconfig->bNumInterfaces != 2)
0 ]8 f+ d" v) J3 l! u5 c9 n$ X{
: f1 h6 d k) C% k+ _: v9 \$ r$ Sreturn NULL; % N7 J$ a$ o2 u3 I6 R/ I
}
& r3 ]; n! E8 \/ u5 R8 t* P7 B+ F# i, M. ]' B; w& [7 d
if (interface->bNumEndpoints != 1) return NULL;
/ D- V( Y6 [) Y
% o0 k# i9 W: w7 U( W* u- l endpoint = interface->endpoint + 0; * t$ X: W" h6 D- _% n, h
]$ _& U' G0 @
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
6 d! m' U5 u" d+ G0 Y+ M1 }5 _% n1 @ maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); ; g+ h2 [; F! k( ^, `
X/ B" v: ]3 u* | |$ ` usb_set_protocol(dev, interface->bInterfaceNumber, 0);
! d _8 Q( z1 j; z usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); " I+ g+ [- [! j( L8 S: U$ ] N5 R
3 E0 V- ?: X# W. @' C9 Fprintk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n", $ L. J/ z" M% [! j8 u3 y
dev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); 7 e ]6 q( x& ]
& N+ a3 I, @2 _" q0 d! Q8 Z. y4 {$ e) { if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; * f9 G u* z/ [
memset(kbd, 0, sizeof(struct usb_kbd));
! r; P: f" ^& T! a% v7 N% o% R6 L: v/ F/ u4 f
kbd->usbdev = dev;
6 C5 X5 Y# ?& T# b6 D
* _" M, @' x! R7 Z( c FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 8 L. w: C6 y& u1 y1 l8 ~
usb_kbd_irq, kbd, endpoint->bInterval);
2 J; X$ O' s* T, ^7 N2 |
; y% X4 H3 ~" ^8 p& Z7 g. g0 bkbd->irq.dev = kbd->usbdev; ! b# m8 |0 H2 B0 }; H
& }2 `2 W! Z( n; Yif (dev->descriptor.iManufacturer) " U% | c2 M: R
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63); ( h+ b4 v9 C! Y; v$ {1 m1 B" E& R
, }, H- R5 w0 U+ E' r
if (usb_submit_urb(&kbd->irq)) { + g$ R9 ]; w; U; |& ]$ U+ N
kfree(kbd); 9 S3 t# r, E% k3 T5 r2 c* [, ]
return NULL; 2 q/ F+ \/ h; \' v% {% i6 A9 |
}
# F1 a: z' l( K3 p; `
! ] d4 e8 O2 i7 t* Iprintk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", ( ?. ^* |5 v- d. ?- L! b8 d7 p
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
, d$ w( v- E& H8 n- K c# V1 V' d+ a1 S5 H
return kbd;
0 s; p. @/ w% `} 2 y- @$ E7 d% [' n' [& a( G
( ?" A/ P* W( p& K' B# j* e nstatic void usb_kbd_disconnect(struct usb_device *dev, void *ptr) 8 o5 j: D5 i' o* f
{ - m9 ]& O& R0 ?' K/ ^
struct usb_kbd *kbd = ptr; ; g6 j' V5 _% {- W
usb_unlink_urb(&kbd->irq);
" S. ?1 }% I9 D8 O kfree(kbd); . q3 Z/ H/ f5 S1 A+ N) ^, C% v
) R- u( ~( n3 F8 [+ M* J8 C5 E} / ]: @5 Y6 r' y, l
6 O" s: b9 S; ]$ a- X
static struct usb_device_id usb_kbd_id_table [] = { 3 {5 y: m2 u- f" z* m' T: [/ K
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) }, # P# ^" r6 d0 B3 A+ M) G
{ } /* Terminating entry */ 8 w9 z- U' U1 ] F y
}; 0 J; C- I/ x7 y) [
) H0 i# T- O9 `
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
+ F H# }& |( c$ D: H0 k% O, Q) Y/ D; [% c# A
static struct usb_driver usb_kbd_driver = { " t* x1 y- D \# [
name: "Hotkey",
% ^5 _; H* K& A4 O0 sprobe: usb_kbd_probe, ( m9 A6 |# A# G* Q9 _* D
disconnect: usb_kbd_disconnect,
1 W: q5 s/ S; B" Fid_table: usb_kbd_id_table, ; v$ i# N! ^8 d2 k% A- b& j
NULL, # y( D) \/ G" r3 [8 Q) ^, r
};
% r) N. G3 t0 f; H7 e* Q% {0 ? ^; q3 h+ u; ^. K8 P
static int __init usb_kbd_init(void) " I2 j. G S: S
{ 4 m$ g$ N6 z, F
usb_register(&usb_kbd_driver);
1 O: p; f' S, s$ @2 W9 v; Hinfo(DRIVER_VERSION ":" DRIVER_DESC);
2 o0 U# E! O4 ^1 [return 0;
& z; `! K- k- d} 0 f0 H) q+ g' }( |
8 k% @8 P& E fstatic void __exit usb_kbd_exit(void) 3 y/ U5 d& {( R
{ 1 b# U$ O+ n" h p
usb_deregister(&usb_kbd_driver); ( O1 r1 x7 M0 x" O ~! ~
}
3 w. ~+ s0 a, q" \ L3 t A- V
) A: a7 C; E& Q/ Y# E. ~$ Tmodule_init(usb_kbd_init);
# z: U0 m* T* f! Omodule_exit(usb_kbd_exit); |
|