- 在线时间
- 63 小时
- 最后登录
- 2019-5-3
- 注册时间
- 2004-5-10
- 听众数
- 443
- 收听数
- 0
- 能力
- -250 分
- 体力
- 10122 点
- 威望
- -12 点
- 阅读权限
- 150
- 积分
- -516
- 相册
- 6
- 日志
- 10
- 记录
- 10
- 帖子
- 2003
- 主题
- 1253
- 精华
- 43
- 分享
- 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,
+ b2 d5 d/ v3 n% Z! ~5 F$ c" USB ", " Mass Storage ",
3 _6 ?6 y0 G+ u% yUS_SC_SCSI, US_PR_BULK, NULL, : u3 E* {( ? k3 J6 I
US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE ) 6 S' O# f f# e% _& |/ _1 D
( u( g0 J$ D' q, A( d6 ~注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。 5 K9 L& u7 b9 N$ \* X- k
最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 ' F' s2 W0 ?4 y4 E
键盘飞梭支持 " S0 K8 [: K1 P& U( f3 e' ~
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。
( K; K2 ~* `( C+ @下面是具体看到的信息
1 s+ }1 Y S6 m* U
! S B$ Q; A( c2 T2 _3 kT: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
1 D( X# U8 s/ ]- {0 n# sB: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0 4 W& y% V, m; T
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 4 v! p% Q/ M5 @! z. I
P: Vendor=0000 ProdID=0000 Rev= 0.00 & ` u- r: k5 P! {7 `" B. F
S: Product=USB UHCI Root Hub
# F9 Q9 t3 q" A5 k$ D& U. A7 ?S: SerialNumber=d800
; y0 w3 D* e' H7 gC:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA 4 Z7 X% _/ }, v; Z' Y
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
6 Y, C. c' Z0 H0 @/ V5 e3 @1 hE: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
1 ?+ r! |+ o2 m$ ]* h, X- MT: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 ! }( Y9 d8 y4 `+ y( a F' |8 `
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
+ c. o) U8 c( o, G& YP: Vendor=07e4 ProdID=9473 Rev= 0.02 / K, t/ Y" ~# m; S+ R8 T: d p
S: Manufacturer=ALCOR & {$ y% j& F5 B" |4 l6 T
S: Product=Movado USB Keyboard
0 a/ D2 s% P" O% EC:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA 2 s* F. s% G5 i# H5 h7 M
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
9 n. A8 t/ Y5 Y7 E3 A0 F3 j8 QE: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
, {! _# H F. h找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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$ M5 C2 Q1 U) @& o! y" V, ?0 t$ ]+ l' `! P7 A& o) y+ v
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, - A3 I$ s- S% c) v8 H
usb_kbd_irq, kbd, endpoint->bInterval);
% \+ A& [) G* j- Z3 ]$ i- ]% h* V |; b7 q5 d6 L1 S& [; p
一句中实现。 5 e/ ^7 `7 Z' P" @, G2 `( P
从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。
( C8 s1 d$ J' @- Q在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。
2 v) a# Y! C) H; g0 F程序见附录1:键盘飞梭驱动。 ( i. X! z* s1 o
使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。
1 E; r9 c B8 s' L1 D7 \参考资料 / r+ ]) p& O {$ M& O1 j6 E4 f V
1. 《LINUX设备驱动程序》 ) d% R* v) S( ?4 ~. s, ~& w, }
ALESSANDRO RUBINI著
) }! G4 N9 m$ U3 k! _LISOLEG 译 2 d, I H" X% u k
2. 《Linux系统分析与高级编程技术》
2 O2 b1 L3 Z: c# Z, ?& \0 ?. r( j周巍松 编著
J7 k0 B3 K% [% @3. Linux Kernel-2.4.20源码和文档说明 + s! D1 o5 m7 b
附录1:键盘飞梭驱动
0 f2 N! C' N" o# c7 c8 l& a) w: Q. V
#include <linux/kernel.h>
4 H3 n3 Q, K) T2 C0 f* x3 q# o) t4 [#include <linux/slab.h>
- l8 p' O6 o' A1 L) v- e#include <linux/module.h>
9 n8 {$ Z4 {& K% T% `0 u. d#include <linux/input.h>
6 A0 [1 O7 z% I0 `2 J) f! q#include <linux/init.h> 5 E! X' M* h, L W3 A
#include <linux/usb.h> - I6 j9 Y3 a% I% p! M2 a
#include <linux/kbd_ll.h>
/ X8 h* R- `! K# d5 e) x6 v4 @ i+ l; T( F6 o8 `1 E1 u
/*
/ h, i. e5 p( k+ v9 I4 s i * Version Information + `& H e0 Q" T
*/ 1 n5 i& J/ ~! A$ |# U- ]1 H
#define DRIVER_VERSION "" # P1 \/ `5 p- K+ k$ H* H: L. C* v
#define DRIVER_AUTHOR "TGE HOTKEY " ' n/ G" G8 W2 D
#define DRIVER_DESC "USB HID Tge hotkey driver"
m# ^8 w) s8 Q( `5 S$ c" M1 S* q$ `/ |! V
#define USB_HOTKEY_VENDOR_ID 0x07e4 , q2 r }2 e6 J z- _/ l O
#define USB_HOTKEY_PRODUCT_ID 0x9473 + {# f1 z4 p! X4 M; j8 Z: o( g r
//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
0 K U' t! [) W7 t+ M# V
; s8 O3 C1 q1 UMODULE_AUTHOR( DRIVER_AUTHOR ); 6 @- l+ \3 A7 A5 S1 l
MODULE_DESCRIPTION( DRIVER_DESC );
* k3 a9 a. g$ c, G4 w) T" O3 v7 R
; O9 ?% W( d4 f; Ostruct usb_kbd {
% ~- M2 p& H! d) `" S A# hstruct input_dev dev; 3 `8 Z! }; r8 M. m9 h$ K
struct usb_device *usbdev; , Y5 ^+ Z5 A. i7 v( B. ]7 g' d
unsigned char new[8]; 3 O; b& x5 k) a% j- X% p" {
unsigned char old[8]; + B9 u, K( f0 F! M
struct urb irq, led; * X2 W& V: s) h
// devrequest dr; , `/ o$ e, R2 q+ Y
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化 1 b/ D3 Z+ Q8 b: L* {$ Y9 }/ L
struct usb_ctrlrequest dr;
, r) `3 f5 _3 u9 b* G0 _unsigned char leds, newleds;
8 [6 [5 n8 { F- A' _4 ychar name[128]; ! E' K" V; p" G; P) G
int open; - a8 p z. V: X! w4 S9 t* z, y
}; ; M! q! o: U4 w& v6 T! y
//此结构来自内核中drivers/usb/usbkbd..c 6 j% ?# g) g9 Y, H
2 c/ e4 [ ?) o! P" P
static void usb_kbd_irq(struct urb *urb) M3 E; I1 B- k" t" H7 `9 ~; |' n
{
5 u% E0 @; E" istruct usb_kbd *kbd = urb->context; y/ {% }5 [& k8 I! ^
int *new;
! l6 b1 e% W. H2 X; O& U& ]: [ new = (int *) kbd->new;
% H) Z% T& [+ u* e. V }( G( S7 U
4 T; O u$ d+ [% Nif(kbd->new[0] == (char)0x01)
`/ F* ~# b: H{
- a8 Y2 V* R$ d" S/ Z1 B+ v/ Qif(((kbd->new[1]>>4)&0x0f)!=0x7) k! m' G C" c y; ^1 j
{
- c4 C+ L& e' |) |5 Z3 {3 hhandle_scancode(0xe0,1); ( \3 e$ k5 F( j1 p3 D# V3 ?. }
handle_scancode(0x4b,1);
u& G7 ]' J; k handle_scancode(0xe0,0);
6 K+ ?+ k l" g/ o* s& d handle_scancode(0x4b,0);
/ B# h: H$ |/ w T0 K! q8 v} 5 ^5 P! v# p w
else
" A' b; s3 j7 Q% u{ 7 O; Q4 J( p4 [1 _
handle_scancode(0xe0,1);
$ |+ H& e; C, q4 o0 |& l# K handle_scancode(0x4d,1); & \$ d" i4 _( h+ [. V& ?0 r
handle_scancode(0xe0,0);
" B# R; h- ~2 W" X9 k2 |3 e handle_scancode(0x4d,0);
: Z: W3 v1 t( G- b" E- H' l0 a% B9 h4 @} ; ?/ K# g+ E T, W/ f1 q6 T1 r
} , e& x$ a1 y5 h9 E A
; u$ t N: W3 k6 D5 l/ ~
3 c. w; K k G/ S. }8 Aprintk("new=%x %x %x %x %x %x %x %x",
) l& T/ N3 F/ Ikbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3],
) l& o) q [- j& k" ukbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]); $ `3 ]' i/ w* P) K- N1 Z
+ Z" M; F8 v1 }
} 8 T: G; J% d6 a
) H/ K7 i( H" R! S6 Q' f4 V
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, " _. B' k- K: D, K. d# B
const struct usb_device_id *id) - H& F; l% R% q
{ 3 P: q: Z: q: B2 n* |
struct usb_interface *iface;
) W# s0 r: d3 W- u' V. D# F struct usb_interface_descriptor *interface;
- z& o4 M: U& x& Q- [$ astruct usb_endpoint_descriptor *endpoint;
, A, ^0 j0 f. M! {- ] struct usb_kbd *kbd;
- `7 E' m& g6 G# ^ int pipe, maxp; 3 U3 U% o& E2 V
+ t; Y* k6 Z3 Q+ ^9 e: E
iface = &dev->actconfig->interface[ifnum];
5 ]* ?7 K% f6 _ interface = &iface->altsetting[iface->act_altsetting]; ; @2 V% R" y& b9 W
" ~4 M/ }' {! X, B7 J Jif ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || " H1 q( B, x* O$ u
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) ||
' w0 N% f1 p5 N9 |(ifnum != 1))
# E1 O) l) N: V; w2 T" ?. h. B+ H{ # p! m0 U! T6 K' U
return NULL;
/ _+ J' O2 Q* v% W9 d( v1 R% e} * s/ F2 f, j3 u+ U% g9 e
if (dev->actconfig->bNumInterfaces != 2)
6 p8 Q; Y. i! v$ D# c; J1 s{
/ {" K* H3 k. i; @+ X3 @return NULL; * ?4 ]! N! G3 l( S2 p! E1 s" H' y
}
6 _& k' p/ S( O# s3 F+ ?
) Q/ M# A( @# z8 m- Oif (interface->bNumEndpoints != 1) return NULL; 9 C8 l* D5 }' b3 w9 [; l3 U2 c8 U
% `3 G, b, \; G/ A+ r4 l2 G
endpoint = interface->endpoint + 0;
: z$ }8 n- U6 [% N& A" U
" |6 P. L- S% ^' C1 n( W pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); * D y, B/ U5 ^" F- k6 m
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); . h; e5 R3 y, b2 Z& ?9 H) ]. ^5 ?
9 ~2 t5 T' C5 V4 a7 q: }
usb_set_protocol(dev, interface->bInterfaceNumber, 0); " y1 T* j( a% D4 k% L4 Y1 {' f: Y
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
' r8 Y$ {, `" ]$ |* c( q& W
. Y h/ h" R0 V- j8 K1 x) v/ t4 Oprintk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
, b7 L4 \1 u/ C4 |$ O1 ~dev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); + V: m5 N* H6 C/ M* A3 U7 t
% m# d$ h( V# O+ L if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; ) A( C& w5 j$ v
memset(kbd, 0, sizeof(struct usb_kbd)); / r h) B; Q- c3 z; L% E% k7 t% z. d
6 m9 r0 [. x/ D' P kbd->usbdev = dev;
: [* b# g3 m2 w9 n9 f) G: C0 X! i
! ?9 K7 H2 G' u& |6 w$ s& m FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, , i& U1 P3 t5 C% s# _; p" _
usb_kbd_irq, kbd, endpoint->bInterval);
. d9 v% E, Q1 D5 c8 Q6 S. }. U- L& e K5 D
kbd->irq.dev = kbd->usbdev; : `) K2 h* ~' \* x; W0 s4 S
' Z! w( Z& F) @
if (dev->descriptor.iManufacturer) 3 b+ k1 b! M3 j X$ ^
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63);
6 i( X( N, o/ @$ Z0 F: d
8 a( Z1 U- v7 c. ]/ ]* {5 s' }: Vif (usb_submit_urb(&kbd->irq)) {
0 E5 a1 r& ~& i5 |! Y kfree(kbd); 7 s& l+ Z$ A# g* H1 }
return NULL;
3 A! s P3 D: A } ) b: w0 p6 O, z% K$ n2 A- h
7 }4 [ Q8 ^# @
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n",
: @) V) v- D5 m% T0 y8 |. A- U kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
$ `4 H) W( e* [7 n$ q; c+ Y3 [! | g h; S$ }4 K( f' S
return kbd;
# w$ y* `4 y- Z/ }( g& P4 g}
: R+ S) |: {0 s) X& O- g3 `; m
1 f- h, P; |% e% J( gstatic void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
% R' X5 u, L3 M' f3 q! O$ K" I{ : J* d# f, R& m# u: V
struct usb_kbd *kbd = ptr; & n: X# g6 ` |8 ~. S
usb_unlink_urb(&kbd->irq); ' ]6 s- Y- C* N" Q& b A5 f6 I. @
kfree(kbd);
* P( |; I+ w" N9 P g+ R! n4 f7 z' q8 v( P& Z, y* B- N
} : u) J. ~ M l u) p( u
. w# k9 o) C Z% Ustatic struct usb_device_id usb_kbd_id_table [] = {
- S% D+ }. y; q/ Z4 t7 e4 l{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) }, 9 K" L/ p; o1 g( E& e
{ } /* Terminating entry */ , {7 s% S( j; A s' {; P
}; + S2 [0 R# \# f1 O4 ~5 m- R
+ s5 p4 | B& I2 a8 n1 L1 t2 F2 nMODULE_DEVICE_TABLE (usb, usb_kbd_id_table); ) U! H+ b! x* J. D& K3 X( Z6 k9 |
$ `. h3 C) j7 @: ^6 ]" a' gstatic struct usb_driver usb_kbd_driver = { " M+ [/ `/ ]! ?6 }
name: "Hotkey", . M. I0 }* V% B$ R/ V
probe: usb_kbd_probe, 8 ]' B/ J* n0 w/ X6 m! j% V3 w3 F
disconnect: usb_kbd_disconnect,
8 p0 `8 F0 u! _/ g4 n# j2 Aid_table: usb_kbd_id_table, ; p! D# M7 [* }# X! N3 S$ e
NULL,
2 i% [5 C' v, S8 Z3 w};
1 `1 {. k- n- m. y, v" U& f
; b' u9 e8 q6 o5 b$ `9 E/ Hstatic int __init usb_kbd_init(void) 9 A0 @7 a5 y- \, Y8 E( ~
{
1 X$ f1 D5 l$ N* ^" E/ Busb_register(&usb_kbd_driver);
, u: R4 W7 d! J2 P$ Cinfo(DRIVER_VERSION ":" DRIVER_DESC); , O5 B. {% b. F* H; y- \+ Q
return 0; + Z/ {4 {' A5 K$ w' ?5 w' [6 k
}
9 y0 k l' z2 [/ q
9 b$ T; J! q% d( |) U' dstatic void __exit usb_kbd_exit(void)
" U$ Y( m$ @/ p7 x- m+ T7 ^{ 2 R4 h; @+ K" B
usb_deregister(&usb_kbd_driver);
5 d$ `* S; h1 z5 j: x}
- T- d8 n% @6 ^1 z8 G
6 K$ w8 F# R4 }! |* ^0 umodule_init(usb_kbd_init);
* U9 L6 }( [- A0 N/ N H5 L, B$ v6 Wmodule_exit(usb_kbd_exit); |
|