- 在线时间
- 63 小时
- 最后登录
- 2019-5-3
- 注册时间
- 2004-5-10
- 听众数
- 442
- 收听数
- 0
- 能力
- -250 分
- 体力
- 10122 点
- 威望
- -12 点
- 阅读权限
- 150
- 积分
- -586
- 相册
- 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,
T# H0 c9 {9 d6 H( [! @" USB ", " Mass Storage ",
* k. b9 B/ [& h) [US_SC_SCSI, US_PR_BULK, NULL,
# ~& p. n) i/ Q* T8 N+ z& gUS_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE ) & N5 E& M p, U( Q; E% q% J# l" i
- C4 n; w- {8 L% d0 p4 B
注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。 $ d# l/ ~7 l: [% o7 Q, L' q
最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 2 G& k8 i8 E. w* R
键盘飞梭支持
- q* C4 u8 d4 Y" H- M, ^3 u目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 8 U2 u' C# o+ }3 W! b. c3 j
下面是具体看到的信息
$ {1 n# j& l5 D) [8 m1 i( H9 L+ g) U6 R! g! k
T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 , y3 Z. q5 L- m% M: A
B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
# ]( m2 Y, o. M; \- d1 lD: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 2 D, r- ?- u0 T- G
P: Vendor=0000 ProdID=0000 Rev= 0.00
* E7 H/ x6 ]8 b p/ H2 \S: Product=USB UHCI Root Hub
, M l) s/ c9 R9 a0 R: p$ W" JS: SerialNumber=d800
/ w9 u' s7 ?( s0 i9 C5 z+ JC:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
8 J0 v) f9 R( Z; r7 xI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub 8 L- P1 r. u& A8 m9 T& q
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms 0 Z/ ^* L) U, }" p. M0 `$ g) G
T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 ! v7 Y# O: }% B* |
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
1 J& J, e+ C7 h$ l4 [7 YP: Vendor=07e4 ProdID=9473 Rev= 0.02 5 y% k1 w+ }- e0 Y: \5 j8 g& E( Y
S: Manufacturer=ALCOR
1 C5 c" h$ W. V: M) d9 p3 OS: Product=Movado USB Keyboard , G" z! b2 v! x2 j1 u! ? q4 Y
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
! T# g1 p6 i, LI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
( O/ K4 @6 g* r6 T, B6 VE: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
7 V N; b& k6 \4 T找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中 % J3 |, f/ {- S. B2 B$ n
3 t1 E6 ]7 }4 mFILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
% N, N" ]2 |$ L& jusb_kbd_irq, kbd, endpoint->bInterval); ! L f' N3 R* h: B/ J" I8 u* j, `
; f4 Y0 X" y3 |2 A
一句中实现。
( D, e. q1 C7 t$ z% T, [从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。
9 |+ _; Z" `; j3 C' l* I6 ~$ ^+ h+ J在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 0 q9 ]9 H$ y& w! |; K, Q
程序见附录1:键盘飞梭驱动。 ; B1 I8 Y$ G; q6 d: e
使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。 * l" ]' S7 n& Y
参考资料 + f3 s5 ?) U- F% ?
1. 《LINUX设备驱动程序》
. `9 Y$ G7 ~! e5 F! y0 I6 L( @, z. [7 kALESSANDRO RUBINI著
3 z( n7 ]" i, ] A7 s. zLISOLEG 译
/ B T& L+ }, S* W2. 《Linux系统分析与高级编程技术》
0 p) ^5 r+ n" x K5 U周巍松 编著 " s: _9 A2 ?- ?; S5 Z; B2 R. t
3. Linux Kernel-2.4.20源码和文档说明
: p- D) m1 {1 z6 u4 s6 B% y G/ e附录1:键盘飞梭驱动
7 r) ]4 l. _# D' L; A1 d2 m2 q' x9 o5 ~, l J& a& O
#include <linux/kernel.h>
% c, v, J( Q9 T/ n% s* M#include <linux/slab.h> 9 d% B* G7 ^7 Z* y# `9 g
#include <linux/module.h> 5 f' F" u- F6 M/ M) @3 r4 o
#include <linux/input.h>
2 G" _9 P+ U/ F6 _# B#include <linux/init.h> $ @6 R& |% h% ^$ k/ }5 d, I
#include <linux/usb.h> , l$ h3 J6 P: l; D9 X
#include <linux/kbd_ll.h>
. V5 ]6 S6 R! O0 S4 k* r1 T% l
5 T' s$ ^, L8 I& p$ ~& G- c! z/* C' W7 V4 a i2 R9 F' w4 o
* Version Information
& O6 S5 |. Y: M3 M. t2 S1 M$ x */
0 P+ R" l% p, S, |2 |% v#define DRIVER_VERSION ""
% E6 f2 e ]" _#define DRIVER_AUTHOR "TGE HOTKEY "
$ I! }- Y) [8 J# N; b0 N& ?#define DRIVER_DESC "USB HID Tge hotkey driver"
7 ?, j d( \6 f/ K0 V: W7 _8 U5 Y( j' a
#define USB_HOTKEY_VENDOR_ID 0x07e4
/ d" n. V$ @1 }#define USB_HOTKEY_PRODUCT_ID 0x9473
) i- r& u, ~( o8 B7 K5 T8 c# G//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
5 V- R/ U1 I1 h5 w# a' \9 Q
+ m) j. o! f% d* ^) M7 lMODULE_AUTHOR( DRIVER_AUTHOR );
/ }5 q8 z0 |+ q u" \4 QMODULE_DESCRIPTION( DRIVER_DESC ); ( K; m. J# {6 ]3 z% h: j8 u
0 y1 w# ]2 \2 _4 `: h/ i
struct usb_kbd { 3 J/ g: b, n ~: T( z6 r7 r
struct input_dev dev;
/ F$ Y$ @. [6 ystruct usb_device *usbdev;
8 h' g7 n& b# q3 B% H+ U/ u( ?unsigned char new[8];
" K& @" f# h9 f8 X5 p7 C2 K- Xunsigned char old[8];
1 s0 {$ ^8 {0 `2 Q" e+ ]6 Y4 [struct urb irq, led;
0 L+ V0 T& K* ]# w// devrequest dr; % }' @3 X( j0 @& W1 z; X
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化 + a0 E; r' Z, P' l
struct usb_ctrlrequest dr; $ U' T J7 E& z( h
unsigned char leds, newleds;
" Z' ?1 h2 K0 z7 [2 S8 ]char name[128]; 1 o5 R% `( Z# w x/ _
int open; 8 Y9 l- L- g3 K* s
};
/ H" [ _+ P/ }5 `# z2 ?7 d//此结构来自内核中drivers/usb/usbkbd..c
- l& C: k+ L; i/ |
) w& |: z- E9 V0 bstatic void usb_kbd_irq(struct urb *urb) ; f" N \. x" X* |6 d! S' R
{
# k" {) n5 b" F, bstruct usb_kbd *kbd = urb->context; ; r6 `2 n. z5 i- V& v& s
int *new;
3 K( P: v+ @8 ^7 V f8 t new = (int *) kbd->new; 5 m* ~& a( n% ^6 Y1 C& `% v
! t; n& T' G; L* uif(kbd->new[0] == (char)0x01) - V3 a# p6 S2 A: I, I* M7 J$ j
{
+ o: \: |5 N6 l- yif(((kbd->new[1]>>4)&0x0f)!=0x7) * C$ T) a7 Q& s1 \5 p
{ ' n( J; v" z ?/ U, H1 X* e) t
handle_scancode(0xe0,1);
8 A. M6 I* w* w5 ehandle_scancode(0x4b,1); 5 N, w% N/ l% }# x3 F& a7 Y! L
handle_scancode(0xe0,0);
" W# r+ \& j0 y K* q! j handle_scancode(0x4b,0);
; A Y& e2 i7 G! G} : k; o, r- j2 e- m1 O# y
else
. B& ]% O1 {. j) i/ \2 e$ `{
) E, S* I; K1 d6 M: I/ mhandle_scancode(0xe0,1);
/ _8 _# r0 D5 E7 x' V) F/ S q2 @ handle_scancode(0x4d,1);
o- v- q4 t$ Y5 @ handle_scancode(0xe0,0); t5 C# u1 h+ W" ^5 P7 ?
handle_scancode(0x4d,0);
) K8 m8 \" t% K- n# Q0 a" U9 I}
/ N5 ?, d q$ }. P; H}
/ F' _7 S P& ]0 @ E" k0 D/ `: A' G0 X1 q" x7 L+ t
$ R, h, `+ W. j+ D9 A3 v. b- {
printk("new=%x %x %x %x %x %x %x %x",
4 ?4 ?+ f* O- j. r# C+ K$ t {! Bkbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3],
/ q6 j' G1 s* K; kkbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
; W N! k, A0 `6 [4 E
/ H: {, Y$ d+ F0 L: y} 2 D# q' w- A( M8 s
8 y b3 p+ J8 t& [3 v! o
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
5 K! V4 @! z' w" U6 m) ~2 v2 Z" |( K const struct usb_device_id *id) ; f+ E/ H( [$ g: s- u7 A& s
{ 3 |$ J! w3 f2 z
struct usb_interface *iface; 2 c; u. w: [1 |: f& d' E7 Y5 E$ y
struct usb_interface_descriptor *interface; : N5 \9 K; y: `8 }* [: Y5 m8 F
struct usb_endpoint_descriptor *endpoint; 2 ]% O/ r, f& _5 @$ o
struct usb_kbd *kbd; % U: v4 ]; H& U( F" T; J' v ~
int pipe, maxp; 1 e; L/ [/ x, [; n/ N0 Y
9 v% I/ ?) C& p, miface = &dev->actconfig->interface[ifnum]; $ C5 K9 ^! M$ L% B# P& d
interface = &iface->altsetting[iface->act_altsetting]; + \& Q6 m3 q6 B! p B( b
( F3 X- d N& j7 R t: Q
if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || + k6 Z- L: U, W. ^ I% @
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || 6 Z+ x/ ?/ w5 Q5 ?6 Z
(ifnum != 1)) U' S& r1 `6 ~, o- M6 a* t5 U
{
* P+ r% \/ C) @1 G( j0 `5 k: Greturn NULL;
/ ^6 @9 F. F. o/ E, ] u1 h}
+ `+ y [" A6 P, c$ w! C- Kif (dev->actconfig->bNumInterfaces != 2)
m* b6 o) l. L. _{
* @) o% ^( A6 F& t2 xreturn NULL;
' S5 h% j" A. e" c T+ r} & n P, I( N. `! r/ U2 [
( P, `% V1 Q% A* @& x" _ ?! u/ v
if (interface->bNumEndpoints != 1) return NULL; ! @) { X, k& f0 Z: h" x0 a5 x; Z- N
: n5 G3 I1 u5 u, t
endpoint = interface->endpoint + 0;
' Z: W4 `, m* A: R# R
5 `1 P4 J" s) [ pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); 5 \5 W, l" g$ O# I
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); $ ]8 Z, d1 ]( Z! a% `
7 m- F9 j& J ]
usb_set_protocol(dev, interface->bInterfaceNumber, 0); 2 J. ?) f; q6 I. u
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); ! e& \ g' ?' o9 K) d
3 w* c8 `' ~$ x' w; qprintk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n", ! _- X* }8 T% r- f3 o) S3 d
dev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); ' n* h' O6 t Z2 z; r' V; h
- h3 L2 W6 E( H2 m: E if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; 3 K+ {- A8 u( f5 T& K7 j
memset(kbd, 0, sizeof(struct usb_kbd));
( y# b5 I# _; [5 W0 R1 {$ b
' `: w3 o/ g: I Z- ^8 L kbd->usbdev = dev; d6 I/ Z# M( f- ?
" k3 o1 a+ z* A3 e6 W: }" p FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 0 z2 }, @: x, I, W; K
usb_kbd_irq, kbd, endpoint->bInterval); ' f6 S" u6 N: \3 m4 M* L: R
" v, [. e: |, E8 m& L
kbd->irq.dev = kbd->usbdev;
( U0 s) J6 x. Q8 @
7 v) I" n; ]8 m0 K$ U0 b dif (dev->descriptor.iManufacturer) ( f% `3 W/ F6 r) l
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63);
; B" S, L. p* o& S( {# X) o8 c- m- ~0 c: T' g- F3 P
if (usb_submit_urb(&kbd->irq)) {
4 u% | m0 b% d6 b, ]4 Z8 i kfree(kbd);
1 y5 ? I, K% I& T6 ` G. y i" C4 L return NULL; ! c' X, }8 W Y$ N6 g% C5 s
}
% g* F5 [ U% ~
- h* d- {6 _/ I# X' ^8 Gprintk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", / `( c @! }( A4 \0 Z7 e
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); . \+ [. D0 b9 [2 C3 Z
, ^1 q3 O0 B1 n t) Q3 g return kbd; ; ^0 c: Z0 V0 o
}
# l, w6 u( E$ q! P2 b. y$ A+ \; i# z' J/ l4 z( D b1 m' J
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
: p; p! s3 R$ w! d( ?{ 4 p5 y4 ]/ j+ \; Z8 d3 J$ H
struct usb_kbd *kbd = ptr; 2 R, G1 k) v; O' X
usb_unlink_urb(&kbd->irq); $ a0 Z: B3 ^; a+ I2 S: T
kfree(kbd); 7 {4 h8 T7 }* @
2 t% [& }$ L& L' N( j" X
}
1 @, y* c% V' }0 X3 ?+ O4 q
, s0 w1 ^/ v: g1 X J1 @1 |* xstatic struct usb_device_id usb_kbd_id_table [] = { ( o0 w! Y9 @3 B q" ^4 B' ~* P
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) },
7 k- k7 Z7 }7 e; a& g8 s! I{ } /* Terminating entry */ ! Z, s& x4 W" L. g
};
6 w! C1 o/ h5 v) x! r
0 R f0 q9 @! p7 eMODULE_DEVICE_TABLE (usb, usb_kbd_id_table); $ z: c5 Q" c0 ~
- n0 P4 K/ I5 b4 N- W0 @$ gstatic struct usb_driver usb_kbd_driver = {
/ F! k/ x) b+ ~4 s+ I# t4 Mname: "Hotkey",
+ A* ?( ^5 h+ b$ {8 \; p9 G& X- gprobe: usb_kbd_probe, ( K, u$ Q3 J t* m8 g
disconnect: usb_kbd_disconnect,
/ U* _; G+ u# uid_table: usb_kbd_id_table,
$ e' G$ q; v: l" M4 dNULL, $ i/ e+ P7 Q3 R6 J* A# [
}; ) \$ D* O4 n ?
( J( d5 Q2 l5 N; Kstatic int __init usb_kbd_init(void)
7 J0 l \' N4 d: B8 V{ % M: y) A: H" F
usb_register(&usb_kbd_driver);
' |4 r8 E7 J# v- S) z; ?info(DRIVER_VERSION ":" DRIVER_DESC); / ^7 G- E1 U4 y2 [. r' v/ N
return 0; $ W2 a7 D( T) S# f2 T3 ^
}
) L w8 `( c" Q% ]# A# k7 R' H' [) X" e; p& Z) B( T
static void __exit usb_kbd_exit(void)
& G. `% Z+ n" f{
! P$ z6 a5 r! |. E' Husb_deregister(&usb_kbd_driver); - @4 L3 b$ I. ?/ E7 T
} ! o! C/ W0 h) a" h C C/ z# H
8 D( R; g& z8 t
module_init(usb_kbd_init);
7 H U& K# B' ^+ Hmodule_exit(usb_kbd_exit); |
|