- 在线时间
- 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,
5 d6 Z3 j1 I5 C; F f, G5 T' r" USB ", " Mass Storage ", 6 E; v0 y7 i1 {5 x+ R/ Y
US_SC_SCSI, US_PR_BULK, NULL,
6 j; k1 p8 X$ l) c+ nUS_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE )
$ L w: A/ \# J, D
/ D% a) Z! w+ o- P; Y% c注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。 : `) I7 E. z D3 X3 c4 p
最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。
' h% n6 c& _) r7 N0 w; y; V3 Z0 [9 S键盘飞梭支持
( X: s& `; a: b' J目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 ( o$ v$ i, G& G0 L! [* J4 q
下面是具体看到的信息 " a A- m5 o, l- u
+ n. d! V f6 ~# ~# ?; A
T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 - |% u6 H, R8 \2 c, I
B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
+ M2 S' \7 ^. zD: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
8 Q5 }5 O; U- g5 @+ _/ q2 \% {P: Vendor=0000 ProdID=0000 Rev= 0.00 6 }/ b2 K# \8 o# J. O v
S: Product=USB UHCI Root Hub 6 I4 T _0 N* {# n( x) B# Q
S: SerialNumber=d800 % J* c8 P6 j8 f6 M" m3 D1 v
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA 0 L8 _: _8 y7 g1 ~: }+ [+ R3 ^
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub 1 k9 E- v9 s$ b' i9 Z W; A
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
6 S1 p8 z9 j5 y fT: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3
' n' V4 b! P" k- ?: i: t) u; vD: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
' k% f8 d; A& C3 t7 d0 P4 ]P: Vendor=07e4 ProdID=9473 Rev= 0.02
7 ~2 j& ?8 P6 R# N) s; GS: Manufacturer=ALCOR ' l9 Q7 Q& e! Y B7 X
S: Product=Movado USB Keyboard 6 D' m2 w0 X8 V# R4 a/ c" c) \
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA / h; W P2 ^0 L0 Z: a4 J
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub # ~( W& ^* L% u
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
& ~ e, U. @. V( J3 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函数中 ' z8 f. f/ U6 i. ]; B
! { C7 |4 v8 ~/ Y( A/ E* w; p
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
0 L- S: q ^5 P8 Z/ J' V _usb_kbd_irq, kbd, endpoint->bInterval);
8 Q: i2 o: }' N% W9 E' y/ z2 |% H/ r, j4 o/ r$ S- y
一句中实现。 9 A+ _4 v Y' I2 Z
从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。 ' w1 k T$ |' l: }# w& y$ O6 G
在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 5 t Q* v" g& n+ [
程序见附录1:键盘飞梭驱动。
. D4 Q& @/ i: X* y/ F使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。
" l9 A( m, V6 G参考资料
. r) e" E- i; z5 p; z1. 《LINUX设备驱动程序》 # V9 |! V( C& z2 C* L
ALESSANDRO RUBINI著 ! U8 ]. T* d! R/ j, ^, x
LISOLEG 译 1 t4 ]) v+ {" _5 A& d
2. 《Linux系统分析与高级编程技术》
[$ k3 i! k& q: ]4 G' O9 C周巍松 编著
# E% n1 |1 k* A. G3. Linux Kernel-2.4.20源码和文档说明
3 u( i, r4 F9 b8 z2 |附录1:键盘飞梭驱动
- l q0 F* k( v3 S8 P" z. J q- q
$ l# V- m& J W; ?8 v8 S; \3 P#include <linux/kernel.h>
2 R* C- A% N* z: z+ f% \5 D: b#include <linux/slab.h> 9 C) Z2 A$ c+ y
#include <linux/module.h> ; N+ y: l/ c ]0 }
#include <linux/input.h> ! K! b2 }. E( u5 T
#include <linux/init.h>
6 u6 D+ ]# l( p3 j v0 b' o#include <linux/usb.h>
- E3 o7 A% s A8 D7 {" t0 s8 @#include <linux/kbd_ll.h> ! J1 a6 H0 F5 G
; s. V% |4 _- |/*
8 H7 s/ j) V& Q$ y" G0 }7 R * Version Information 4 c" q- _# f4 B! @7 ]# d8 I: f* I. s3 n
*/ + o$ t% t8 P6 C! Q
#define DRIVER_VERSION "" + s5 ?* `* ^0 u$ i
#define DRIVER_AUTHOR "TGE HOTKEY " 8 z: Q8 E+ K, U) v: n$ n! x
#define DRIVER_DESC "USB HID Tge hotkey driver"
6 H+ O. Q7 }$ J7 g5 \
. ?* S" i1 Q2 ]# g d% F. |#define USB_HOTKEY_VENDOR_ID 0x07e4
: f" p/ @ N& b1 U/ h" [+ `#define USB_HOTKEY_PRODUCT_ID 0x9473 4 }( [9 i6 Y" t* y" n
//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值 2 r: f. | b5 X
6 k4 P7 n- C3 t; c4 `
MODULE_AUTHOR( DRIVER_AUTHOR );
8 N% c2 B' S6 xMODULE_DESCRIPTION( DRIVER_DESC );
& x8 `; E; y- _( u/ U' T0 r2 C3 s1 q0 R
struct usb_kbd {
: D y8 \2 A9 h( }struct input_dev dev; 8 X1 l, E" b |/ M
struct usb_device *usbdev; " \$ |2 g8 Y3 @# \ Q
unsigned char new[8]; $ e. w' G$ x) G5 A
unsigned char old[8]; " y) H- z' m. E+ s' j
struct urb irq, led; - J/ d3 z/ e6 g3 ]
// devrequest dr;
) b2 z4 g1 B' d5 J, X G" o" H//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化 " p" Q9 b# j3 [8 T3 H E
struct usb_ctrlrequest dr;
9 _2 S# G1 ?* U6 g- Cunsigned char leds, newleds;
' e4 s& H/ P, \: i. _8 N4 }' a4 \char name[128]; $ {+ p1 F" Q0 D9 p
int open;
$ K d8 G4 w0 w: I}; - K- W+ L$ n" O- G
//此结构来自内核中drivers/usb/usbkbd..c ! E4 [& {% Q3 o6 {* u2 b
% f6 P' m* ?* Ostatic void usb_kbd_irq(struct urb *urb) + U! |; u+ |' T7 ~6 t/ O
{ * k7 A( j& k1 ?% z5 a0 ^" i
struct usb_kbd *kbd = urb->context; 8 `* P5 A" z5 g
int *new;
$ f4 \% p9 [% [% M! ` new = (int *) kbd->new;
/ X, N4 g4 q2 b1 Y2 b Z: R. x6 n W
if(kbd->new[0] == (char)0x01)
4 U4 D+ x, Z3 P4 M" Z6 V* z. h; Y5 v" q{
$ ^, C1 [ Y* f( b! oif(((kbd->new[1]>>4)&0x0f)!=0x7)
+ F/ b2 T$ @% i9 I0 @8 P- [{
$ e1 F, O+ s, p% P5 C" U" i! m4 A0 _, Jhandle_scancode(0xe0,1); + f8 g+ k7 f: y1 ~4 J0 R) `$ U% Z
handle_scancode(0x4b,1); 3 K+ U+ s& i5 y' s; D
handle_scancode(0xe0,0); ' D R" S3 H# w% i4 }2 o# }
handle_scancode(0x4b,0);
5 I9 F/ X w. L* l; s2 l' T! h} $ l' T. {# I9 G! L8 L
else
( g4 I* N ]0 n' D1 U7 {3 A{
j; `2 _: \2 y- X1 Fhandle_scancode(0xe0,1);
6 O: }8 Q0 q) a' f$ F handle_scancode(0x4d,1);
, F- U" _+ ]' D, ~; e; p handle_scancode(0xe0,0);
- n. [' G9 g; D8 C# \ handle_scancode(0x4d,0);
! f( ^8 \! @! y k2 T# i; H}
/ P9 k) k8 _, j J4 z; m} * Y1 `8 w8 I6 r0 U: ?6 n9 E) [
% _: {. V# M* r
1 X& i1 G# |4 C2 e6 N; C
printk("new=%x %x %x %x %x %x %x %x",
9 r8 x" u3 M. n+ P8 v$ k0 @3 O, \' bkbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3],
$ |* ~) z$ J& w7 u1 Mkbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]); 1 o, H' u' \6 V# a
, Q1 o$ t& k( a9 d} ' r. O+ T: I. `; S
^# S* K2 z( t% E( s4 r* H
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
3 f# P8 @6 L( x3 R4 b! N7 _ const struct usb_device_id *id) . h% Y6 Q2 F* j: J& X
{ ' |& {7 i$ V D: y
struct usb_interface *iface;
$ E+ |6 }+ h2 [: E- F9 z1 `! v struct usb_interface_descriptor *interface;
3 V% H. C8 J; r* \, \' B lstruct usb_endpoint_descriptor *endpoint;
3 G3 i. }- ?8 G! [ struct usb_kbd *kbd;
9 x. E9 X2 k' q1 I3 @) x int pipe, maxp;
1 `( M1 a$ O# k' `( f1 j
; Y9 @0 B! k) V' biface = &dev->actconfig->interface[ifnum]; 0 U% ], I; f4 \( v
interface = &iface->altsetting[iface->act_altsetting];
! n# h* K+ s0 Y* c X# n! ^$ U6 n/ }* h$ K& P5 Q$ o; p' X
if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) ||
, M5 B' Z9 d2 o/ X. Q( v& f$ Y6 F+ b(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || 0 v* z0 M5 e o4 C( u
(ifnum != 1)) 5 p% E, B& O0 @) i8 D u3 \$ {# d. B
{ 0 e) W- A! e" @
return NULL; 0 l# `3 I9 |, t! d# Z
} . h2 S. c- y+ P7 U$ f& H
if (dev->actconfig->bNumInterfaces != 2) 9 T8 A4 t+ S; J4 ?7 L* t
{ 0 C5 m5 o/ v: H% U& u
return NULL; 6 O- |7 ?: c- E. n! {& z+ e+ u. Q
} " n* d: h2 `! x" w
& }- T: F% V! J" vif (interface->bNumEndpoints != 1) return NULL;
7 J4 F6 n. N5 ~
2 ~; C+ r; ` \2 e# h2 k( F: ~ endpoint = interface->endpoint + 0; ; x& q7 C- j0 N% W5 S
) |8 B' A8 Y* T% q/ K
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); ; n& z4 \$ y/ K9 J5 p
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 9 ?; p& i+ s1 J/ Y2 C9 q9 S+ |/ c
0 g& [: a4 c/ K3 C usb_set_protocol(dev, interface->bInterfaceNumber, 0);
0 @' G4 y% _& |' w& T: x usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); 1 z3 C q1 S( f0 T3 I w5 a) k S
2 S1 R4 E* [( M& fprintk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n", . S& W. E* k1 g0 u& f' [ c0 A
dev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp);
. ?4 j: S% ?# H- j7 c
+ Q1 y) f( @2 l7 _& ]2 _- T if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
$ W3 I% N3 ^; x! { memset(kbd, 0, sizeof(struct usb_kbd));
( l. r$ @8 I. [( B/ d7 F7 Y9 g! E6 f
kbd->usbdev = dev;
" c2 M! O* }6 G% v+ C( ~ ?9 U7 w) z; E9 K$ ?. G( `+ ~& w0 k
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
5 G; V8 X3 ^9 X& `usb_kbd_irq, kbd, endpoint->bInterval); % @, B1 H+ ] h- T R
7 C: v0 c5 o# H7 I( a1 N; q! U* Hkbd->irq.dev = kbd->usbdev; : T- O+ B7 W( W
# [, F; J/ v$ c1 [8 p& ^$ M/ \1 qif (dev->descriptor.iManufacturer)
4 z- H h3 H( ~: y usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63);
; Z4 L5 B% O$ c' z4 q& e4 E- U) P: J6 I7 p5 }! N# m/ r( b
if (usb_submit_urb(&kbd->irq)) { - g4 z" q* Z' j2 {
kfree(kbd);
: z. o6 l) h8 n2 p- y% P4 ~ return NULL; ' S/ K* \( O W# h2 g w7 w
}
0 ]! |' P3 h! m: M
# N/ k( g7 l2 n% D# D) Cprintk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n",
5 t4 D/ F' R8 E/ e2 Y) }- [: \+ |0 O kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
U- z. e' C! a" Q" `# S$ ~2 _" Y/ B$ q t& X" g
return kbd; ' u) V- m7 f8 g7 N, f$ |
} / W1 m% E; z& G9 Z& j
7 t7 ~$ W' X+ R. w# E: C3 o
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr) ' j7 A* v9 M( i: q( c
{ 5 L$ f* C" x O5 k) H
struct usb_kbd *kbd = ptr; 4 r% D* M, \6 r8 N$ q
usb_unlink_urb(&kbd->irq); 0 G8 y3 E7 x& p& d4 v2 ]
kfree(kbd); # g4 l) t7 ^# F0 w; x
5 L- [6 O) G9 _$ M/ O: J; q}
! L0 M' O1 _' ^, Z' V! ? J1 J$ t3 \% }! o# Q# l2 {( \# e' i' t* Y0 W
static struct usb_device_id usb_kbd_id_table [] = {
7 {7 _ n3 P( h6 y6 J# P, v- a{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) },
- j( Z, B, r" k& ` y' N{ } /* Terminating entry */ 3 [6 q6 e1 J* _6 U
}; ; Z, }8 t. J7 R E) S8 }
% U( A# P* l) ^0 @5 \8 YMODULE_DEVICE_TABLE (usb, usb_kbd_id_table); 7 H- K4 q( D$ D7 q! n/ y
# _+ S% b0 G+ _2 P9 I
static struct usb_driver usb_kbd_driver = { . G. u; a& z; b; I, W* u2 t: ?7 @8 M2 h
name: "Hotkey", 3 t3 K; g3 \: o, R8 C7 M
probe: usb_kbd_probe,
* z" `+ ^7 C2 o; fdisconnect: usb_kbd_disconnect,
9 E5 q- D8 j! X# w" Rid_table: usb_kbd_id_table, 2 g$ m+ v: D5 T5 Z
NULL,
) m0 L; V/ E- K- V& v5 T: N}; # U. u' r& a) y( n0 z0 S: b4 A
* W0 `0 J+ U8 K0 k: e* _ |static int __init usb_kbd_init(void) + }# e8 {* E6 ^: s& y
{ $ p9 u: H9 F' v3 i+ p
usb_register(&usb_kbd_driver);
; k( k: T+ l/ w, _! linfo(DRIVER_VERSION ":" DRIVER_DESC);
) h8 ^1 A9 ~( }, q3 a* Z/ ireturn 0; : {. v: M; Q% l& I" S) N; {8 ]
}
' e; v3 f" q# f4 m, ]7 e5 V! L3 P
% }8 Y4 z) D" u% F2 ystatic void __exit usb_kbd_exit(void)
4 ]4 c* \5 K+ e7 y8 K ~{ ' k7 Y* N, s* {
usb_deregister(&usb_kbd_driver);
Q1 [' q! ~6 h0 h$ M0 g} + r6 P* [. x0 n M1 `% U) O' x
" E& N/ h% E0 b8 ^' v2 Q4 |# S
module_init(usb_kbd_init); 2 q% c0 j$ T9 H1 \( q6 E" n+ K; j# C
module_exit(usb_kbd_exit); |
|