- 在线时间
- 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, $ {# R; Z4 f/ a/ \# d: p
" USB ", " Mass Storage ", / `- X$ ]8 e% n- Z* e! |
US_SC_SCSI, US_PR_BULK, NULL,
# D* t9 l2 q z1 S+ m' n8 F) bUS_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE )
2 l z* m$ ^7 ]6 ~) @' v. _4 h: i) m7 b0 k
注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。 " b) T' f- J. p! o% _! K" T7 G
最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 ) F4 ?; _4 i, S6 F* P
键盘飞梭支持
, X: l/ A, M7 h" j0 _目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。
( ^/ D; t) _; \) j* K4 F下面是具体看到的信息
! x2 U4 [: R2 h3 {+ [
( u2 m6 N( F+ W8 q$ I3 |$ A% G$ kT: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 ) V: q, l+ O( {# L5 L- z# q
B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
/ e0 h' t2 x. i, P+ m5 QD: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 . I# n- f/ Y5 A! u4 Y
P: Vendor=0000 ProdID=0000 Rev= 0.00
+ `3 y# n- R7 N5 I4 [8 yS: Product=USB UHCI Root Hub
0 S( G& x; F! j" ]8 U1 bS: SerialNumber=d800 0 n) y0 N: A8 }7 O
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA , b5 a" ]; h+ q/ X6 a9 |4 E
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
0 h" E( z7 G9 f2 b& bE: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
6 G2 C$ e2 p3 N9 l/ t! K& dT: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 . \4 y1 E: Y0 b1 _
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 % X7 e! Y) j5 e. U
P: Vendor=07e4 ProdID=9473 Rev= 0.02
. b. M8 ?# W% f. x2 \ eS: Manufacturer=ALCOR
7 W" K ]4 f5 I3 T6 f% vS: Product=Movado USB Keyboard
; O3 }" a5 y9 `: h3 |( iC:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA : k, Q, [# |6 G$ {
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub ! n- ~5 B) r; h
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms 4 x# o6 d4 D: j( A. P6 W
找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中 & X% ^' u! u5 @. e" i. A% P
$ s) A# L/ \ p/ A8 t% w
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
- f0 I6 Q9 ^5 I: w! z: l, T- U! N$ xusb_kbd_irq, kbd, endpoint->bInterval);
' X% |6 r, B9 m$ ^) M% O# S, a9 p+ q) u) F
一句中实现。
0 h+ i3 i9 I/ [+ \3 T$ M' ~从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。
( ]* O+ {- L% Z; [3 u在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 5 L4 B6 i! y/ x, X
程序见附录1:键盘飞梭驱动。
/ ^* j/ m; Z' B6 K8 Y使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。
9 G! t9 z/ e+ Z% o" h参考资料
! H+ b' r3 V$ ~3 f# j$ o @1. 《LINUX设备驱动程序》
' K# g5 b& T7 B l' `7 tALESSANDRO RUBINI著
& C ^4 N6 {! Q6 k! B7 g; qLISOLEG 译
2 N; O q- N6 C2 Y7 K2. 《Linux系统分析与高级编程技术》
1 \' R3 o1 r x. F! E3 k周巍松 编著
) j+ q" b8 _. k l" |2 m3. Linux Kernel-2.4.20源码和文档说明 / V$ x4 R; ]( `% \! S
附录1:键盘飞梭驱动
! f4 o, Z: u% r+ o7 O$ {1 c& c6 j3 x6 J8 h) A: i; W
#include <linux/kernel.h>
; V0 }% _) x* J3 }! Y5 f#include <linux/slab.h> # l, j6 B; a2 y6 J ]. \
#include <linux/module.h>
; [1 i1 K' `1 S7 I5 B- Q5 F+ k#include <linux/input.h>
7 g4 C+ x* O- G#include <linux/init.h> 6 D: w- h) B# h+ i$ m
#include <linux/usb.h>
) x0 n6 m5 V/ J#include <linux/kbd_ll.h>
, E; v' i/ K( k" C* ^' B! \
- [0 d6 P3 b8 _7 f& X; B; V/*
7 Z$ d4 z2 Z7 S * Version Information
* i7 a* v! P- `) q+ G */
% M6 g/ H* J v# X2 C. I4 y#define DRIVER_VERSION ""
3 F- l0 F$ r8 V5 M% u/ j#define DRIVER_AUTHOR "TGE HOTKEY "
1 X$ N5 J6 \: z) U#define DRIVER_DESC "USB HID Tge hotkey driver"
* A X/ O5 k- x& O: I8 o- J! q4 k5 b$ g
#define USB_HOTKEY_VENDOR_ID 0x07e4
" e% ~" o; M$ l p0 l( k8 b#define USB_HOTKEY_PRODUCT_ID 0x9473
2 Q' i6 D, {" V) c//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
! }1 q8 X" M8 O0 u2 Q' r5 r3 d2 q9 Y! D* G. [
MODULE_AUTHOR( DRIVER_AUTHOR ); 1 Z1 t, z% N) m; D
MODULE_DESCRIPTION( DRIVER_DESC );
. ]3 I$ v, C0 \& ?9 x* y7 h* J6 O; _& U- Q9 }& L$ q3 |
struct usb_kbd { 1 E0 M/ ?: J# j9 m# R u( K
struct input_dev dev;
' A; k6 _; o2 h0 E2 estruct usb_device *usbdev;
, X; U; C' C- B( a$ [unsigned char new[8]; * J8 X. k4 f" \6 z" p
unsigned char old[8]; - i; q0 q3 n$ D I5 X5 s
struct urb irq, led;
3 z \1 s0 h1 T3 ?: ~& d" ?// devrequest dr; 6 |# \$ \1 e: ?! ~6 e
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
0 |4 a* _. d+ b) ] struct usb_ctrlrequest dr; % W- E" d. f g' {7 l
unsigned char leds, newleds;
$ f" p' m) u7 {! C) o1 J$ T: ~9 Jchar name[128];
& [- Y% Q3 L2 Z W3 mint open; 6 }0 [ H D; B/ s$ D+ ]
};
D# e" E1 d. L! p+ S//此结构来自内核中drivers/usb/usbkbd..c
' y9 k8 Q/ F7 |9 g! b) G
" ~' C- y, k: \; K% t0 `static void usb_kbd_irq(struct urb *urb) ! h x# N/ O: E
{ ) i; S3 q$ j R# Y% g
struct usb_kbd *kbd = urb->context;
9 A9 `% x. H% L) T1 W5 z int *new;
' j) G' R! Q& ^ new = (int *) kbd->new;
8 c( Q Y! p$ ]8 B. Y* d2 n5 u1 E/ d i4 O/ c5 p* V0 f7 @
if(kbd->new[0] == (char)0x01) 7 h5 {2 G# N/ e, J
{
% J" \, a$ V4 g' Dif(((kbd->new[1]>>4)&0x0f)!=0x7)
; n2 |1 a6 T( _- P4 Q1 j1 @{ & [9 A) T" M$ G5 b! X, O1 g
handle_scancode(0xe0,1); + E& N0 f- R4 R4 F u0 D1 p: `" E
handle_scancode(0x4b,1); ' j% q. o, }' @! g3 x
handle_scancode(0xe0,0); g0 f1 H" |- J
handle_scancode(0x4b,0);
- }$ [7 r1 }) R* C} " ^& C3 j* f: u) Q7 @0 M( j
else # S2 @+ g4 g* ]- s( Q" X# `9 P7 t
{
( D+ i L$ {" O5 C3 b- Qhandle_scancode(0xe0,1); 4 n' a& F! p3 U' }; N& ^ Y$ ~, ?. c
handle_scancode(0x4d,1);
3 D; U1 d$ k9 a2 W" p) q* }' D2 r handle_scancode(0xe0,0); 5 y7 R7 d ?7 h' y/ j0 q3 I& ?
handle_scancode(0x4d,0); 9 g2 j% a* T+ Q/ ]
}
9 D: v, f& [; ^( t- d& W/ f' M* @$ _} 5 F% C/ M. O" x# ?8 J
* G- t% h& J" ], ~
$ |1 @" T" @; w0 |+ s' J' V' ~printk("new=%x %x %x %x %x %x %x %x", 6 m" T% I0 k1 w, |# R9 H9 X
kbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], % P7 Q, R$ f8 o- e$ R {5 e$ B
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
r8 |+ n: d0 z3 M
' z3 K1 {/ w$ p2 b} ! l" ^* K U: x A
( ^2 W9 l; ^( h. V
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
1 I0 n# G4 E* K0 s: W+ q const struct usb_device_id *id)
9 y) ]8 Z! R9 l5 I{ 7 k) T! b1 u6 s% G" k
struct usb_interface *iface;
4 @3 D; A/ y; q0 u3 @ struct usb_interface_descriptor *interface; . |0 l4 G" w4 A1 p4 Y
struct usb_endpoint_descriptor *endpoint; ( a5 `* I6 c5 {1 Y" X4 O& Y
struct usb_kbd *kbd;
$ o2 p7 g$ v, g int pipe, maxp;
. ~) t- ]8 C# Y1 E; T% @) J- Z! v% P
iface = &dev->actconfig->interface[ifnum];
; F1 ^3 \. {8 W2 e interface = &iface->altsetting[iface->act_altsetting]; . ?$ v$ z) J* i1 ]9 e
& {/ k' H' J" Z/ U: Kif ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) ||
6 F$ F6 d4 F) A/ `9 f; }(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || : a5 M4 P7 }' Z- n3 f) t
(ifnum != 1))
; ^8 h3 d7 s7 Q8 x' J7 V; H( G3 R+ E* M{ 1 E9 a, ?6 g( b; n4 P1 @
return NULL;
8 A& G+ G4 h. x+ p8 O+ c4 G}
2 D' \1 t2 I$ G( w' ^+ aif (dev->actconfig->bNumInterfaces != 2)
! _% y8 _: x2 y{
5 c% Z% I5 {! W9 N% K6 h3 @return NULL;
0 U8 r* g: U; m0 E& W! L6 D6 u. r9 S} 2 c* E$ d) r' t8 |) ^
& Z' f% C+ h1 r2 Q) a8 h3 gif (interface->bNumEndpoints != 1) return NULL;
9 M# ]! j: q2 H' n+ G% q1 ^! v: ?) O: ?" t" b D$ Y
endpoint = interface->endpoint + 0; 6 {6 `2 l" Q7 S8 j' x
, F6 l e0 A$ ~ `$ o
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
8 j: `$ L. m5 g maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 4 C. G9 ~/ S2 K
4 ~6 N) }% `. o
usb_set_protocol(dev, interface->bInterfaceNumber, 0);
- q2 f/ _, N, b% m& P: g4 u usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
* z) D1 _7 x/ y7 Z9 E' n% ]9 p2 H( Z% m% S3 @: J& P3 T" u
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n", 7 b6 k+ H( d; j+ \; e* p
dev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); ' n8 E7 w$ Q9 x0 T
1 U, X4 @* ~/ A
if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; / k) m' S, T$ p8 J
memset(kbd, 0, sizeof(struct usb_kbd)); " }( e3 V9 [) }) g: ?
/ ^9 x7 ~4 K' P3 D' k kbd->usbdev = dev; ( `; f- X5 k- C( |8 c0 F
8 n, I" w/ l8 g+ g2 B& ~4 M. r' k- d FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
& |- u! n( i4 E" l4 K* Susb_kbd_irq, kbd, endpoint->bInterval); % E: e+ T5 g1 V
8 p v' r+ i, d3 D# G! T' Tkbd->irq.dev = kbd->usbdev;
+ N: l8 B' T( O5 S% L/ j$ z& R8 r- I. a/ M! A8 V" W
if (dev->descriptor.iManufacturer) % p+ m: z; k; |& T) ^
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63); / V; ~2 E) n7 ~. z
0 j: ? @) g7 P+ `* ]9 [3 h2 y5 N
if (usb_submit_urb(&kbd->irq)) { 4 u$ ^: B+ y( }: g9 U
kfree(kbd); , H% |! L6 Q5 l# `2 w& }. k* Y
return NULL; 1 y' M K# X* _. R8 V7 _2 ]
}
% {6 [+ l/ b! q
# D- J* s& i6 M! f, d. Zprintk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n",
8 x& a4 Z4 _# R kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); / [; D2 K' d( O( \7 H- a; |& k
3 i) m8 c' Q/ g! n$ w
return kbd; & s& g$ m3 S! P: s% ^
}
3 Y* Q" G/ \/ }$ `' X/ z" H
& T; _2 v8 y( V% r9 @4 Vstatic void usb_kbd_disconnect(struct usb_device *dev, void *ptr) 6 G! ~7 C. ?& D. b
{
' }1 i2 d! d; v) I! @& I* _struct usb_kbd *kbd = ptr; 2 ~% M4 A; z8 N# c" e2 c
usb_unlink_urb(&kbd->irq);
# p& C2 B* L8 P2 W& t8 s kfree(kbd); % _6 r+ A. Q0 Y9 Z5 n
) N) g+ Y7 g7 S8 L
} . | _5 D5 c9 B7 m$ Q
4 x: F i( c. [ E
static struct usb_device_id usb_kbd_id_table [] = { 8 M* W) k9 H% d
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) }, ( U' t6 Y R3 D$ \
{ } /* Terminating entry */
( Z7 @# v2 D6 [# h) `};
4 S) `, H$ U) p3 W
7 Z" k* y9 Q( V- \MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
3 r; g! {- c6 s7 e% |0 |: d3 X ^; w4 G: r2 x
static struct usb_driver usb_kbd_driver = {
5 `. P& k/ T& ^1 r: k8 R: ename: "Hotkey",
( a Z, F$ f1 B* P5 u; s* q+ U( ~probe: usb_kbd_probe,
( Q, _8 o0 p2 {- I+ odisconnect: usb_kbd_disconnect, 7 d/ Q- f. Y" _+ \
id_table: usb_kbd_id_table, 9 _8 w2 L3 Z: L0 S. G. W# m
NULL,
' P n4 ~& A, h, B}; : O( w* o+ f0 t& E+ h
# F3 @7 k( i Z2 u8 Y8 n# Jstatic int __init usb_kbd_init(void) k* q5 q: G C
{ # u& o+ D7 H, A/ d* o
usb_register(&usb_kbd_driver);
9 s4 x: A9 k; Q# V+ rinfo(DRIVER_VERSION ":" DRIVER_DESC); ; N+ v$ J* q2 r$ x
return 0;
' V* k, b1 s: V, x- Q}
& Z) n5 b& U. c/ X8 K% K! ?" x- C9 n) f+ R$ m; C b6 _" J
static void __exit usb_kbd_exit(void) 7 @) P4 g- w' w+ e, X& H, a% ~4 z
{ ; P9 A" _3 E( I* n0 L
usb_deregister(&usb_kbd_driver);
. e, P# I" N% {1 |9 a" h1 T} & }, V; K" o1 ^) F/ }2 t% A
( D1 {! \9 Q* ]6 {+ M8 Rmodule_init(usb_kbd_init); : [5 e& ?; t. @0 C" f# I" p0 l
module_exit(usb_kbd_exit); |
|