- 在线时间
- 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,
' [) b/ E Y! m q6 {( T/ j" USB ", " Mass Storage ",
[/ B S/ V9 J" r4 ?US_SC_SCSI, US_PR_BULK, NULL,
2 g3 E. }" @. b: a! x. |US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE ) ' M! X7 k9 p/ w# o1 [7 b
3 b8 L1 ^, u r/ w注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
3 |' x& ^; N6 H最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。
: F6 T& ?: H( Q; n, Z键盘飞梭支持 * |9 q! ]& J& w% v
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。
. V. E( U' ]' d& O* q/ t2 t+ F- F下面是具体看到的信息 : M/ w* v- ?' l7 s0 L1 s
( H0 r- p- t9 a$ |2 Q/ S
T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
: L8 }. {5 E5 }5 a/ d8 rB: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
: `, a3 j L2 ND: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
p. r+ [- j' b1 `. r# LP: Vendor=0000 ProdID=0000 Rev= 0.00 1 v7 O% t1 m8 J r
S: Product=USB UHCI Root Hub ( T8 P0 O- Z5 G/ G" A% ^
S: SerialNumber=d800
2 O. C1 ?7 T0 \6 k1 Y- [C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
+ h4 X' Y0 r- v4 e8 v- b/ eI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
0 M, h7 T6 |( Y& t b" I' {& EE: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
' r2 {+ V6 K' k m/ T3 DT: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 $ @% K" U" `" }; X, L
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 ' x! p' K6 a1 L3 g- N
P: Vendor=07e4 ProdID=9473 Rev= 0.02 9 c. E0 Y& g" I' w5 n
S: Manufacturer=ALCOR % I) Z* F% P5 o/ r# s) {
S: Product=Movado USB Keyboard - j3 Z7 T# J# j$ b
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA 9 u6 K* C7 P- y" b2 Y3 R h
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
9 h/ M9 D3 z7 l: y, m6 aE: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms 4 a1 c. o6 v& |3 Z8 Z! x: o
找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中
$ F' i7 t' x+ A# v/ Z$ K$ {& _( s( G" e) R
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 8 M! J5 S) d9 F: g$ s) ?
usb_kbd_irq, kbd, endpoint->bInterval);
4 @! E0 i7 r- J4 p* P# r+ Y) m8 l! x0 h# h4 D& N
一句中实现。 8 j+ ^& U! R( W+ W- P8 X- e
从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。 ; N( g. ]8 Z: W
在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 * i7 _0 p) C& i5 e _, i: v
程序见附录1:键盘飞梭驱动。
. E9 N9 j- a ~) B9 Z使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。
! Z' A8 ^/ N; j8 j% S9 e参考资料 4 @; S) A" }" W( l
1. 《LINUX设备驱动程序》
, N) O& a) h7 Q% h8 H% E! ?ALESSANDRO RUBINI著
; \: c3 X3 z2 g6 L, w' tLISOLEG 译 9 `( D5 r5 B4 ^
2. 《Linux系统分析与高级编程技术》 ; l. ?/ r u2 p. l% d9 e
周巍松 编著 + Y' b( F! L1 }; u* g
3. Linux Kernel-2.4.20源码和文档说明 ( c p5 d! D4 ~ p- {' K. `
附录1:键盘飞梭驱动
; t1 s& n2 ?$ ^- ?% F: G \
7 D5 u' P3 _4 j4 u1 X, X#include <linux/kernel.h>
4 u& f8 B8 }6 m#include <linux/slab.h>
+ }- `# H& B4 ^/ d; Y' p7 k#include <linux/module.h> / C X0 J2 w2 u8 v; {! T
#include <linux/input.h>
% K2 n7 V6 @* y+ P0 m#include <linux/init.h>
8 Z( B8 B+ j) z1 J6 R7 o# C#include <linux/usb.h>
1 Y- p9 B; p& @. X6 F, y+ \/ V$ k3 k; T#include <linux/kbd_ll.h> ) s3 t5 v7 j: `0 F( O8 `
' I1 j; V7 O2 \6 w9 O* o- a/*
5 s$ s7 _* W- c5 m- L$ E2 i k * Version Information & |) b6 m: g" w# m
*/
+ ]- b: L0 a) I/ q' X, z8 n#define DRIVER_VERSION "" & T6 ^9 q# E1 B# i
#define DRIVER_AUTHOR "TGE HOTKEY " / w+ w: U: O' |4 H2 _' e
#define DRIVER_DESC "USB HID Tge hotkey driver"
9 X( `- g/ S: h8 U$ s9 l3 \4 R& x! t
#define USB_HOTKEY_VENDOR_ID 0x07e4 : W# C' z2 B! F3 `, c: w G& U
#define USB_HOTKEY_PRODUCT_ID 0x9473 7 N3 K7 P! u. k' i# }$ |
//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值 ; U5 Y* e4 p s+ \6 I- N& C- H
6 }& C1 T6 D; z0 ~0 R6 oMODULE_AUTHOR( DRIVER_AUTHOR ); * {/ E% C: ^: t( l' r, H2 n
MODULE_DESCRIPTION( DRIVER_DESC );
' A; @& ~1 M" ?' X! @0 z
3 U' T5 Z" W6 L9 g6 n) v% nstruct usb_kbd {
5 u/ b& J s* A$ ?3 xstruct input_dev dev; : N+ A% r: ~* H
struct usb_device *usbdev;
. b4 y* @, g" A3 ?( V# ^unsigned char new[8];
+ h9 r' Y# }- c" _7 t6 Cunsigned char old[8]; ) Q# U4 I3 X5 v# W
struct urb irq, led;
6 _7 O4 S0 j$ ~! u# i( ]( [& v// devrequest dr;
?* o8 u; O! d+ p# ]//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化 ; P& l/ F0 ]& u- W3 c- L6 d
struct usb_ctrlrequest dr;
0 E- W3 M5 h& Y7 sunsigned char leds, newleds; ! d: ~- W. l) |+ L' }9 m5 g7 U
char name[128];
' ~. e2 P- ^. Z, m. c* Cint open;
9 i' S4 h. x4 \% O}; 1 J. {- O" `" }! ?$ o* w: T: x
//此结构来自内核中drivers/usb/usbkbd..c
/ A* d4 ~& q0 t9 v8 n3 a+ M, d2 m- J1 b( J/ X7 t9 t6 E$ t
static void usb_kbd_irq(struct urb *urb) ! C5 V; m- n3 Q" ^
{ * V3 J& z- x& d, |' K
struct usb_kbd *kbd = urb->context; 0 B: I- K4 O# ]! V1 _
int *new; ) R" i5 a, ?8 T% R9 N. c
new = (int *) kbd->new;
4 c3 z+ u9 U1 _# J
+ @' P; b# c' ?) `& Aif(kbd->new[0] == (char)0x01) * T0 Z: a6 s' U( p3 t
{
8 z/ `9 c; D4 y; _7 yif(((kbd->new[1]>>4)&0x0f)!=0x7) / V0 g, `7 |; e! X# y) A' |
{ & R5 K) ?. O6 M4 H8 T0 ^1 @; h
handle_scancode(0xe0,1);
B/ \0 d, A2 h) E4 C; phandle_scancode(0x4b,1);
4 s* F* _6 G3 B% [ handle_scancode(0xe0,0); 5 Q# J6 W: E1 M H- c5 O2 b$ e
handle_scancode(0x4b,0); , n8 x1 l0 i% H" o
} . y7 I9 L& R6 E! U* H8 `9 @0 @
else
- O7 K, k$ O9 e& |; T) P{
1 C- G" L$ R; Y( ^8 q% x7 \handle_scancode(0xe0,1); 9 y4 B, c( C$ L/ q% t2 g/ M1 N
handle_scancode(0x4d,1);
; I5 M' w! Y1 I2 B4 o: s; p% B handle_scancode(0xe0,0);
3 c6 p3 c, l$ a handle_scancode(0x4d,0); % b" }9 ]6 R7 Q/ U) P
} - V3 X! V2 ?/ x
}
) m. n, r7 L7 c& A. s8 m) P4 K8 ?2 m1 r6 F6 o. P5 D
* F& L8 Y& F2 ]4 I Kprintk("new=%x %x %x %x %x %x %x %x", ( }: P' T$ t* ~, v% O2 i
kbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], ' R; |8 j) e; X5 b5 [, A
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]); 8 P& g; ]- I3 c$ b% n8 ]. V2 ?
0 ?) B& _8 P1 _, M7 Z. u _}
* I4 A6 G: I& z. H2 [+ d( J( r& M$ E/ T) E* y6 s+ |3 Y
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, - \3 H0 P+ j, d2 U
const struct usb_device_id *id)
" ~/ R# r& s; f6 h0 g{ 5 m) C7 u+ [3 J9 ?2 g; a
struct usb_interface *iface; * |6 h z1 h L( h
struct usb_interface_descriptor *interface;
7 |/ m. Q. e' f& q, D: Gstruct usb_endpoint_descriptor *endpoint; / f% b1 K. ~/ W o2 L, V- Q& u
struct usb_kbd *kbd;
/ X, y- ^7 N i4 b$ w! y$ g6 k6 k int pipe, maxp;
2 `1 | O( ~' D5 [( Q9 b. z7 X* N( x7 w9 z, {$ d) a0 m
iface = &dev->actconfig->interface[ifnum];
: t1 X! J$ N: l2 \. R1 n interface = &iface->altsetting[iface->act_altsetting];
& V% E0 e" A, S
& _, A" e4 g$ c1 }if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) ||
! e, m# Z4 e* I ]& I(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || 5 E8 m7 e* `; F. s) m1 z
(ifnum != 1))
. R% D, y$ }0 y1 C0 ?{
: y5 U& C0 R$ g0 u# l: P' X3 Mreturn NULL;
6 s" R8 Z: S9 y2 E}
2 _1 y. \" L6 }3 F+ v4 n7 ?if (dev->actconfig->bNumInterfaces != 2)
$ M% ~) k9 K/ V8 L- Y8 C. J0 V{ " t- ]/ Z0 [. g& C& f, a1 G$ u
return NULL; - u0 W& l. l: p: }" Q
}
8 A5 _6 [1 W9 T; M* X# P- {( b/ |. r# m0 v7 m( f
if (interface->bNumEndpoints != 1) return NULL;
; }8 a3 O! R, A l" Z+ Z/ `7 c0 `2 d
( A; }) A- ^0 h1 q( a endpoint = interface->endpoint + 0;
2 D* G5 T; f4 p3 R
6 w* O' [. c$ z6 p: Y$ Y pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
, w9 u' l5 v7 D# q4 f! U maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
3 w) F& B3 z, x2 m4 n# d* k) {5 [0 _; \* r7 F5 s- [3 R1 j
usb_set_protocol(dev, interface->bInterfaceNumber, 0); 5 Z" P, V) q" ^( U4 h
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); 7 Q5 B( C7 j! D5 w, G- `7 |
2 X, Q( o/ t0 P: [. U
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n", - V: w8 g) m/ I" R. Q& @
dev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp);
5 u5 T" p4 f: l- L7 ^, W
( g$ e9 }* s. F; R; g& f* f if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
0 { y$ Y2 t; _; J memset(kbd, 0, sizeof(struct usb_kbd)); 8 ^: q) c% J7 w6 V& Y" j: E9 B9 x. B
, j+ y) R5 z& }- n$ z- s
kbd->usbdev = dev;
6 S8 g) U! f* j5 F! p; @
. i8 H! C4 G/ G* z; i0 e" t* F% p FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
+ N$ [' f4 {( m3 gusb_kbd_irq, kbd, endpoint->bInterval);
2 X# k$ P2 i) W& e" w8 W$ V+ r0 {5 d! x
kbd->irq.dev = kbd->usbdev;
! P( J" R( Q9 S% C: R* u4 R$ P
" C& V$ n, R L, \if (dev->descriptor.iManufacturer)
. _* _5 b( K4 ~# i usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63);
$ B7 V! Q6 F* i4 f0 H5 k: _0 D
# U. N' E7 C7 N0 `: vif (usb_submit_urb(&kbd->irq)) { 0 L" V5 `2 p- R' d6 H6 v$ X5 u
kfree(kbd); ( Y- x' x0 Y% o' ?
return NULL;
# G8 P" b- F Y+ f( h8 M+ {) [ }
4 o3 b. b! S! K
8 g* I. [5 K6 r- U. A0 aprintk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", 9 R, v) o# O# d) W
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); 7 n2 N$ q- ^9 D# ]
' y2 O# B- J! }9 {7 l
return kbd;
9 c) A0 V+ W; U1 o% z; m} 7 n0 X/ K2 ^6 B& ?( l$ [6 [
6 _. r4 E9 D8 G0 rstatic void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
) L' O1 G7 M' c6 J5 R{ " Y3 L$ a+ {: \, h( Q$ Q
struct usb_kbd *kbd = ptr;
7 @) Z% N3 c+ y6 ^& l# ?$ ` usb_unlink_urb(&kbd->irq);
1 W+ F- K9 h9 A kfree(kbd); - V3 @; A9 v p
; L- c+ Y2 z- z- j' r
} ) u" Y: S5 ~& u, k
0 w0 w: X5 G. u5 z# F; t9 j5 e& {static struct usb_device_id usb_kbd_id_table [] = { " d) Z& f( E D3 T7 Z/ r( f& j
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) },
# L; `8 u( `8 E/ S$ f" o1 i{ } /* Terminating entry */ 2 a N6 \0 F5 C2 c# s3 u
}; + U2 T) o( ^- ?- k% H8 C
K! |' D1 ^5 H; [" U. [# `; e
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table); + a" @* X. k( e9 k$ J) D2 ]
( Q. j* x% c l9 Q1 R Ostatic struct usb_driver usb_kbd_driver = { + X7 ^. j x! m" w3 j6 N
name: "Hotkey", ( A0 O" M/ B' Z1 y- \
probe: usb_kbd_probe, O0 d0 L( j' L3 m5 _4 y: y
disconnect: usb_kbd_disconnect, + |; \7 ^1 A4 g/ X+ s$ D! h
id_table: usb_kbd_id_table, 6 t5 p H J. P! P+ D
NULL,
/ S: F; J P% u9 ^, }* E3 H}; % `6 |6 _$ F0 o4 ~3 t6 B9 m8 \
2 M1 O; q( J) O$ L' w1 Wstatic int __init usb_kbd_init(void) 9 s- T+ O0 I" R' f
{ + j1 `% h, T5 n5 \: _
usb_register(&usb_kbd_driver); " o$ k2 k5 z- b. Y# r2 a% k
info(DRIVER_VERSION ":" DRIVER_DESC);
% r2 G N1 c7 t! `& U) T' Z/ { Qreturn 0; : T* e) v6 M7 [3 G, R
} - r# q! d# |1 ]2 u
, J6 t; B3 W ustatic void __exit usb_kbd_exit(void) # n2 ]" W% H. ~
{
8 Z& N' R' V& d2 S: E- |usb_deregister(&usb_kbd_driver); 2 i- Q" [/ T$ e9 Y+ n
} 3 i* F; I6 W. a% \7 g* O6 y/ p
- k: e+ u+ {7 r2 f3 Q+ G" K
module_init(usb_kbd_init);
& ~0 r% f( e% b" W3 y& {7 Tmodule_exit(usb_kbd_exit); |
|