- 在线时间
- 63 小时
- 最后登录
- 2019-5-3
- 注册时间
- 2004-5-10
- 听众数
- 442
- 收听数
- 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, , x& K2 ?4 k( U6 |% ]0 k4 y/ p
" USB ", " Mass Storage ", 5 S0 j/ u- ^$ R: J
US_SC_SCSI, US_PR_BULK, NULL, ) `) w! N7 p7 `8 C: @
US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE )
; Y$ h5 n1 n3 e; `* i% I; C. I/ C3 c4 H
注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。 % ~$ R& I/ i4 Z9 C3 S4 l, t
最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。
. _' v) r, y+ ?& L) n键盘飞梭支持
* I1 f- c$ J* H3 l) K* l目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 2 {9 ^" J+ [2 V4 t4 e
下面是具体看到的信息
4 i; N5 P% G1 ?
, A. g K1 K+ QT: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 , k( \8 P/ V) }+ D- x- ~; G
B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
* ?8 o. i% ~4 o SD: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 , u$ b" M1 e6 Q6 ~
P: Vendor=0000 ProdID=0000 Rev= 0.00
6 e# ]7 Q, ~8 pS: Product=USB UHCI Root Hub 5 c! C: ~" B7 A3 }! f8 V4 I
S: SerialNumber=d800 S! q6 |4 ]8 u" | z
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
! {! _" A8 ]( Q# E) v3 L/ iI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
; t# j9 y2 j, `0 L: \3 nE: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
. R* U1 I$ l4 a" X: T2 @0 VT: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 9 o) @2 W' H" ~$ v6 [7 }
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
% x- |" f) @2 i6 AP: Vendor=07e4 ProdID=9473 Rev= 0.02 " r2 r! I, h3 d. S
S: Manufacturer=ALCOR
0 h6 ?* z( D/ ~8 xS: Product=Movado USB Keyboard ! V4 {/ F8 ?+ t/ ^* r7 e
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
( l# V( B; I' _ u8 }4 E: t5 sI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub + `. \9 N/ D' ^
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms - Z+ h2 X. O6 ^6 k7 x) Q
找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中
( ~- K' ?: G, T8 [) |. \+ o3 o. G% x; D: F _: U; {8 I2 p" ~$ V" \
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, ( Z7 q% D g9 [8 G, h; X
usb_kbd_irq, kbd, endpoint->bInterval); # p/ ]5 U G9 l* v
" P V3 n5 K* r. ~6 D
一句中实现。 - s4 @" i' z6 c, L
从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。
: a8 H; p5 K: v- o, t在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 ! W7 u* p& D% N( M# r0 g/ |
程序见附录1:键盘飞梭驱动。 ) m! b e& v$ j6 m. D1 ^0 x. r
使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。 , r1 L" S7 y3 u* q, P+ H! u6 a ~
参考资料 0 I6 }( l+ H: ^7 L6 _
1. 《LINUX设备驱动程序》 / u, L: E0 n% m a! ^7 N* r9 M
ALESSANDRO RUBINI著 5 D3 `% ?- W" I
LISOLEG 译 " ?' s3 u% ?1 h" @+ }8 n
2. 《Linux系统分析与高级编程技术》
1 f* @- f" v4 e7 K3 b周巍松 编著
2 g! F% T. u& \, q; k9 y1 O5 j2 W3. Linux Kernel-2.4.20源码和文档说明
+ U5 Q8 |& C7 \( ^6 v' A$ ^附录1:键盘飞梭驱动 # Z5 G9 v; w% P2 v8 t" N- O+ ^$ I5 P
3 M. g0 s' \0 b- L: m#include <linux/kernel.h> 4 c. l! Z2 t. t- Z
#include <linux/slab.h> 2 m% K3 O; U1 k- O
#include <linux/module.h> % s% g( g( r4 v$ _7 b, N$ t5 C+ `. }, s
#include <linux/input.h> 1 Q" r0 }4 Y# j5 ~! H2 D
#include <linux/init.h>
9 Q O0 t: r- ~3 I#include <linux/usb.h>
6 v0 Y: g2 b+ S5 M9 l#include <linux/kbd_ll.h> ; U& e E2 d5 @4 B" e$ y
% E& m2 A$ g% J. z; a$ B/*
: L8 B' S- _4 v) V$ F% F, n * Version Information . ], c6 R8 h3 o Z. r5 Q7 ^% o
*/
j d9 p+ d1 ?6 x* q! F* [: c& l/ N7 Z#define DRIVER_VERSION "" 5 q0 w6 F7 P* M9 ^* c6 x X
#define DRIVER_AUTHOR "TGE HOTKEY " h! P" f. ^2 p( {& R
#define DRIVER_DESC "USB HID Tge hotkey driver"
7 x* n$ t- c# n6 Y7 N- `$ G/ r/ f2 }
+ \* s: n% F: X2 _. S, ~#define USB_HOTKEY_VENDOR_ID 0x07e4 ) e7 @! N4 h4 j* T
#define USB_HOTKEY_PRODUCT_ID 0x9473
/ e+ i, Z4 i$ `1 i& [//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
( b4 X) d Q6 G5 h- D2 o9 G% I$ l+ F- }3 _( V8 v
MODULE_AUTHOR( DRIVER_AUTHOR ); / B" T3 ~/ j w2 Q% K; }
MODULE_DESCRIPTION( DRIVER_DESC );
9 y- f7 U1 r2 J/ E/ y Q( g9 {
struct usb_kbd {
+ Y4 c0 D) h7 c1 ^* r5 Astruct input_dev dev;
" }) b& J% v: d2 y# Rstruct usb_device *usbdev; # f3 C/ u% {! q1 n
unsigned char new[8];
' R/ }* n- z& G" Q+ zunsigned char old[8];
8 |' |2 f5 l) }+ _: Y5 Ostruct urb irq, led; : `) h% Q; ]! w/ I; b" F/ D
// devrequest dr; & v2 O: u9 U; o; ?
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化 & \; t" c+ n. O! k9 u
struct usb_ctrlrequest dr; ( h( S5 |3 b" G! n9 E- ^' ]
unsigned char leds, newleds;
; r, a" g5 b9 T; v$ Uchar name[128]; 4 g. z8 X k5 B6 E
int open;
# ]6 H. L6 E( |* j/ z. k) Y}; ( n* x4 P. w! j$ F9 V% u# b# E
//此结构来自内核中drivers/usb/usbkbd..c
! U P( r0 X8 H8 V/ Y, N& i0 }2 |/ F
static void usb_kbd_irq(struct urb *urb) 0 I/ ~/ g y9 p6 i. _0 d9 U* P. C
{
2 K% H3 ^6 |' |7 ~struct usb_kbd *kbd = urb->context;
2 e9 Y d) c+ L8 U6 O ?1 n* A int *new;
/ s7 l' |3 i6 v, Z new = (int *) kbd->new; 2 s8 F# q/ Q+ ?% z2 ~3 e
* S* F6 i! v! t' q
if(kbd->new[0] == (char)0x01) * N3 S1 W9 Z7 w1 D
{
* S9 ?3 z! A" G/ T; a' Rif(((kbd->new[1]>>4)&0x0f)!=0x7)
7 @! _7 `2 p) ]{
4 }- `5 Z# |2 u7 h8 ?handle_scancode(0xe0,1); + R0 u/ R( D& ~- A. b
handle_scancode(0x4b,1); 3 f" R; S4 [3 o' W* u. c6 ]
handle_scancode(0xe0,0);
3 t; `% I0 |" @ handle_scancode(0x4b,0); ' K" u- [; ~) w3 R4 P0 v
} " s# A( i. z$ B* Q$ k
else
' R7 `2 i/ c3 I- V- ]{
5 t: p7 M! P% whandle_scancode(0xe0,1);
. ?7 y# U- z! k, D0 D handle_scancode(0x4d,1); & X$ C; t: B3 p2 @# w% g$ C J3 p% D
handle_scancode(0xe0,0); ; r* y% O% I9 }3 ]; r8 B' V
handle_scancode(0x4d,0);
% R) s" e* X( ?# h6 M' G1 N1 Y} $ g% `# m: ]+ L6 B" ^0 j& n$ Z
}
& _. P5 E% L+ R) ~* C
8 X! h- w3 F: N+ K4 R6 K( q
5 E* w) B- J/ A* X5 rprintk("new=%x %x %x %x %x %x %x %x", ! @- n# f' U1 F7 t) ?/ o
kbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3],
0 c& i3 o9 D9 t# J" hkbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]); % ?" z! _- \( i4 M8 ?; F
- q$ b* Q& ` q6 r8 d& w( |" m% q
} ( |0 }4 {# {6 q' ]0 p: r
3 ~0 L: {+ T9 [: ]' L. @7 `
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, 0 J5 t4 w) T. Z
const struct usb_device_id *id) 1 O# _9 T% t8 q
{ 7 h# M% N6 y p" q
struct usb_interface *iface;
0 [/ g' j+ ^ R" _ struct usb_interface_descriptor *interface;
" K( C1 o& F8 V$ l _struct usb_endpoint_descriptor *endpoint; " ]: L- g$ y2 b$ o9 M
struct usb_kbd *kbd; - i/ P- w2 i* j9 E
int pipe, maxp;
* s( @: F7 ?' ]0 Y) G7 _( ?% M, {. I U
iface = &dev->actconfig->interface[ifnum]; 2 Z: v3 Y) o6 f" Z& n
interface = &iface->altsetting[iface->act_altsetting]; / q7 w, y8 C1 s* x: A6 ?, y' F* ]
0 l \/ Z$ k5 Y0 d( r, p* [) Gif ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || 9 ~! [: g! R' V5 f* Y/ j/ r
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || 8 L9 i( s( d% t; G
(ifnum != 1))
' n3 x8 t- b* V{ & W. R- K$ C7 u, V: t7 \, K' D& s
return NULL; ( \* l' U3 k7 r& U$ j
} 4 i g+ v3 e" D. L+ P- w$ C* a
if (dev->actconfig->bNumInterfaces != 2)
7 N0 Q( N U9 n% t{
) u- ?; D" Z* S& ]' T( vreturn NULL;
; b1 c/ V+ \8 j( m3 l} 1 [5 Z$ \; x) u3 ?/ v3 c
; P' _7 q- B- B; h K, q9 Mif (interface->bNumEndpoints != 1) return NULL; 0 J0 w7 r3 H5 H0 Y
/ v8 S! M6 p& s. `) j+ @: Z2 q
endpoint = interface->endpoint + 0; + E& W1 ^# z9 I1 u' Z- [2 \- p
, N1 l L7 i9 q3 \8 m# E
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
7 I* m5 E; e4 u* N; |& U maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 6 D& b4 T& o/ ~, g# p% i
! W: Q" \- X7 ^4 @: i
usb_set_protocol(dev, interface->bInterfaceNumber, 0); ( z, q' D p+ J, B7 Q7 y1 ?# t
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
7 |6 i/ ?7 N/ C3 ]
- y7 T( d; D+ k4 B6 M9 Oprintk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
% _& ]+ D5 M4 Z" hdev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); " j( |* K# z6 Z9 c
, d: O# u; ?: U* v3 F; V if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; " K( x# U0 b, W8 `
memset(kbd, 0, sizeof(struct usb_kbd)); ( m; a8 C+ ~) b, F) T
& V E) a4 c" Y7 D( H( d' ~! s- A. V
kbd->usbdev = dev; + c, F8 f K% \: I& @$ B8 c
- S6 I( ?5 j, x7 i5 { FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 6 W) m5 i) t% k6 n# C
usb_kbd_irq, kbd, endpoint->bInterval);
1 t) ^2 K+ h' S; ^& D9 ]# Y D. x6 l
4 k" d' J$ x, q, p+ q; I/ D1 C+ S3 ckbd->irq.dev = kbd->usbdev; 9 ^% k$ V7 z, u# ]+ W$ C1 R) Z
3 \. K! g$ G+ `if (dev->descriptor.iManufacturer) * L+ f- B7 h; A3 L/ ~# _+ W( A
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63);
( u1 o2 u/ Y, C
1 G$ W4 t- J D! X5 \3 cif (usb_submit_urb(&kbd->irq)) { 1 P D& k5 {$ [; U& W
kfree(kbd); 1 i4 t" y5 s0 Z2 I0 f( b! I
return NULL; 5 f" M' I4 h9 d* J2 q5 P
}
% N% ]' h: K5 D. I, M; Q' ]0 T. N- Y! F; e; x
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", " M9 o' T$ z( a$ C% B. \
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
8 _6 T( ?# d( A# B3 r" T# j8 U1 b$ g1 A5 j8 B5 g& i3 f, e! j- K
return kbd; 2 ^8 t. E3 k1 z& k+ G
} $ o& @; U; T' {
. h2 X+ @$ ^; a% ~
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr) * F) ^ V- _9 k1 o" w) L
{ z' `. V& t3 m
struct usb_kbd *kbd = ptr; & n3 _1 I% q0 P: M. d" e6 _0 ]; c. d
usb_unlink_urb(&kbd->irq); $ ]0 o+ J: [: D+ a$ |
kfree(kbd); 8 n! J4 S5 [- W! S& S/ @
/ l9 v0 f B/ @* G}
4 r3 N% A9 ~# ^8 e" ]& W/ m2 K, W, O0 a- U% A) n0 B
static struct usb_device_id usb_kbd_id_table [] = {
4 S, Q- \6 y& s7 [- O1 f! j{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) }, 8 H% c$ ~6 \4 U& A4 \$ j
{ } /* Terminating entry */ 8 m& m, d% B7 {7 p$ z
}; # i+ N F2 d2 c( p6 P) }
# J3 n& ~/ c# @& T a! tMODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
( E7 Q$ q2 \$ f9 X8 E7 d! A# s# @- J! `6 t* f5 d
static struct usb_driver usb_kbd_driver = { # @0 g1 e: b% i4 I- t5 t
name: "Hotkey", ( Q x: X( S7 Y& b
probe: usb_kbd_probe, 0 p' r* P' U4 Q! v1 d* S
disconnect: usb_kbd_disconnect, . P# ^+ _" T8 s) T
id_table: usb_kbd_id_table, , l, \3 I8 e8 |' V9 \- Z
NULL,
- B' x: m9 b0 x9 Z5 @4 s: d" @}; 2 ~6 H% A, w0 Q5 `1 [* ]
- A) {3 x X7 k( u, xstatic int __init usb_kbd_init(void) ( h7 C; o0 d0 B
{
7 U- D' {# Z2 ^/ ~usb_register(&usb_kbd_driver);
: ?! V3 ^9 @9 v$ r$ K! R/ M" xinfo(DRIVER_VERSION ":" DRIVER_DESC);
" c; ^/ I u( I: `' c3 Y- K2 ~6 vreturn 0; + u( t( G: K% M, R5 u* e3 Z
} 3 B, H' _2 ?: T
& b( `+ f# v* i4 q( y* fstatic void __exit usb_kbd_exit(void) 5 w) l+ o4 s$ d% |( f
{
& G6 ?. V4 \0 s: d* Busb_deregister(&usb_kbd_driver);
2 @) h" w' X2 c4 @$ V6 N}
8 W7 Z/ k( W. r4 Y2 n) X; Z& ]+ b
module_init(usb_kbd_init); " c+ q/ E' Z8 S/ ~6 D
module_exit(usb_kbd_exit); |
|