- 在线时间
- 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,
- ]% v7 r9 X+ ?! t. O! @- b L0 F" USB ", " Mass Storage ",
. A) q' w) B8 v* T! ZUS_SC_SCSI, US_PR_BULK, NULL,
7 ^0 C' Z% a; F; q. @: oUS_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE ) 9 W# T- v5 k: [$ n. R4 z7 q
5 y! X& e* R! x* x8 B# ^注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
* ]5 h+ |. g' S' u+ n o+ x {最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 ' I& `3 R0 l0 ?/ }) `- k& t
键盘飞梭支持 % X8 O% V0 h9 \8 W; b
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 ) x0 s. q6 d7 K3 r, p; v
下面是具体看到的信息
) p+ Q0 b+ R, U5 x$ Y0 l9 L, {0 ^, J V* A7 o
T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
. ]) k4 @/ `" |7 n: l, P5 @B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
/ _4 h( O$ C) E, s( nD: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 6 {8 ^$ b6 Q" ]: D
P: Vendor=0000 ProdID=0000 Rev= 0.00
5 ~2 v; ]* p- r$ @S: Product=USB UHCI Root Hub
% F4 f$ C4 m4 P/ w" v' CS: SerialNumber=d800 ; }/ H* e) _$ }6 Q3 q' X$ Z+ }/ O
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA 5 {: W1 W3 O# a. Y" h1 c
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub 7 _9 l/ B8 C, {9 u9 W8 F$ g
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms " ]9 M. N$ i+ K7 b2 X: ]; I; V7 x
T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 6 X# i3 n; E Q( p) f& s8 R, X
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
" B6 J$ O/ k$ g9 u9 eP: Vendor=07e4 ProdID=9473 Rev= 0.02 ( Z$ B4 j( Q: R' ]! {# Y' d
S: Manufacturer=ALCOR 7 Z' A9 ?' N0 d4 q
S: Product=Movado USB Keyboard
" n; F9 k) X+ ^# e& J3 A* oC:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
: H9 f+ K2 G3 T0 I6 F4 l5 ]I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub 0 B; n$ H$ T# ^" p" r5 q1 B# F
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms 4 v. M. O. M4 @) 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函数中
3 N. T6 W7 \. A, L$ ^5 O B4 `% Z/ ~* k2 a& v
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
& i3 l$ ~9 T3 ^/ s2 X" J7 Ausb_kbd_irq, kbd, endpoint->bInterval);
1 j" Z/ `3 g# T7 x2 p0 y
% [1 M3 N! j# X$ G8 d3 z2 V一句中实现。 4 Z5 _( ?9 G; A# T0 l R
从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。 , }7 [ B6 V% c- w, f
在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 - X. a% g% v0 `, J; V1 H' F
程序见附录1:键盘飞梭驱动。 , s3 H$ {9 q, ?& _8 z' T6 Y6 |: i+ v
使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。
0 m' i! |1 b" O" }+ J' }6 I参考资料
- q4 k, Z# W$ a1. 《LINUX设备驱动程序》 * I5 V B1 H7 Z0 x
ALESSANDRO RUBINI著
2 I# N: Z/ n a- c, o8 i/ W" Z2 A6 d% PLISOLEG 译
8 m/ S3 {2 {/ @) g2. 《Linux系统分析与高级编程技术》 M7 z+ C7 V" u( D' S* `% d
周巍松 编著 5 K2 G1 n/ ?1 Z0 ~
3. Linux Kernel-2.4.20源码和文档说明
2 `( [/ U" r/ b附录1:键盘飞梭驱动
2 N' P! s2 B0 O8 E
3 k7 O$ w" C, a! y& U* u#include <linux/kernel.h> ) T) y, o+ n9 S3 B# F
#include <linux/slab.h>
7 V) U8 Y9 U. o* y+ g8 N$ J( D#include <linux/module.h>
' V- ^0 c7 c9 G9 I# i#include <linux/input.h> 6 D. i+ m" f S5 z; p, W4 |: B
#include <linux/init.h>
C7 d( p- J5 S: V#include <linux/usb.h>
$ Z$ H" y$ U, q8 {#include <linux/kbd_ll.h>
/ W3 j% ~) M* T5 B J0 y8 u' t6 q# |1 E# o$ h- s5 v d
/* ( Q v3 Q) E1 S
* Version Information , {1 B, n! k+ z% x
*/ 3 h- n" h+ O T' T: C7 J
#define DRIVER_VERSION "" 0 Y* Y) `! ]* A$ [1 O
#define DRIVER_AUTHOR "TGE HOTKEY " 1 U E- ]7 G3 S1 q! _
#define DRIVER_DESC "USB HID Tge hotkey driver" $ i& T3 B Q; U5 e- x7 p: h
* K, j% } g1 e% e, e& }/ d7 _$ k
#define USB_HOTKEY_VENDOR_ID 0x07e4
( S- N* [0 x, v; @, G#define USB_HOTKEY_PRODUCT_ID 0x9473
3 U7 J# l' ^& E5 {' _4 @//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值 9 j1 p7 I4 t& }3 c4 Q! I
, v' f& t! a+ r1 C7 n8 \5 j6 b
MODULE_AUTHOR( DRIVER_AUTHOR );
; W l I$ X# {! V5 bMODULE_DESCRIPTION( DRIVER_DESC );
; R: s; G/ ?3 |* x3 x: H, ^) @5 k) n3 W- ^" x( M0 c
struct usb_kbd {
: H1 ?# w" T! e5 o! @; rstruct input_dev dev;
8 O2 {9 R; W( E: Y# Mstruct usb_device *usbdev;
x/ Z6 y5 t) j1 o |+ l( ounsigned char new[8]; $ c8 Y* E8 T" p7 v/ Q/ R' r
unsigned char old[8];
, X% O* r- n+ }struct urb irq, led;
8 G, O/ {6 L1 R- ^// devrequest dr; % m0 X- w: `) X( l6 V
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
; g$ c. f) L# H/ G6 H, t struct usb_ctrlrequest dr; & f& V" z- ~, b2 }8 m
unsigned char leds, newleds;
; T3 s) ^$ H; t9 }3 T; Z2 Zchar name[128]; , Z, L; \0 _ Q5 f
int open;
( D/ n1 e% I$ X6 O! w, M) p, z};
+ L/ G; e, A. D9 W% x7 N# m4 c, F//此结构来自内核中drivers/usb/usbkbd..c
- u3 m4 U6 q! e3 P6 }2 f5 B, u& V9 T9 }9 ]% P8 P
static void usb_kbd_irq(struct urb *urb)
5 C5 P- {+ L! N. d) n' R{
: K# @; g4 B. j/ R9 @struct usb_kbd *kbd = urb->context;
" H8 k j' f7 | f: w int *new;
# M; R. c0 P5 r! L p$ w1 l new = (int *) kbd->new; + c( f6 }) W/ U, F# t6 `) Y
$ T0 n% c) x7 ?. oif(kbd->new[0] == (char)0x01)
5 ?. ?8 E" ]- A% w1 B2 k# x! ^* c{
6 g1 R! w) E9 b- E6 Zif(((kbd->new[1]>>4)&0x0f)!=0x7) 9 ^; s, @9 a) D# E) |
{
q8 @2 ^& T; Y8 U- A2 Zhandle_scancode(0xe0,1); 9 [9 G0 z8 F$ e& Y/ S
handle_scancode(0x4b,1);
- Z: Y; T3 X( e" }% U handle_scancode(0xe0,0);
: O- f' v7 W ]2 m handle_scancode(0x4b,0); : Y7 y2 p. [/ n6 p, `
}
* y# {7 p9 B uelse : Z2 S' J1 u: h$ U
{ 2 M% J6 n8 v+ Q% n. I8 t0 @5 ]
handle_scancode(0xe0,1);
' [6 X- p% ?6 ?3 H* R: A; D B handle_scancode(0x4d,1);
8 k: }3 `" t; |8 g handle_scancode(0xe0,0);
1 N% f6 e& k1 c8 Y$ |# Y# n handle_scancode(0x4d,0);
4 i' P5 F- M' X0 }} 5 M5 X" t, H$ D) T
} / A( d9 W4 Q" }2 [6 R- V% N
' |+ N* j! A2 H
5 E- ^* ~( [/ @7 B! r( p0 p0 j0 y3 Pprintk("new=%x %x %x %x %x %x %x %x", 5 g! _( S9 V; \/ ]
kbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], 5 q9 I; j% a. `; g
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
% T$ o" }8 k4 J. {2 e4 p# F" ?1 @0 L1 R9 L+ h7 [
}
2 k4 h3 g U1 {. Y8 ]5 ~: V* B# v/ s% b
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
; x0 y* Y5 \4 b3 F- D const struct usb_device_id *id)
1 I: z/ o& q% b. m7 Q6 X5 J{
, B: i- @) a2 q3 r7 y4 X# Gstruct usb_interface *iface;
: B0 \& _( l. v# J struct usb_interface_descriptor *interface; 5 M) y& ~9 H0 z
struct usb_endpoint_descriptor *endpoint;
. n3 A; p+ ~3 l: m7 o struct usb_kbd *kbd;
" Z1 J7 i. b. g int pipe, maxp; 6 r2 e1 R3 y7 X7 O0 u6 h
0 d) ?2 W8 v. n6 @( T4 S" Ziface = &dev->actconfig->interface[ifnum];
, G) k/ \9 q6 }: t: k& l7 I# ^. I interface = &iface->altsetting[iface->act_altsetting];
$ z- z8 \, M% |! R5 j
, n$ n2 q& \ A$ R' eif ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || ( {& d1 I# |# {, @( n
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || 7 Q, b* K3 t& J, e
(ifnum != 1))
% d: o+ m: v. L) G5 ]! F# X) w{
( o% q9 ?4 u0 breturn NULL; / y: P; k$ P1 N/ O" U7 i c% L S
}
3 y; f! V# K) b, |( K: s- nif (dev->actconfig->bNumInterfaces != 2)
9 L! K; j! f4 J6 \7 H/ x{
J! [1 ?/ q% A, [5 Y3 Treturn NULL;
+ P- M8 \- B# w; N0 Z8 D}
% i: A5 w( {3 O0 U6 i- ]6 F1 @( D+ C; d6 ^
if (interface->bNumEndpoints != 1) return NULL; % K& N# `9 G* f1 A! F+ j$ U
, o) C: i' A% L9 o1 |/ y endpoint = interface->endpoint + 0; 4 i1 p& e/ {; Y7 ?
8 W% p4 h l; [" K" O& M, @ pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
. Q0 v: n$ J: U* ?/ V maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
, g6 l/ ?3 Y. Z, m3 R n" l$ \. f* s! E) t2 f
usb_set_protocol(dev, interface->bInterfaceNumber, 0);
; _/ A, D. v1 z* R% Z usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); ( {! z$ D+ s8 `: w J3 I b
$ |6 \; E* L5 o `( mprintk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
# z& M0 [- P5 d0 W/ I! Adev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp);
2 ]4 U& x$ V% `+ X0 n0 i3 C* p, p- t& g& @- V8 B
if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; ) m# \7 t5 S: a
memset(kbd, 0, sizeof(struct usb_kbd)); ; w1 G5 f2 S9 C/ y8 n: d
8 s* ?3 l4 H$ R2 ^0 M' g9 a kbd->usbdev = dev;
1 t( {, O' O6 P k$ P$ a z5 ^
0 A3 ^% B* K" W4 c; N FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
5 F: J) B, m8 w3 S5 p0 Iusb_kbd_irq, kbd, endpoint->bInterval); % z0 B+ o# x/ f) Z- x8 d2 H
# L( R7 Y( Z, C
kbd->irq.dev = kbd->usbdev;
$ @- @& E7 {; a6 {' ]; A. G. K C
if (dev->descriptor.iManufacturer)
& z! e% C0 b8 K usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63);
" q# N' L6 A9 j& N+ l" a! V
+ `6 X* S2 J4 {1 B* dif (usb_submit_urb(&kbd->irq)) {
- y, d- T3 @: C% \2 H- N kfree(kbd); $ a! Y% F7 J$ H; n6 D
return NULL; . e; p( y! Z# r
} 5 {( `# [9 ]' Z) D
3 z( _# Z! Y# ~printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", & q# Q1 c7 v g1 @ R
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
- o( H' ^/ l% X7 Y- G0 i# m9 x$ D5 g
return kbd; 2 Y( A( e' X/ c% ~
}
) M& y7 E7 U. x/ e
3 o* o4 g: W; vstatic void usb_kbd_disconnect(struct usb_device *dev, void *ptr) 0 ^" [0 I9 s# P3 e! F3 B4 x
{ $ {8 B1 q( W9 J
struct usb_kbd *kbd = ptr;
- N1 j/ P0 `. R7 @' S$ R8 [ usb_unlink_urb(&kbd->irq);
: h; y# J2 D. j1 Y" L! b& z3 u- }3 H& M kfree(kbd);
3 N; ^# O# c2 a T5 V/ a" N5 d, P/ v5 R% I; |, P1 r& r
}
X, r3 O/ [( s: Y B: H
+ A3 }; S) B! e- o8 P" K! @7 Kstatic struct usb_device_id usb_kbd_id_table [] = { 7 M% D W* Q5 t
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) }, $ Z$ ?' h; C/ r
{ } /* Terminating entry */
0 u, g6 C1 f& e6 H2 r};
7 F, \ g8 u) Z0 k7 Y
9 P2 l( d; q2 i$ m7 Z" j: }MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
' b- T! A( V' v" {" [3 C9 `
& U, a5 S4 P! M2 ?9 ?7 G! ~: cstatic struct usb_driver usb_kbd_driver = { ; h* b0 x' |& [9 g: t
name: "Hotkey", 5 y" M* m+ W% @
probe: usb_kbd_probe,
/ w% P; ^% n: R* A k& ]3 Ydisconnect: usb_kbd_disconnect,
& t% X) K2 u) T6 o5 n+ T% Bid_table: usb_kbd_id_table, 8 _' G' ]* v- F% Z# L
NULL, " r$ N7 L! g% L7 ?
}; * c5 }7 Y, J8 d! c; R& V
/ @3 Q: W5 K: Y" \1 D6 Estatic int __init usb_kbd_init(void)
0 |' {! X) {! B* f% G9 U{ " D; V% H! Q I& K% V
usb_register(&usb_kbd_driver);
# W* I8 M. Q- v2 ~9 Sinfo(DRIVER_VERSION ":" DRIVER_DESC); & x: P9 O3 `/ E* V% l3 q
return 0;
2 i5 m% T0 _) x% d, z. n} ) s/ _( ~9 e% S% e% n" b& q8 L
" C% f+ f% }3 _) I+ mstatic void __exit usb_kbd_exit(void) / t# p- `7 S2 c8 K
{
: ~, Y$ Y- z6 Y; Lusb_deregister(&usb_kbd_driver);
5 D2 V* a0 M9 c$ d* y}
2 G3 H) `, z' ^0 t" v j ~' F4 J; h: A& O. V' j+ y
module_init(usb_kbd_init);
* l( N3 A5 m# \0 H" E& N9 ymodule_exit(usb_kbd_exit); |
|