- 在线时间
- 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,
, R2 `* w* w; _5 z0 b! N" USB ", " Mass Storage ", , ]! m& V2 B9 v2 d& c. P7 e3 s
US_SC_SCSI, US_PR_BULK, NULL,
* t1 H, l" P6 y, z/ MUS_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE ) + w( x, \/ q7 g6 e) k7 u' J. p
: p7 @( ^, ]1 D. L6 [/ C6 `9 d3 R注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
1 }- l# I9 H% t- `+ ?最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 4 q9 a/ f+ y# E; Q& }- |
键盘飞梭支持
2 }/ h$ j+ }0 V& E) W+ h C目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 ; ? _5 C$ Z. W/ j2 I
下面是具体看到的信息
. k5 T; E8 e5 f# i R4 H( Z
. G# q# O. v9 o. k; X, wT: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
- g8 {1 f! ^5 Q8 fB: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
! c- u- ]5 O T0 O, VD: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
8 X. g! \2 h, |4 ], d' {* ?P: Vendor=0000 ProdID=0000 Rev= 0.00
2 f7 r- J6 `& w5 YS: Product=USB UHCI Root Hub
# a ?3 p& N4 [6 L8 M7 G: YS: SerialNumber=d800 , | Q9 E! I4 m9 k- t# Q
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA & r6 J: t3 W* h* `( B! }1 P
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub # y4 h- A; [+ y- w4 o
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
: P/ |3 D ]- L. A5 DT: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 0 H4 P+ O; _: O) ]4 L2 |
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
8 C1 ?9 W+ ?. a7 c) q# j' uP: Vendor=07e4 ProdID=9473 Rev= 0.02
. S1 @5 n L9 G( J3 eS: Manufacturer=ALCOR ! F/ g% r* J L7 v
S: Product=Movado USB Keyboard " D9 D0 e2 ?! Y1 ^
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
0 e& G) K5 b: z6 `& L' ^I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub / \8 l2 T/ _- I* K
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
4 p" V/ G9 v- o8 c; \找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中
6 G6 ~# i: v5 \, J# g7 V! Z1 O2 k7 M9 h" u, q
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
. T) t- F# O4 W0 Eusb_kbd_irq, kbd, endpoint->bInterval);
* h& E/ g4 a! a" y: s
0 l- z5 _. i0 Z2 F' Q一句中实现。
/ u% n! G- B4 i5 I @9 I7 i% O% O/ s; ?从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。 - n. X j4 f, G: V) q
在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 , X- O8 i% y ^* C6 x
程序见附录1:键盘飞梭驱动。
; j$ a. f2 s: k7 f8 f0 B% g3 \! i使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。
1 V) I1 G4 P1 P6 {4 c$ g9 ~3 M参考资料 & B( C6 v6 d; o9 l/ Z* _
1. 《LINUX设备驱动程序》
$ o( [( ~$ g) n% G5 i# A! s* oALESSANDRO RUBINI著 & k6 `0 m# w& D* \" B
LISOLEG 译
/ A' @# `4 h8 Y& [, {8 @! j2. 《Linux系统分析与高级编程技术》
8 J0 T* g/ l, x+ o, `+ a周巍松 编著
: _; [' J! o0 N' m: p3. Linux Kernel-2.4.20源码和文档说明
, S" D5 c5 ~0 I7 I附录1:键盘飞梭驱动 & `& n1 P ]& V% D2 V
7 ?; V3 E# V7 h
#include <linux/kernel.h> 2 R3 n( P" I9 f) q3 ]4 x5 J$ V
#include <linux/slab.h> ! H& c# ]6 n/ {7 \7 G! K
#include <linux/module.h>
; ^$ _# ^! I- d# y& i#include <linux/input.h> - D# }/ t/ b% m- D2 F% N
#include <linux/init.h>
% J3 S, y% d0 L/ O, R; _#include <linux/usb.h>
& \6 h% [# n7 H#include <linux/kbd_ll.h> 1 E9 f+ j T, X. X/ O
$ s7 v6 l, i& o, ?- w
/*
% ^/ f8 g5 v# f2 r3 A, \ * Version Information ' R2 w0 a2 H* d8 R( S
*/
) H0 E* B) h0 G: T' f2 W6 P& _#define DRIVER_VERSION "" ( s; z l z' ^0 Z) u0 ?0 T
#define DRIVER_AUTHOR "TGE HOTKEY " ' p6 V$ Q: ^/ y9 T6 _7 I9 t' h' N- ]9 K
#define DRIVER_DESC "USB HID Tge hotkey driver"
* ~/ c! z: a& Y, i7 Z" Y
/ p2 C- s& b" f+ k( S#define USB_HOTKEY_VENDOR_ID 0x07e4
~4 t* M9 [- H#define USB_HOTKEY_PRODUCT_ID 0x9473 : V+ n# c% h ^. X
//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
0 _3 e' o$ `( w$ N) Q
% \# V9 q' `: n9 v2 p$ \MODULE_AUTHOR( DRIVER_AUTHOR ); + \7 i1 X" c5 f
MODULE_DESCRIPTION( DRIVER_DESC );
: H3 Q0 _# y6 V, j( D p4 d
' @; q9 Q0 }) P& Y7 ^struct usb_kbd { . {0 |, H- {1 A) N. V* d
struct input_dev dev; ' T* V R$ G5 T7 w
struct usb_device *usbdev; + v0 s% s' Z# f
unsigned char new[8]; 5 R' p$ _! e6 c8 B! g# I8 a
unsigned char old[8]; 1 B2 B, U! d1 N- @8 a9 F1 E
struct urb irq, led;
& |* e5 x; m2 D! C) M! D// devrequest dr; 9 U6 O+ R' y& C- r: N* k
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化 . l t0 q- K7 Z8 _% s5 Y& |
struct usb_ctrlrequest dr; 5 M& R% u0 m2 T3 M( U; ?
unsigned char leds, newleds; / l% ]7 E- U( e5 U8 ]
char name[128];
u8 E/ p* T, q* }int open;
& D8 a5 ~$ J* y6 L- C}; & H, B, y0 n. P6 e
//此结构来自内核中drivers/usb/usbkbd..c
6 ]+ |5 _9 n r, x. k
7 o, b* V7 J' o1 S1 D: C- E" {static void usb_kbd_irq(struct urb *urb) / I+ v! }# P9 S$ ?) J1 t
{ / Y6 l& i( z* d3 G/ U
struct usb_kbd *kbd = urb->context;
9 O. B( V/ P/ R' R8 J+ ^ int *new;
4 S$ n- C( N9 f2 ~+ G! g% A2 a2 q new = (int *) kbd->new;
" H3 W7 V6 w+ r9 v* E3 _' r, f; c" S0 S( ~8 p) ^3 Q. g4 M) x
if(kbd->new[0] == (char)0x01) ) Q: h1 I5 D; g/ |: m$ k
{
; T8 A; }2 ~+ [6 W5 H6 E5 D; M5 Xif(((kbd->new[1]>>4)&0x0f)!=0x7)
2 k) \( T9 ^2 ]; j{ 2 l# {6 q. f" N, a+ g+ u/ W. i* e
handle_scancode(0xe0,1);
/ Q' u& Y. J. q8 t- T. R7 Lhandle_scancode(0x4b,1); $ m4 K7 C8 k: N! g) ]3 r
handle_scancode(0xe0,0);
1 o! X3 u0 `! \ handle_scancode(0x4b,0);
( o7 |8 L- }$ r" [$ ~}
0 ~7 V3 |2 z' E/ Velse 7 j/ z, o. t, _) P5 E! K+ O! u2 [7 ~
{ + M' v0 U0 M. ]* p4 \! |
handle_scancode(0xe0,1);
6 O4 ^* A: W0 {' R' p handle_scancode(0x4d,1);
! b2 ?! n. `9 Y$ L handle_scancode(0xe0,0);
. i8 C+ e+ ]& H, ~8 w( f' v handle_scancode(0x4d,0); 9 V4 e" u% R6 Q5 {2 _# R) L
}
" Z6 Z$ h9 p( b$ D" e' Z" o8 ]} . I$ r# g1 f0 |' M$ l, u! v
/ \" k5 M( `- t! Y. V
9 e" x4 Y) s1 R. ^. ]printk("new=%x %x %x %x %x %x %x %x",
6 T& |, a( t; B/ L% Dkbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3],
4 k6 X, k3 c/ G$ nkbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]); ) i8 v+ B& S4 h7 z% L
$ H* p P5 N$ I} 7 @" f) `, l) A7 Z6 u! X
. Q3 a9 R! i5 v$ c! T6 J
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
[, p0 p* S- Z& i q9 p const struct usb_device_id *id)
& w1 H' o/ ^. p) a{
/ [. ~, Y, I, i9 Xstruct usb_interface *iface;
; T: C0 f* Y8 B) e" P struct usb_interface_descriptor *interface;
0 a% w1 ], @/ v8 Gstruct usb_endpoint_descriptor *endpoint;
( V; ?5 s/ {% ^5 x/ d( E struct usb_kbd *kbd; ' T/ k8 c' M- z4 Y4 J0 A3 M
int pipe, maxp;
0 g: v0 ~; W$ |8 j2 e5 r- \
6 b; e2 A! J, ?iface = &dev->actconfig->interface[ifnum];
1 ~- F) D ^) D; c8 A interface = &iface->altsetting[iface->act_altsetting]; 4 Q4 W6 u$ H' A1 N4 B! s: L: h
& M9 U/ E- _2 ^
if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || 4 G+ e$ x& v8 h- R3 O( E2 |$ o
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) ||
4 }" t7 F, z `5 ^$ d5 [6 ~. g(ifnum != 1))
6 |5 m* f* D/ j) ^, [& W) o) l{ ( g' A+ [1 J$ P8 j
return NULL; ; N* {/ i) `: F. {( N
} 2 f- G9 H* I, R0 c9 J3 P( ?7 @
if (dev->actconfig->bNumInterfaces != 2)
/ x7 j0 O- N6 G8 C& n7 z, P{ 9 g0 ^& L- l, m5 f7 ?
return NULL; # W( M$ v4 P/ o# a7 O+ a
} + L1 J+ J( B1 `' \
3 ^8 I* F7 p& }" M; Wif (interface->bNumEndpoints != 1) return NULL;
8 L. _2 l! O1 d% A
" C: e; T8 t3 p, ^4 T- D# s _ endpoint = interface->endpoint + 0;
h1 t. |9 ~3 Q7 S- i, X! ~
& G) d7 }1 @( _ pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); + q: O8 A0 g1 W
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
" P2 D4 h3 R: s( E( T! r" ?% r) X) ]7 h, a
usb_set_protocol(dev, interface->bInterfaceNumber, 0);
7 u7 `4 k* y. {! B usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
8 ^8 T! L$ W" ~' V- J' s; b5 J4 a$ _$ m. q
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
. x+ p3 W- E5 }2 |dev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); 6 h0 D5 p6 C; }2 w
( W5 }6 P" |+ [3 j8 b l' \8 C
if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; $ d5 k: K9 A9 P8 w: ]# I
memset(kbd, 0, sizeof(struct usb_kbd));
' Y: z# L: h; E( b9 ?# g' i: @2 x3 b7 Z q
kbd->usbdev = dev; ) A2 e2 g, ~, W$ }
1 w* B" J6 E. ]0 N1 f6 s
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, : p3 w# u/ {- O1 W5 U7 W8 \; L
usb_kbd_irq, kbd, endpoint->bInterval); ' \& [$ D! _! I. Q f6 ]! K# D
9 w9 P" [# o7 tkbd->irq.dev = kbd->usbdev;
" I3 R# w7 J6 b9 i
0 x6 M, }7 _6 \; G; A- r0 A# Yif (dev->descriptor.iManufacturer)
' x0 ?- _+ n$ C0 U; M2 ]4 p usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63); 4 D1 I! ?7 a5 c4 t
& D) Z R; }0 Z& Q$ }# W. zif (usb_submit_urb(&kbd->irq)) {
+ C7 k# i7 W7 Q, T1 B kfree(kbd); $ M- X( _- n1 o. a& I2 e0 r
return NULL; R t8 T+ x; {6 }( B
} 9 K, E% V$ N, }1 Q) n
: b6 n# I$ A; a
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", 9 j0 p4 A0 a* Z+ P5 F5 }7 W
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); / }7 z& n' |( j' R/ [ ^5 U
2 i3 s( _5 U: R2 |" m5 z5 | return kbd;
& k6 t9 z9 I; ^! F! h/ N} , N* Z- m5 S: O& M
7 A' o" O. g, {, w
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
2 }; Y- G. C: X( f# v{
) R9 `; j/ z3 c( ystruct usb_kbd *kbd = ptr;
+ x; H& P8 A7 I: M usb_unlink_urb(&kbd->irq);
- l! f5 H/ B( ` kfree(kbd); 0 }& ]$ I0 K0 }& m. u( H- ~5 `
+ a, l' Y: d2 k; W
}
$ V+ w; X- t, L( L
& v2 M. m0 l3 S/ j3 L9 Gstatic struct usb_device_id usb_kbd_id_table [] = {
$ G1 @& K/ W3 R G{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) },
# F6 e1 D1 ~( O; n2 Q{ } /* Terminating entry */ 0 H" c. z9 C& X3 u8 ~+ a
};
* r1 Y$ o) a0 d0 |8 n/ m* X* j9 g4 ?
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
c- z8 m, F% F- w3 D2 Z2 e% S0 g3 Z# y) q: c
static struct usb_driver usb_kbd_driver = {
4 a; S# H" Y: D! G. rname: "Hotkey", ( P6 v% N1 g' b7 f* D( _# a
probe: usb_kbd_probe, ! Q( ]6 ~% i. A, v+ x, a
disconnect: usb_kbd_disconnect,
9 j# I+ n0 z- n1 D4 l* S% K. \id_table: usb_kbd_id_table,
# n$ V/ w0 ?2 r% Y8 J( s& O: kNULL, 3 [! R) g* X. N: r# X W; r
}; ; f, J( P) z$ K7 m) m: M8 x
0 b7 S# R6 e" x$ L7 o+ P* Hstatic int __init usb_kbd_init(void) , A/ ]5 ?& Y% f: @
{
! d3 d& s! H9 a# wusb_register(&usb_kbd_driver); , |! c8 ]7 T; P T
info(DRIVER_VERSION ":" DRIVER_DESC); f% w: R# z1 P5 V- n
return 0;
, X0 T6 P) e. K# r3 \* Q} : U H& {5 {& N# T$ D% I5 X" E
( b4 g0 t. O. M i1 astatic void __exit usb_kbd_exit(void) ; ^0 ]3 E8 a8 X
{
+ k& n5 |! O3 U* tusb_deregister(&usb_kbd_driver); + \% I$ w5 `3 I. ~3 C! R
} , X3 u+ Y2 o0 i4 W
2 q3 M8 U2 F% r4 b( d( [6 xmodule_init(usb_kbd_init); $ k8 U/ u, L4 j- J6 S8 W
module_exit(usb_kbd_exit); |
|