- 在线时间
- 63 小时
- 最后登录
- 2019-5-3
- 注册时间
- 2004-5-10
- 听众数
- 440
- 收听数
- 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)是目前中国最大的数学建模交流社区
群组: 越狱吧 群组: 湖南工业大学数学建模同盟会 群组: 四川农业大学数学建模协会 群组: 重庆交通大学数学建模协会 群组: 中国矿业大学数学建模协会 |
发表于 2004-9-27 14:33
|显示全部楼层
|
|邮箱已经成功绑定
UNUSUAL_DEV(07c4, a400, 0x0000, 0xffff,
; I8 N2 b0 t! z4 w- s* \" USB ", " Mass Storage ",
2 S) a/ p% R. r8 y$ t- P, B3 wUS_SC_SCSI, US_PR_BULK, NULL,
; g; `4 Q4 {- [6 }0 D+ wUS_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE ) * n& q$ S3 A+ k9 Q2 M L% U/ _
9 ~- ?3 t0 e: b- r! O6 C
注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
2 V5 s. C V0 O# B最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 : \+ S1 A( s0 [
键盘飞梭支持 1 o& A5 J5 M" M3 q' h9 n
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。
1 p5 T2 l7 r0 [" C# o- r- |下面是具体看到的信息
' w- `" S4 M& ]* \: ^3 d) }
2 o. ^% z) A% X1 |T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
3 m/ A$ |7 q* ]6 J3 D! u% `B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0 ) G& r- y% [0 D/ Z2 ?+ K
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
4 V- B' j- p( B1 n+ K1 qP: Vendor=0000 ProdID=0000 Rev= 0.00 6 k! y- T& d6 v) H$ l6 F% L
S: Product=USB UHCI Root Hub % V" |+ U( D' v1 I5 l/ D. y
S: SerialNumber=d800
4 M0 w* ^- }# u. D2 e( PC:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA * c1 d6 D4 B. K$ ^4 E9 X3 O! _
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
0 @- b6 t. N+ Y( U) W/ QE: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
! h8 A$ F6 g o. ]' I; tT: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3
! O, m5 Y4 H1 W3 O oD: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 " F+ I- Z G2 d* s$ C
P: Vendor=07e4 ProdID=9473 Rev= 0.02
5 H* m1 h' S# kS: Manufacturer=ALCOR $ K3 {. e: J: j2 E# U+ c
S: Product=Movado USB Keyboard ( N r2 a' t7 |3 s n3 S
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
- p! C2 O& H. _! rI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub + |, p6 ^) ?& J8 k
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
& `) U5 N+ v# o. ]( g" [3 h% j找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中
/ M- T. b4 f0 D& z' _/ f$ _2 A# D1 F# {- L$ u4 d( k2 y
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
" y; l) G D J3 o* T, Ousb_kbd_irq, kbd, endpoint->bInterval);
) {" G- z( n7 k) H* p4 c3 E/ ^5 p- F. [ V! B
一句中实现。
/ I+ u% W7 h6 `$ T" d1 m从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。 7 T2 a) P" a! |5 I; c ]
在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。
% e5 ]! T8 q$ K: J# m4 R程序见附录1:键盘飞梭驱动。 0 L2 M( v8 t! n* g: `5 ^- X# R/ z! ^
使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。
- r: }! A# B* H! K" w参考资料
" n. |, [: j, G% w7 {& m3 w* v1. 《LINUX设备驱动程序》
" m$ s$ q" T7 K( p1 _; ]ALESSANDRO RUBINI著
; M S! h: @, ?0 `6 P- ^, FLISOLEG 译 * u( T4 y, Q5 R' v
2. 《Linux系统分析与高级编程技术》
- s' _9 s P$ w/ k周巍松 编著
2 _1 B* v* J, V" W; I- h' B& d8 m( Y. W* a$ O3. Linux Kernel-2.4.20源码和文档说明
& X& z0 Z7 B( ]2 K0 P' G0 P附录1:键盘飞梭驱动
6 f8 d; m( D8 d6 E
, ]& Q1 Y2 E0 B4 _#include <linux/kernel.h>
7 H) j5 V3 H7 ^, d$ {, ^# S7 @#include <linux/slab.h> * g& _8 y- |1 \, C% L8 b; L
#include <linux/module.h>
( ]7 O* a8 ^4 v5 l, C; u#include <linux/input.h> : p4 \7 W3 {. H3 i$ h1 E
#include <linux/init.h> 4 r! X0 p2 H' W5 N) U* l
#include <linux/usb.h> : W: ?9 \& [( s* I0 c% t& A. R
#include <linux/kbd_ll.h> 9 R/ W' n) d8 J4 m0 a* i* n
6 Z; b5 y# W; {* ^/ j. N2 V
/* 4 m: X$ B, L1 J# X, L
* Version Information * e2 H* R, `) l6 t; {7 q0 Q: W. p: X
*/
) l. O) }2 v9 G, _3 ~#define DRIVER_VERSION ""
: z# j/ e- X: \3 M0 @; I' t: G#define DRIVER_AUTHOR "TGE HOTKEY "
1 G) U" O3 ^8 d- P5 d% Q2 A#define DRIVER_DESC "USB HID Tge hotkey driver" + r7 J' e# q' W
3 Q$ C9 y5 }. }' L: x/ w#define USB_HOTKEY_VENDOR_ID 0x07e4 ! \: V# K6 m8 k6 }
#define USB_HOTKEY_PRODUCT_ID 0x9473
' N. G) T& l# A% b* K7 a4 y# U9 R5 [//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
$ j+ |+ A. L7 ^2 N* [% W( t" W3 s3 x8 F( h! M* ]
MODULE_AUTHOR( DRIVER_AUTHOR );
7 I p2 v: o1 }0 A" E7 o$ {' PMODULE_DESCRIPTION( DRIVER_DESC ); - C0 x& z$ j. s% h
8 R# s+ T" c( l0 u3 M3 v M9 c
struct usb_kbd { t: J% m3 W' {% ?! V
struct input_dev dev;
! }; P6 q& k% @' d1 b- bstruct usb_device *usbdev; ) T0 ~! d# g) S4 B1 O
unsigned char new[8];
% b/ k0 K Y2 uunsigned char old[8]; ; A, j" O$ o0 L* w4 S
struct urb irq, led;
8 p% g- U5 v% _$ o// devrequest dr;
" T+ a" v( o: D. `//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
; j* p- o: f, Q) N struct usb_ctrlrequest dr;
$ A/ Z' b2 I4 e9 \unsigned char leds, newleds; 5 U) @7 m" l/ E
char name[128]; - B/ T n& Z- z: A% L
int open;
& H$ x" Z! e, Q$ q8 Y/ |};
# l" @4 o6 V& O* u$ X//此结构来自内核中drivers/usb/usbkbd..c
6 B# x2 ^4 d6 a8 \! U6 U; S- N2 X7 S8 S, X
static void usb_kbd_irq(struct urb *urb)
5 _' [( Z& w8 s9 K0 G5 p; K{
) `) k! j9 L; J; gstruct usb_kbd *kbd = urb->context; 3 e8 J+ l0 k. V8 L
int *new; 6 Y- o8 J- O: N. z8 p
new = (int *) kbd->new;
8 X, O# p( ]7 {$ \4 A: p
# l) \( a9 N9 [, g/ i. t. Jif(kbd->new[0] == (char)0x01) 8 a0 c! }3 t+ N, K7 U: d
{ z- m( @3 I; ]% J2 Q- i+ ^
if(((kbd->new[1]>>4)&0x0f)!=0x7) ) A. \5 I3 ^! C% G0 r
{
3 z6 H1 c# g; x4 W0 _handle_scancode(0xe0,1); % Q4 b' T% P2 s% o4 ~% q2 t/ A+ M) p4 C
handle_scancode(0x4b,1);
# l+ U; X: Q r handle_scancode(0xe0,0);
7 @3 V' F! g3 K9 c5 k! `; ?* L handle_scancode(0x4b,0); 4 | ~; V) _2 c+ s! b1 P
}
* e' i+ [3 m' }1 }else % n! Q9 J! L8 U' {; z; V2 v
{
4 ~' D+ U% w% d% \# {& whandle_scancode(0xe0,1); ; {& x' K g7 ]& m2 R
handle_scancode(0x4d,1);
$ D9 B) r8 R( f8 X$ L0 r7 F* v handle_scancode(0xe0,0);
: A; G; S- Q: i handle_scancode(0x4d,0);
Y! Z- v5 H* M}
: ^0 Z* u6 R& x( E" j# d} 8 I, J8 s1 y& M a' X* X
+ g" z% Y0 t# G" K7 a% F. D! |+ {& h0 C# ^- E
printk("new=%x %x %x %x %x %x %x %x", " w; [: U' V( e' e( ~+ U; }
kbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], / m0 {& A, w# Q
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]); & X! d6 [" v1 I$ s& t
8 q0 ?- d% r- ?8 @6 m4 Z- J
} ; A, A* q+ o/ R/ |3 C# X: `
0 C- `" }+ c3 P* w% k1 _3 i
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
: G5 t$ v# J6 H b, u; }; }1 S const struct usb_device_id *id) 0 j) x5 M# t* X
{ 2 l& Z' v5 I9 B" u! F
struct usb_interface *iface; ( y X( h3 \) Z* g3 ?) E) K
struct usb_interface_descriptor *interface;
/ S3 s' k+ R) X# g, Ostruct usb_endpoint_descriptor *endpoint;
( ^) E6 c. F; k% b7 i0 q6 A struct usb_kbd *kbd;
5 a9 R: d6 K$ y1 b+ I, r& I int pipe, maxp;
! G2 |5 ]2 @; ^
! `0 o3 {" B! p( R3 Iiface = &dev->actconfig->interface[ifnum];
3 ~1 E. ~0 U; k. R interface = &iface->altsetting[iface->act_altsetting];
8 A' z g" x8 V: C! k
# S. B: k1 a% |5 A6 Nif ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || 4 ^5 }. Z! ^$ G. K9 q' J9 \5 k
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) ||
% s' [7 s0 e% P' V+ G) q7 [. u(ifnum != 1))
- S) W: `5 B4 {2 b- Q: z: M{ / P( ^$ l0 b) d0 R3 H1 t* Y) a
return NULL;
7 \- e; B3 Y+ w# y& A}
1 B- s4 l: {1 s6 @/ _" R2 f8 xif (dev->actconfig->bNumInterfaces != 2) & z% E$ T5 k, }% {* U
{ / R# o& Q, u. n9 h% a# I
return NULL;
9 C% q6 g# t% e5 p/ l}
* m; _- _) v0 I& b
% G2 ^3 g% d: a2 |7 dif (interface->bNumEndpoints != 1) return NULL; - x9 }3 v0 {( D% F: S8 q
4 O$ f% C8 I, Z8 ?" ?$ g9 B endpoint = interface->endpoint + 0;
% o# B& @& }2 n; y/ K2 q
# t: v% I7 n$ i# ]+ D8 m* F" _ pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
5 J6 i" Z9 _ b6 y; @' Z maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
/ L, E* [ a4 g" F/ H! j
+ t( c5 G7 X7 D; i* {% ?' ?8 g& i usb_set_protocol(dev, interface->bInterfaceNumber, 0); + Y4 J; O& Y( f4 x
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); # _2 R$ {& v- F# S/ n
: A8 D1 a) }+ p9 Y! }( f6 w
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n", 8 ?, }* d" i* u+ j
dev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); $ m# R( i, y& y7 ^
- z0 D1 T! s, u( C8 }, a( T G
if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; 1 g# }+ x* o2 v
memset(kbd, 0, sizeof(struct usb_kbd)); ( D9 I V# e9 d/ C, D
3 K1 T, @" a% I4 L, D, `, d+ n+ b kbd->usbdev = dev; + F" p' r6 a% I- P9 E }* S
5 S" `5 U* w* n; P, G4 A. m5 E FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, . n- J, \" }- F& Y
usb_kbd_irq, kbd, endpoint->bInterval); ' |# E; [9 U; v% s5 e; U$ Q3 e
/ ?# L7 f3 p# Okbd->irq.dev = kbd->usbdev;
3 v, V) G$ Q8 e) i v. R$ M m5 G5 ^1 G4 `8 Y
if (dev->descriptor.iManufacturer) 4 L% i; O$ b$ d4 K" E2 C9 p
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63);
. Z# V+ o2 K, O
8 o$ [0 c- f2 |; p k# Dif (usb_submit_urb(&kbd->irq)) {
' b3 ~, J2 i4 `% R, A kfree(kbd);
# e9 y" k: g; o7 n return NULL; - `1 _4 w( r9 \8 O+ z( }
} 8 w! W; N# [# T& z+ ?/ G% g# h
. ~& g, O( @+ a) P8 j6 W4 n0 r% `printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", 6 b* v) Y' [4 S5 F
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
( v8 W7 i( E4 H' X3 E
5 L3 T7 n' i' F, w1 w- N return kbd; 2 Y* M2 j0 L& b, P$ k* R$ L; W
} 3 p0 U6 g& r; Z. V( t8 E% n
9 t1 N" r! Z2 @8 S/ s
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr) * Z3 H0 M. @$ K9 P) N2 B
{ / O, [ b6 o( z, ` g0 r8 p7 f
struct usb_kbd *kbd = ptr; " c! r( \' |% z* r0 I8 K
usb_unlink_urb(&kbd->irq); $ v3 E6 V& _6 s. `. B6 ^) ]
kfree(kbd);
; o" @1 P X8 }* y; y; L$ r! g2 @& r+ x# Y5 E7 y
}
6 G3 O6 I. S, G7 S; _/ |, s9 V7 w; J1 |/ z
static struct usb_device_id usb_kbd_id_table [] = { ! J0 C* V- v/ i) b$ J9 x
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) }, + v( s" e! N* W/ A3 R
{ } /* Terminating entry */
; _; x0 O% ^" Q: x};
+ v: }4 a! K% ]! ` \3 Q' k9 Z, f3 S, F2 P5 C9 l
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
2 X! ?! X/ Z+ ~5 u# a/ c9 o
* B( Q7 H) e6 j) `5 i5 ?static struct usb_driver usb_kbd_driver = {
8 i; B. k4 u% ~& s( y; iname: "Hotkey",
# J- J: o# K( k" |& G2 S% cprobe: usb_kbd_probe, 5 T0 q8 {" d1 R4 b/ A( q
disconnect: usb_kbd_disconnect,
$ F" \( w$ ^! X b; W8 O5 p/ q: v/ |id_table: usb_kbd_id_table, 6 i/ A: F, q7 e- |/ m' [7 r9 k( N
NULL,
: Y* u* M& N$ t}; 5 f& F* {, e5 L$ |4 X# A0 H
. l2 x) ?5 ]5 r) R( {
static int __init usb_kbd_init(void)
! K, B9 ^- M: ]- J{ 3 ]4 T$ x A7 c, U* J; ~" U% t
usb_register(&usb_kbd_driver);
5 s7 E. ^+ a0 X( _info(DRIVER_VERSION ":" DRIVER_DESC);
! k& g" F& P$ ~. V \9 }, I; K+ Creturn 0;
3 M4 R0 v& v$ {5 g} ( H J! L9 H1 Y9 G
; d" Y& H4 i& \
static void __exit usb_kbd_exit(void)
2 Y3 a: R D& i, h I1 }) A{ ! ?: W4 S7 D/ O
usb_deregister(&usb_kbd_driver); 6 q' s- e- ]( B; \
}
9 \- H3 ?' N) k4 G `( a: M" Q: G; b, B: |1 x
module_init(usb_kbd_init); ! d1 R4 e# K2 J$ g$ G% T6 W& t
module_exit(usb_kbd_exit); |
|