- 在线时间
- 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, % f7 V! a+ X& B/ s, W2 y' m/ A
" USB ", " Mass Storage ",
8 y. w4 l+ k% f8 MUS_SC_SCSI, US_PR_BULK, NULL,
' d& O: { H! J- w" i4 oUS_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE )
8 b* h! x# J: Y+ L! n2 h. Y" R3 m9 L
注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
- p% A6 _! L$ E$ o D6 C" z! p最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。
Z0 ^. Q' N' I8 D/ z3 F! ^键盘飞梭支持
A1 E- r% j9 J; U目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 1 o. s X8 H; ]5 C) d B9 Y* l3 `8 I: \
下面是具体看到的信息 * a% J4 y4 j2 D5 S0 P
; W, l0 f* |1 ?: s5 P1 ST: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
9 O4 c3 }0 ]* CB: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0 8 L3 O3 v0 @* g. u$ k% E$ V
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
% S5 m7 _5 Q: U: Q: ~P: Vendor=0000 ProdID=0000 Rev= 0.00 1 j8 w. }& d M0 z! `
S: Product=USB UHCI Root Hub , p0 k; M7 k5 T$ v3 s0 R
S: SerialNumber=d800
& R: U5 T- @% g$ B @/ PC:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA ( m% ?: D- i" c1 M1 k3 t6 ^
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
" j8 t# R1 ^4 p8 n; _, IE: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms 5 J, ^) m5 m' S+ ]; m9 F
T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3
' L% P0 v" z& DD: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 " P8 F+ O [& e7 C d
P: Vendor=07e4 ProdID=9473 Rev= 0.02 " v) k/ }2 h4 y$ Z: @/ x9 e8 E, ~
S: Manufacturer=ALCOR
4 M! Q: u$ q8 SS: Product=Movado USB Keyboard
! ^& }) C* P0 T/ L' i, rC:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
' J- A9 `2 X* UI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
2 W5 z! n9 i8 c- a/ TE: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms # T& {+ B1 ?" ?0 p- ^: G
找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中 ! E9 E! \9 h U2 e. T' D& U
9 T" \' C. i" c' V! Q; i" Q
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
2 @8 o- [1 P& c1 X% Rusb_kbd_irq, kbd, endpoint->bInterval);
7 f# w: E. O% S5 [
! V1 I/ ^* m# p( L* M6 J& T一句中实现。 ; c+ q# N1 {8 g( k3 ^4 g k1 n
从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。
: m: h; z; K5 _: ~6 I在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 ) [& f. K+ W7 {2 ]9 C
程序见附录1:键盘飞梭驱动。
' t3 I% X) l' j" J. [) S( c使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。 ' L( N5 [; i: t- f* V
参考资料
& I6 v# O6 i6 e1 S1. 《LINUX设备驱动程序》 ' a( f+ b/ G! _; W. U
ALESSANDRO RUBINI著 - W! p- D" |5 V, M+ d
LISOLEG 译
: N: d4 |$ H% ~" f3 y) s. C4 }8 J2. 《Linux系统分析与高级编程技术》 + `: S! t `% a& q7 }0 o
周巍松 编著
1 c5 O# W8 b* K3 ~$ e* @# V: ?3. Linux Kernel-2.4.20源码和文档说明
5 @( E; V! G9 P" t附录1:键盘飞梭驱动
1 D- Z" c5 b7 N$ Y) ]
+ Y) v, w5 K/ s# [5 \#include <linux/kernel.h> % e8 t& J [7 T7 `, K' B9 `: b
#include <linux/slab.h> 9 \& B! d- `6 N0 Y7 ]
#include <linux/module.h>
7 ~6 C& Z. r9 ?/ X, i#include <linux/input.h>
% O& F) J/ P0 g5 |. {* w. n& G#include <linux/init.h> 0 K% X9 [; Z8 ?' N5 D0 C/ P( V8 U* q+ ~
#include <linux/usb.h>
4 m4 Z6 g/ Z5 ]) _" N) f#include <linux/kbd_ll.h>
- P$ T" n" i7 A9 u: m' q' f' h/ Q% |
: q( K- D& @3 A( B* `* E/* ) a; _8 Z& M# I, S( @& o- a R
* Version Information # @0 U5 S# n7 G
*/
& O0 X$ j. l6 X! \7 R" U: h#define DRIVER_VERSION "" " ^) O- W- ~7 ]3 B- e4 {3 a
#define DRIVER_AUTHOR "TGE HOTKEY "
( `/ L+ E* r/ Y0 r% x9 ?#define DRIVER_DESC "USB HID Tge hotkey driver"
& ^0 {$ x. F! n- x9 f- X/ S' Z5 ~8 T
#define USB_HOTKEY_VENDOR_ID 0x07e4
! B: a9 i; _# a9 d4 g, N& e#define USB_HOTKEY_PRODUCT_ID 0x9473 " |" S# {9 l: q3 l, ~% m
//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
- f' f* D! E1 T: q- `% O1 ]" A3 K
9 }: _: v3 G$ oMODULE_AUTHOR( DRIVER_AUTHOR ); ' j+ w, |+ `" k* f4 ^7 L0 t5 _: h7 L' K
MODULE_DESCRIPTION( DRIVER_DESC );
# ], {* P: O! G T# G8 F3 Y! b3 ?0 V' d* `9 Y$ Y
struct usb_kbd {
4 c2 y' x) h# T, |struct input_dev dev; 0 o. m& x5 ]7 ^+ O) u3 J% m
struct usb_device *usbdev;
" \. a, P v) h- A3 X* o$ {unsigned char new[8]; " b+ r- Q& \, I) e, O* u/ Q+ f
unsigned char old[8]; 1 L' `6 v$ q1 f3 H3 j
struct urb irq, led;
7 @" j6 W, F3 D( j# D1 l// devrequest dr; 8 x @8 ^1 G( F6 M( i% z
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
; U9 y: A) [0 p, O( @ struct usb_ctrlrequest dr; 9 i! R5 d: Z) g- s9 T
unsigned char leds, newleds; 4 W, w+ Q: r. y5 W
char name[128]; , c1 r3 c- U3 c% D
int open;
# h* r* f* `+ b' R}; . J9 ~+ U2 W$ N0 s3 v$ w( }( Z
//此结构来自内核中drivers/usb/usbkbd..c 3 f, t7 H& Y$ n( {, h& m% k1 z8 _
4 M p9 F9 h! b
static void usb_kbd_irq(struct urb *urb) ' W6 \3 E9 C7 v) d
{
% J2 `: @" q' x& d) ?, p' qstruct usb_kbd *kbd = urb->context; / G2 W' `8 h" u/ ~
int *new; % g& k$ C4 X2 Y+ p. W6 t
new = (int *) kbd->new;
0 c1 j& O0 ?8 B8 S
$ w" C' X; X5 }! J6 Q& A Wif(kbd->new[0] == (char)0x01)
; m: q+ G5 ^ ~2 @3 J" |0 ]0 C! U{ ( d3 s, E' C" Z" Y8 Y8 d
if(((kbd->new[1]>>4)&0x0f)!=0x7) $ \& z( K' g8 @8 w- [- X9 m
{ $ b% C- ^' J, ^- l5 a
handle_scancode(0xe0,1);
: W% x3 j6 G3 u7 b1 Xhandle_scancode(0x4b,1); 6 p% j/ t# z6 I6 i* H+ k
handle_scancode(0xe0,0);
5 z% A5 O$ I7 G% J* q0 w. C- N1 k handle_scancode(0x4b,0);
* K' C& H7 e8 t; b' w& X0 t+ B}
. K+ |- U0 J/ W" |else 8 M$ V8 S3 A9 }; H0 x& Z2 l
{ * N, y* \/ j5 _2 p. A
handle_scancode(0xe0,1); 8 s" q' C+ R5 c" G5 @5 z& a8 A
handle_scancode(0x4d,1); * a* s( t4 F. q6 Z+ L
handle_scancode(0xe0,0); ]% `5 E4 _+ l# k8 G _9 p i
handle_scancode(0x4d,0); 3 ~( S! A- n/ G3 O2 w1 F* K j* y
}
# k# C, k* C; J5 P3 l}
* n; B3 q2 Y% R8 f% b3 w; }% c0 z2 K2 V' _- B, `* G2 L- `
% c+ {1 I# G2 h% i& L
printk("new=%x %x %x %x %x %x %x %x",
3 {8 D4 u: h( e( `3 H3 Akbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], / {+ u4 O( `* b; ?1 w5 F* u" _
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
1 L* T: w3 E5 ?" Q2 U2 g8 H2 Z7 M/ f) Q, @* u& B8 X& I# t# }
}
4 `1 n, q; I; {: G/ F* T& q: W6 D! h7 B! m+ Q0 V
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, 9 U% P) Z; o, C3 \# A3 ?9 F; h
const struct usb_device_id *id) 3 o" W' c& W f1 ]& Z1 u8 _7 A
{
) s) e' r' h( r7 X8 ]7 hstruct usb_interface *iface;
6 b/ \ h' O% Z9 @ struct usb_interface_descriptor *interface;
) w' |3 _+ p; H! {( a) _: Xstruct usb_endpoint_descriptor *endpoint;
( ^ |& e, d4 R1 ]% O" i struct usb_kbd *kbd; ) {6 i. Z+ a. f
int pipe, maxp; 4 ~1 ~3 F" z1 l. s% N( ~
% b/ }1 x T! L8 ^iface = &dev->actconfig->interface[ifnum];
: P2 C! J! v8 @ interface = &iface->altsetting[iface->act_altsetting];
9 l, F3 o4 E7 O) L) e$ O! \$ Q& t' b* R8 d
if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || 3 Y# J. H$ {5 \% g/ T2 b
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) ||
% V Q$ ]8 G+ C! U$ j2 w" Y(ifnum != 1))
, h9 i6 a; _$ [5 b/ l5 u{
3 N \6 b' |( O0 z: @return NULL; / Q0 L8 l( D2 d4 }3 E
}
- Y k: q9 [" z! t, E7 a/ `if (dev->actconfig->bNumInterfaces != 2)
8 p8 M# j- v+ r# _{
, r. \: A9 @1 rreturn NULL;
' k. U: T0 D' e0 Q* H+ t}
+ i* ^+ h2 q1 r& D% ]
/ t' Y" w1 g8 {, Aif (interface->bNumEndpoints != 1) return NULL;
0 e) U; l1 A/ ^% m
- m4 _( ~/ V) i$ T5 Y* M) i endpoint = interface->endpoint + 0; % D( H" y5 h' p8 C" v4 S
# N" ?7 k# A+ u( H& U3 a4 J5 x pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
1 |0 P) K0 w+ [ maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
. S: W$ Z' ~0 c# L; G, Q- o2 X) g& S* W0 I
usb_set_protocol(dev, interface->bInterfaceNumber, 0); * n5 C }: e) |6 f9 u/ h4 ~
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
& d" U; w4 {5 k# s t# |; [0 w
$ L/ k! Q- Q# K# [: U% r8 iprintk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
8 V6 y5 O, z) t% N1 sdev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp);
' h6 m/ c z; r
. s: x& X/ O+ B3 I if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; 5 U7 h7 Q- E* E; u- B9 M
memset(kbd, 0, sizeof(struct usb_kbd)); - L' L" v0 i' c; Q' f
" L$ i: M9 z: D kbd->usbdev = dev;
5 i: `, R3 m7 F/ X9 k) ~6 N" ]2 e+ l' }' v
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 9 h& |) M$ m) L Q
usb_kbd_irq, kbd, endpoint->bInterval);
6 a6 b8 t. E& Z- m4 |
5 i8 V5 ^$ A/ Ukbd->irq.dev = kbd->usbdev; 2 \% T/ U/ f3 Q* n) c* M' R/ V; g# i$ A
. U0 D0 e7 Q1 z. Z
if (dev->descriptor.iManufacturer) 6 p; {6 C# B2 [! `8 a9 y
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63); " H9 O1 \$ X) }* x- d$ O
1 B( l" G! {2 F/ u% `( xif (usb_submit_urb(&kbd->irq)) { % c" N" E' P7 F4 B7 Y2 D
kfree(kbd); * j0 q& e0 S9 l
return NULL;
0 N, @; b( W$ L }
! K3 Y% f0 Y4 v' P% V
2 ^% x6 M# {" mprintk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n",
1 A+ p2 l$ s1 | n" } kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); 7 g, t' K7 n" M% x- D
! W& I- a# T8 _( x" _% a9 q
return kbd;
) W7 F% m! [, q5 ~6 D} / [3 |6 X! X( \1 z+ Q
; K3 z8 Z3 w" x4 t3 S2 X
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr) : S0 N! F- v! z0 Q
{
% i9 g, z* M2 l2 X I& c" astruct usb_kbd *kbd = ptr; $ E9 E( L! o9 F4 M8 j
usb_unlink_urb(&kbd->irq);
! `7 f; n4 ^& N. W c kfree(kbd); ' n# @( J( w/ w' `/ B( \
8 U9 M0 H+ \9 S' ]2 E4 R0 L
} ; V' t8 V, p$ k |' B+ z
0 ]8 k/ }9 L9 ?$ Fstatic struct usb_device_id usb_kbd_id_table [] = {
* Z6 z0 U/ m% |{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) }, $ z7 \) D, Z3 ? m; l2 f5 O- R5 D, }
{ } /* Terminating entry */
3 W, z8 A( b1 @};
* |; F q5 U% E4 J8 V5 E% f- `" v" \. K! m4 k; |0 f
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table); $ A7 r' x/ g2 u, P8 p. `
0 K1 I4 `! P& V a2 i
static struct usb_driver usb_kbd_driver = { - I P$ u$ w- t0 n$ i$ h
name: "Hotkey", & A" j1 `) ]/ Z6 ?1 M5 U, w
probe: usb_kbd_probe, 7 ~1 E) J6 y7 ?* h( w6 ]5 E
disconnect: usb_kbd_disconnect, 4 S% K" |) e# P/ `) Q
id_table: usb_kbd_id_table, : v) F4 m& F+ d8 m( u8 N
NULL,
( }, o0 F/ {, ^5 @! U}; % {0 p! ~! L3 L* a
% e$ k/ q1 b# r! S# _4 l8 x j
static int __init usb_kbd_init(void) H, b, A: W2 X4 T$ x
{ 1 F m& V4 G& ~% n5 q( D
usb_register(&usb_kbd_driver);
$ `- Y0 P5 |) F jinfo(DRIVER_VERSION ":" DRIVER_DESC);
* W1 @$ t( r2 x$ [2 u9 e' U) kreturn 0; 1 y* a/ G& D- B
}
5 ]* @! W5 l# R. b/ j% g
5 }8 K4 p! e, e M* K7 S0 Z1 Ustatic void __exit usb_kbd_exit(void) , p' W$ O* _* m# l
{
& [2 K& O1 m5 J# v. B$ xusb_deregister(&usb_kbd_driver); 2 T& F! @4 [' C O
} 6 u0 X ]! m$ T2 R& {
" m$ R G: R9 F' J3 D' W
module_init(usb_kbd_init);
/ {, h$ d1 Y$ i, W4 s; x% c/ dmodule_exit(usb_kbd_exit); |
|