- 在线时间
- 63 小时
- 最后登录
- 2019-5-3
- 注册时间
- 2004-5-10
- 听众数
- 440
- 收听数
- 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)是目前中国最大的数学建模交流社区
群组: 越狱吧 群组: 湖南工业大学数学建模同盟会 群组: 四川农业大学数学建模协会 群组: 重庆交通大学数学建模协会 群组: 中国矿业大学数学建模协会 |
发表于 2004-9-27 14:33
|显示全部楼层
|
|邮箱已经成功绑定
UNUSUAL_DEV(07c4, a400, 0x0000, 0xffff,
1 X9 ?5 R- K; N7 {$ C' d7 u6 m& T" USB ", " Mass Storage ",
- k4 m+ @0 i/ _US_SC_SCSI, US_PR_BULK, NULL,
j3 u3 Y; W8 m3 dUS_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE ) " ~" ^4 J/ A) R; r" A
' j3 U% @3 Q1 l
注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
! z7 x! l% S( E最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 e. u: @: ?: k. Q1 o ?* b
键盘飞梭支持 9 l9 E3 Y$ o4 U, U' [7 F+ P
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 2 n" c( ?4 ?- y& V
下面是具体看到的信息
1 O# v" ^. w$ F" L2 e: S# R, j9 l2 N8 \( m. S! x2 d" d: V0 Z. b# u
T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 : k; h: `, h( e0 f
B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0 1 Z1 p* \! G/ o4 R
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
) D* B2 k7 c4 K4 n& a5 h. BP: Vendor=0000 ProdID=0000 Rev= 0.00 , X* m& p' ~8 v3 [* m8 e& V O
S: Product=USB UHCI Root Hub
2 j7 L6 D- u [. ~( US: SerialNumber=d800
/ i: ?2 M* J9 r1 C5 e X2 nC:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
* V- M6 Z. | t8 \I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
2 k! b; r; u3 O. HE: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
- b9 H3 ~8 e7 M* b9 }1 n! V1 YT: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 8 M/ u6 o; O# H, v5 x4 t9 d
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 * ^( p' C+ ~! v: }! U
P: Vendor=07e4 ProdID=9473 Rev= 0.02 7 z& R$ {+ N6 e! J
S: Manufacturer=ALCOR ; }' H/ f( [- W% }* N3 h
S: Product=Movado USB Keyboard
`' l8 ^0 s4 u i, hC:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA ' w" P1 D" A: \) Y* X
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub ' g; q }- J6 M" z1 @0 A- {. W
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms % v6 q% x/ W5 q+ g5 ]
找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中 e2 i7 U4 D% ]4 d
# @. r0 p" M4 _/ r' lFILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, : @& }5 v6 W0 C. s7 D
usb_kbd_irq, kbd, endpoint->bInterval); 3 x8 e6 H/ R( x) i* v+ Y
& T1 ^: i6 O5 {$ ] k# O* J一句中实现。 % X, Z- l1 }9 ~
从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。
: c% O0 S5 L. u/ s在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。
4 Q! c# E. ^, M9 v, N8 g) W程序见附录1:键盘飞梭驱动。
7 u; S& }* `/ s% b6 K使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。 ) l( j0 |5 k3 }& g& t5 G+ q& o
参考资料 * C. w: S5 F t5 m
1. 《LINUX设备驱动程序》 / V( \( p* E& ]
ALESSANDRO RUBINI著
6 S' M) c! X- E, G/ @LISOLEG 译
# |* p2 Y+ Y+ g5 @9 [5 n& p7 S! @2. 《Linux系统分析与高级编程技术》 8 v" s. y; r( D4 H4 l
周巍松 编著
' [, P. k" i6 B U7 A3. Linux Kernel-2.4.20源码和文档说明 ! g% o& _7 w2 S, L* h
附录1:键盘飞梭驱动
. T1 b* `9 V# G& S7 R& l9 B/ P
9 n+ v3 M1 C) J# ^#include <linux/kernel.h> / o& E. j7 @/ R7 w$ d
#include <linux/slab.h>
6 Y; G, d/ I; y9 {9 d3 F7 O#include <linux/module.h>
5 g' G) j) _% z0 L- n% L" O#include <linux/input.h>
: h' F( A# R0 C7 S& g#include <linux/init.h> $ R, L5 c6 I/ d" W7 L
#include <linux/usb.h> ! g+ R, Y4 v, w8 y0 H3 {
#include <linux/kbd_ll.h>
3 d1 f6 V* A9 W! f3 ?, E! ?% j$ \4 i: ~7 H
/*
5 P+ p7 m, S) c: P# x3 A2 F * Version Information " I# C' k% @' \8 m
*/ $ w4 c1 f! q8 f
#define DRIVER_VERSION "" 8 Y9 d! \& o. B. L' k
#define DRIVER_AUTHOR "TGE HOTKEY " % D$ L0 w2 }* f, R' n! y
#define DRIVER_DESC "USB HID Tge hotkey driver" 7 ]# {% q8 g! H9 b$ C2 a
4 O9 [# _7 S5 z7 r* b/ D( i#define USB_HOTKEY_VENDOR_ID 0x07e4
3 i3 f1 R$ _2 A7 D8 O& B#define USB_HOTKEY_PRODUCT_ID 0x9473 . K& |# C) b8 ?3 t" h
//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值 9 b- s- b6 R& m+ N" x7 T( Y
6 s7 A9 V. I6 @7 N6 f0 MMODULE_AUTHOR( DRIVER_AUTHOR );
3 y" x& [3 M+ L; q2 L9 F. z7 ~$ `MODULE_DESCRIPTION( DRIVER_DESC );
1 a* g |" ~. V, J0 G4 U3 A
\# r. {5 k- ], ~1 \struct usb_kbd { 4 Z6 x% }, r K& \
struct input_dev dev;
7 k! p) j; [2 L3 V2 ^8 U# ostruct usb_device *usbdev; * y' y( h" `; m& [9 d
unsigned char new[8]; : ^3 o/ u( e* X
unsigned char old[8]; - l* @/ w! D& c" C2 [$ x' E+ A; z
struct urb irq, led;
, x* n/ r7 w2 E; X1 e" W" ?0 G// devrequest dr;
0 @0 l9 } d/ x% O//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化 2 V' [0 ^* X0 d( z% Q' `+ H
struct usb_ctrlrequest dr;
/ d7 J& N6 U$ x; i _8 r5 j0 S+ C0 l! Xunsigned char leds, newleds; * j* Z" y' u" I3 S; k" \
char name[128]; ! g* ]9 x- s* q5 e
int open; + d# ~8 o, b, R" V& Z2 ^
}; - j# j E2 X7 o, g. u: P+ c0 D6 D
//此结构来自内核中drivers/usb/usbkbd..c - o3 {3 _9 s7 k7 m- p
8 d4 C4 K& M, M. j. A* e" n
static void usb_kbd_irq(struct urb *urb) 6 h( p. h) C+ K" e z$ H
{ 8 u; ?/ i- \! M& V) S
struct usb_kbd *kbd = urb->context; ' e, f8 V' G# Z
int *new;
7 c. K" t" A, P) V/ d. F, C new = (int *) kbd->new; , v+ P/ f4 [' y6 n: M( ?
: P; k$ ?) M9 k4 o6 W, `$ o% P
if(kbd->new[0] == (char)0x01)
' Z4 X1 K$ J, T9 E2 n x{ 5 J. K+ d1 g! V+ h% V, W% ~
if(((kbd->new[1]>>4)&0x0f)!=0x7)
n* ]4 S [# d% [$ H{ 6 W! [, p9 r# h& ?/ s
handle_scancode(0xe0,1);
( h- n3 D. p% }' @$ Ihandle_scancode(0x4b,1);
; L* k) O8 c; U+ [& p* \1 D: f handle_scancode(0xe0,0); ) G. z4 J5 f ^- i
handle_scancode(0x4b,0); ( j4 ]; J! |' X9 a. Q/ X
}
! J# c. B! p4 g( R- Ielse
& w& N3 Z6 ?- c, |$ J{
/ j2 ~5 t4 o4 thandle_scancode(0xe0,1);
9 R2 O) ~ z9 J3 V( c9 o handle_scancode(0x4d,1);
" O, F$ H5 L C- ]6 } handle_scancode(0xe0,0); # X3 H; T# ]) Z7 c3 H0 f
handle_scancode(0x4d,0); . X5 o+ I S8 a
}
* Z% n' A& e% D. U} & b4 O! k! \$ G$ G0 `
2 s5 s8 e) V" [3 n5 d8 i S% I
' y# h$ x( G, s# O; ^/ V+ l6 jprintk("new=%x %x %x %x %x %x %x %x", , [/ v; M8 J, g \; \( a/ g
kbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3],
& X6 Z! c+ e$ B0 [! ykbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]); % d7 M* z/ D8 W4 y6 j0 X5 y. D
* T2 S+ W% ^/ r9 n `" G} 7 P% l0 r% P* T2 I7 y) d
- d6 y% y0 m. ]: S/ |static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, & [, X6 K/ ]# R
const struct usb_device_id *id)
1 k2 m% C0 S1 }% W{
2 z+ A* I+ e0 x$ Ystruct usb_interface *iface; . L' T) I% d, L: ^9 @' L
struct usb_interface_descriptor *interface; 3 A2 s8 Q3 d! j
struct usb_endpoint_descriptor *endpoint;
3 v0 g2 ]+ R1 T* M9 { struct usb_kbd *kbd;
- ?, h# L3 V" G/ J! P6 o int pipe, maxp;
! P8 i; J$ h* t" V
( c# u$ U+ F5 I9 J: piface = &dev->actconfig->interface[ifnum];
# |7 d- S8 p% @( Q" _8 x interface = &iface->altsetting[iface->act_altsetting]; 6 d. Z5 f# v& f/ Y6 k
! {( Q. j# \2 q0 `3 S; a% t
if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) ||
7 g* E c- L9 r9 W+ }+ c(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || 7 {( l8 e/ h: e! Y" l, @! q
(ifnum != 1))
8 D) F0 }' ^; j5 g9 ]- C' m{
% x1 i3 i; {" s# }/ f5 S5 Creturn NULL; ! D/ B' \- a! N0 g. n2 C7 ?
} 8 ~/ s8 w6 n5 [) i+ Z( q H
if (dev->actconfig->bNumInterfaces != 2)
9 a9 D6 p! V* h9 @' n{
" p2 }! F" }. A0 e, Lreturn NULL;
! x/ @0 N( R! G0 [) @6 G; Y} 6 \4 s/ S; Y7 ^8 }* O( t9 r
& V# \; f# {6 V6 J# c
if (interface->bNumEndpoints != 1) return NULL;
3 D9 G0 A& ?: H e' X9 N/ T# I
# ~( s7 [ |1 t) V endpoint = interface->endpoint + 0; / O: ^+ p+ i/ }
9 L9 ? R) n% w! r" q4 C) w
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
8 E! A. [) A0 Y( U maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); , X& P4 [) X. |4 r" U' m
5 M _3 x/ {: W. |# G usb_set_protocol(dev, interface->bInterfaceNumber, 0); 1 k# `% h7 A) z
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
6 b3 F- ?4 q& M8 ^% L# D' R: k3 F, d* M& f/ }, H: H
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n", 4 Y4 T2 _4 x. b# T V, D! h
dev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp);
4 u4 D3 B' s, H5 }: J7 I% X: f7 ^3 U5 F3 e( [) T+ h
if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
$ Y% s+ Y' U5 G' {2 A memset(kbd, 0, sizeof(struct usb_kbd)); " q: u) @# [: h y
. O7 C A' }( k3 \6 s
kbd->usbdev = dev;
* ^6 v! f4 M, u2 O& M
$ P9 K# S5 n5 @# M9 H, d FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, ; _( \8 G6 r! p; V. V6 r
usb_kbd_irq, kbd, endpoint->bInterval);
& }& P; G, ?. y5 E6 x' |$ \
9 O& o$ p: i7 d& V: r% z0 s, ^kbd->irq.dev = kbd->usbdev; * C/ N: c' m# S$ E; Z
" D2 D2 Y9 \0 ]! H( j
if (dev->descriptor.iManufacturer) 9 |9 K5 T0 C5 k( F) [
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63);
4 d; U6 D' V$ S5 i0 r% Y+ z7 t, F0 X( q
if (usb_submit_urb(&kbd->irq)) { ' ~9 a$ }1 I+ U3 o5 o
kfree(kbd);
* ?; \# q0 w% Z$ J return NULL;
" i9 _8 [& \/ A0 `. u& \* g } ! {! e7 h" u1 `1 c/ F# o% ]4 C$ p
0 c& [. ~1 @! aprintk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", 5 e5 q8 a3 o0 v2 k" d* M1 R
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); 9 _" `8 k3 L# L9 R" W
5 n1 t9 D6 V. C% w return kbd;
3 z3 ^ ?1 S- d9 ^* Y* Q, ]} 4 a$ ~# N! F- ^/ T n
0 q$ X$ \, O7 s( U9 Istatic void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
' e( ~* g5 R0 ]6 T{ # y& r. k7 F+ I7 y$ A3 ]
struct usb_kbd *kbd = ptr;
0 q: D( X% t' R' q usb_unlink_urb(&kbd->irq);
7 n2 ]; q0 n8 g( ~4 z' R3 s+ e: Z kfree(kbd);
7 y& t- N* z, O8 K1 f4 x. m
5 |/ l$ g6 e4 U}
# z) S/ u2 z; l
9 J; y! o. o+ i* V0 L! Q Qstatic struct usb_device_id usb_kbd_id_table [] = {
5 X0 J: g8 [, x* |* l$ G5 U{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) }, / z W: e2 F. D# ]8 }6 z& }% ~0 U
{ } /* Terminating entry */
& W! j$ c: c/ ]6 D( w# O6 \}; ' R/ d; M" q! G6 r8 I) W6 o
, y+ V) Q) m; [& _
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table); : K& Q- { E2 O. {5 k* t
( N2 {9 Q: s! W' ?) y+ E9 }static struct usb_driver usb_kbd_driver = { : b: y4 y1 ^8 _( n
name: "Hotkey",
$ r- j+ A# v _probe: usb_kbd_probe, 4 ^! l& \$ H- ^: F! O# o7 |
disconnect: usb_kbd_disconnect, 7 s4 H: l$ E, p% H4 c9 z
id_table: usb_kbd_id_table,
( y, i: \$ ?" ]1 A( KNULL, - W' [8 }+ A3 v
};
& D$ x% V$ b I% i# _, H
2 l$ f6 w" J1 h. c2 C; `9 ostatic int __init usb_kbd_init(void) / J# `- c5 B! z+ y! ~
{ 7 m1 M! i( [# H; \3 b
usb_register(&usb_kbd_driver);
: O8 W( o, S* T8 P2 ?info(DRIVER_VERSION ":" DRIVER_DESC); " d% A! {5 B) M- S' J
return 0; ! k, I+ O% [# a" Q
}
l- X5 T" B E6 Z# w# Q- R: `
4 E1 o% T* y6 z E% _+ mstatic void __exit usb_kbd_exit(void)
# E% `( ~; \, R' t{
$ ~0 ^" F, T# I8 Uusb_deregister(&usb_kbd_driver); ) Y) j) R+ M# r4 A3 b/ k
} ( R0 ], {$ p# n8 g8 V4 u* |
! Z/ _# R- T; F8 q
module_init(usb_kbd_init);
1 H3 i3 ^4 x6 Q7 Qmodule_exit(usb_kbd_exit); |
|