- 在线时间
- 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,
2 @8 a1 W4 O0 f/ j% y6 L# a5 e% m; i" USB ", " Mass Storage ",
: F9 C# T+ x3 Q* G' yUS_SC_SCSI, US_PR_BULK, NULL, 3 }% b8 _+ u W2 f" K3 _! E" s
US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE )
! T% W; l8 O3 D$ q" Q& c& y
5 A) H# ]: f4 p: u; G' A2 a& l* v注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
0 L2 l& t, Q; e9 q4 f最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 " R+ x+ e. _9 X# A; h
键盘飞梭支持
( p( q$ r2 d( w8 H) D' v( O# X目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。
# d4 `1 M4 w! ^+ e下面是具体看到的信息 5 y/ \7 w8 {/ W8 k
( ?1 W' E; O( |5 \T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 + V( A6 K$ m k4 ^* a
B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
) U8 ^$ Q6 I# F' l9 a- [2 aD: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
! p& J( F' j7 n2 w9 `* W+ {$ PP: Vendor=0000 ProdID=0000 Rev= 0.00
$ T2 q1 U( W' p4 ~! C% q, nS: Product=USB UHCI Root Hub $ c. C# d! t7 @* m
S: SerialNumber=d800 " l, W3 }" `" u. x7 W. z6 m6 h7 u
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
G7 w; P& l/ w: G5 LI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
2 r8 }1 A& X* q3 f. S( J# JE: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
- M3 F( W/ _$ [7 T( p1 OT: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3
$ b G9 j( g7 x4 [D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 U& f1 r/ u1 N; x; {3 {. w
P: Vendor=07e4 ProdID=9473 Rev= 0.02 1 \' C2 z1 s: ^ r* ~/ G b
S: Manufacturer=ALCOR
6 A" I* h- ?7 g6 z" t3 fS: Product=Movado USB Keyboard 8 F E7 B% s8 ~+ S
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
6 `' V- ~, P' s0 Z' ZI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
6 I; j* v& m! d/ B1 m- RE: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
0 d8 L3 y( z7 |) |; N找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中 8 j/ _/ [: c j& F- g" f" m" ~
$ B& r/ n) O) T% WFILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 8 h+ O( m: C5 V- ~
usb_kbd_irq, kbd, endpoint->bInterval); Z% S6 W* ^% \4 c: ~* U. Z: O0 [
G' z& S3 b! Q* }, y6 L& r
一句中实现。
% B6 n' a% _; g3 y/ t从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。 + a$ o4 H; m# C# C' l
在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 * b/ f, d# v! J: {" t0 J4 h* J) w
程序见附录1:键盘飞梭驱动。 # T3 T( m2 ^; q# T9 n5 f
使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。 0 z- M- O4 a. G* e- W4 z4 D, |2 L
参考资料
4 z9 J( |0 W" G. O" r' }& e4 v1 e+ Z1. 《LINUX设备驱动程序》 6 h( d! e! C: Y2 H3 { W
ALESSANDRO RUBINI著
4 a3 @8 w8 L# T) L; p# }/ ~- a4 FLISOLEG 译 ( c, m* W9 [* n) \& L; f
2. 《Linux系统分析与高级编程技术》
: F( v1 M+ B# Y7 J6 w周巍松 编著
1 k' j; G- r# c1 M! M- j) X3. Linux Kernel-2.4.20源码和文档说明
; O/ \& M7 M2 ^附录1:键盘飞梭驱动
; L ^0 V" ?# U4 N' O: v5 i
- \) g4 G, @8 b3 l% g3 Q( E' ?0 D#include <linux/kernel.h> 1 S0 y/ s4 ~8 w2 t$ G
#include <linux/slab.h> 3 e# b$ ~5 o. t1 R
#include <linux/module.h> . O5 G! x4 k* H+ B
#include <linux/input.h>
( G; o; }3 x% K2 T% G#include <linux/init.h> 9 I7 J2 v5 T: V5 `4 k0 _
#include <linux/usb.h>
2 H! w# I, ]+ u3 I. [#include <linux/kbd_ll.h>
5 a3 v; C' [3 [ i& S& D* W) f g# t4 N& `8 v
/* 6 J2 ~3 y; j3 {' N( L# P+ {
* Version Information
+ K% [3 k3 o! ]% u% N, p& r */ " m7 l7 v+ ~) R
#define DRIVER_VERSION ""
4 p. |- @: q _6 w" m* S#define DRIVER_AUTHOR "TGE HOTKEY " 5 R: q5 H& K; _ H0 t% \/ i
#define DRIVER_DESC "USB HID Tge hotkey driver" 7 p$ r- m4 U( f6 G
$ Y; O9 Y) I: h U
#define USB_HOTKEY_VENDOR_ID 0x07e4
' k2 Q! }6 P2 I( D( N6 R8 g#define USB_HOTKEY_PRODUCT_ID 0x9473 . `4 O- Z5 Z. A, I7 q' S( y
//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
% ^7 S/ U+ @2 B' b
; `9 G; j+ Z: U6 j% `2 T2 x YMODULE_AUTHOR( DRIVER_AUTHOR );
) b$ ^0 K$ l/ R* @MODULE_DESCRIPTION( DRIVER_DESC );
$ t& F. T. z2 R) l0 a+ j6 M8 S4 I, Y9 |1 ^% e; f) b5 y
struct usb_kbd {
: b+ n6 m+ V/ F# ~' ]struct input_dev dev;
b6 N* d2 h/ n I% K. x% Bstruct usb_device *usbdev;
/ g9 t& q9 n" @; \+ o# Zunsigned char new[8];
+ N7 Z. P- R; Iunsigned char old[8];
6 I! J* j2 x3 M! K. c6 p6 k7 y0 _struct urb irq, led;
& g* p6 b) }' o6 W8 z+ s// devrequest dr;
2 |5 S! ]0 `/ X% K. F//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化 7 q3 c. M. @0 l8 O, h0 E
struct usb_ctrlrequest dr;
5 A+ Q4 _ E# b7 ]" |! \4 cunsigned char leds, newleds; , z0 A; b$ Z C: ~, L8 K) L
char name[128]; / ~6 ^. s# l, V6 h5 z' w' \
int open; " B9 e5 M' X$ y! b
};
3 L( K- y5 U) q E( o6 t//此结构来自内核中drivers/usb/usbkbd..c
6 t7 W+ S+ Q- ]$ }1 S# P& A. r0 x7 T) _$ @- y1 [# T( \: V* |
static void usb_kbd_irq(struct urb *urb)
3 I, Z4 b, d) I8 I3 w P! g{ 8 C7 G) N. K, W
struct usb_kbd *kbd = urb->context; 1 s1 Z1 F2 T6 }
int *new; % y5 O6 n2 f% Q) I& u
new = (int *) kbd->new; # `' u) p4 n" u1 J$ F8 b
4 z8 k9 @( q+ dif(kbd->new[0] == (char)0x01) $ N* |! L9 g: ]
{
# v9 z: j7 `8 ]5 @- Gif(((kbd->new[1]>>4)&0x0f)!=0x7)
' k8 B9 P* ~( O+ @. Y$ v{
4 Q3 b4 y; {; \) M* `handle_scancode(0xe0,1); " }/ e$ }* }& j: G
handle_scancode(0x4b,1);
1 G# N5 `6 P% d6 ^ handle_scancode(0xe0,0);
( f$ H" d; b4 B# s, e) n4 J handle_scancode(0x4b,0);
% k8 P! w$ V/ C- E/ ` d} ) y4 F6 Q: i( p
else 6 H! C1 Y; }& l8 }* F
{ % n J5 y* B) b
handle_scancode(0xe0,1);
2 ?3 m( |# W# a5 [/ p$ Q- R handle_scancode(0x4d,1); 0 j* g6 n; y1 S2 t
handle_scancode(0xe0,0);
( ~ m. W) I0 _5 ?4 O handle_scancode(0x4d,0); + v; S! _8 Z) O* u( w
} 3 O6 Y, o/ N5 e* g, e
}
) x3 n) i7 e- o3 s- @& W; i/ F
; E( D8 V* Z: ?) [; R0 I" @" ~/ Z) I: I& Z! w
printk("new=%x %x %x %x %x %x %x %x", ( w9 M7 `$ n2 z" Y
kbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], / f* _+ F$ x! `2 v( L; }
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]); : B" n8 V" k4 Q! t& d5 j
! u. Q2 N5 a: v, n1 O9 R8 B} : @- ] ^1 |, _. q9 V+ c P) I
! r# g- C# K9 \static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, l, o6 ]9 c6 f* e: A. ]2 r
const struct usb_device_id *id) ' l- T. y. ^9 r4 b
{
. b; c; e8 c$ x$ {% O9 ] Kstruct usb_interface *iface;
- @' e& h5 ?: H( m- `0 e( z( ~. |1 k struct usb_interface_descriptor *interface;
! f7 ]+ ~5 x; T8 N5 z% d; hstruct usb_endpoint_descriptor *endpoint;
2 f' ?- B$ C# ]- G# I' ^9 ?& T struct usb_kbd *kbd; 8 K( [$ F; M9 V" o1 h% \
int pipe, maxp; 7 k6 s3 h) i- X7 N. f' ]
2 b L, Z2 N: Q! J
iface = &dev->actconfig->interface[ifnum];
! ^0 g" e4 L1 R) A& p interface = &iface->altsetting[iface->act_altsetting]; 0 Q4 P0 @% J9 ^& k
, ]' ]9 X% t! y) R
if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) ||
0 h1 X6 _# l! S4 X1 p(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) ||
" e- V# a+ u, |" H3 K" O(ifnum != 1))
# |) ^# ^) N. F1 g{ ! {) z" H+ K0 K( S' ~
return NULL;
" `/ y! @& P, o4 a}
* z |# o/ F+ |if (dev->actconfig->bNumInterfaces != 2) 7 s5 W. G8 c# q; N' r" _' T
{ ; S6 J+ d( q1 u7 }
return NULL;
% b6 X( b3 ^2 @3 b. F4 x' r}
- \, J: d+ w3 H7 p) f/ ]- l& L. Q
/ b% l4 M$ H. o9 I) H t" R9 [3 L; y; Lif (interface->bNumEndpoints != 1) return NULL; 8 N; S- }' ?% z; n
5 f5 c3 L' m9 x
endpoint = interface->endpoint + 0;
; E3 g: T0 R, ^6 d* }
# L7 |$ g7 J3 I& H2 h3 K pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); & E* l4 I1 q9 S4 k
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); , o8 s+ `4 K6 I3 j1 ~
+ U9 v2 ] ]! ~, Y/ j" Z& y/ [4 Y usb_set_protocol(dev, interface->bInterfaceNumber, 0);
3 |3 R T- U2 V6 b1 B usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
) q" m# t, V, J9 i0 U
: E( [! |" F, G8 L9 p$ ^7 |* Mprintk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
: V+ G5 Q; Z: R# }# hdev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); # f0 A. ~* B1 z1 S' x
$ U$ j* H7 v* d* ^4 V if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; # m, C6 W# `/ S, I P) M
memset(kbd, 0, sizeof(struct usb_kbd));
8 j& i$ s, N6 v: Q) F
3 x3 H/ M# H) o; w8 b kbd->usbdev = dev;
% \: \; ~* ~. f2 y/ H9 q4 E' n* g' i; i
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
$ W2 i1 p; q9 [ ?7 E5 o" uusb_kbd_irq, kbd, endpoint->bInterval);
+ `+ K1 N# h7 B
) r1 ` d5 O0 ykbd->irq.dev = kbd->usbdev;
6 {2 x% q. C/ ^0 J' y6 K9 g3 ~, g) Q/ m- {
if (dev->descriptor.iManufacturer) . _( f1 i( x1 G4 ]& q
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63); # |2 `4 X: E. `' ?" o" J; e: @4 q
$ g) I n: ^3 b2 p5 u$ p! Yif (usb_submit_urb(&kbd->irq)) { : r+ C; Q- K6 E2 S
kfree(kbd);
0 w# u; f& ~: |1 g$ m return NULL;
/ [" g$ ?6 ?) P3 d% \0 v* _ } 6 @, u7 ^( R( B: k0 f+ @, p6 b- {
! Z& [+ l0 ]9 h1 x. ?5 J w0 d2 r
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n",
9 F+ y% f! l$ e3 \- T7 [ kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); 4 F- _* ^% w Y- L7 t: o
2 y Q { X+ |. g5 j/ N: F return kbd; # `7 O/ [5 [$ p( x& O
} 6 ~) D3 R; f) V3 }) |4 T
8 d7 v8 F) U& ]4 }" o Gstatic void usb_kbd_disconnect(struct usb_device *dev, void *ptr) ; G7 V; O, `$ Q2 s- }: x
{
+ w3 @- o: @4 C; N! Y5 _struct usb_kbd *kbd = ptr;
8 C6 Y6 a6 W& {2 T usb_unlink_urb(&kbd->irq);
0 S2 Q* q3 A2 Q0 V kfree(kbd);
+ S$ X# L# M! b' q$ V& z- o5 z0 G. f; H) O- ~
} ' D5 v8 K T/ e& Y. _
4 G8 V ~ S2 I+ C- k' y% Y Y1 cstatic struct usb_device_id usb_kbd_id_table [] = { g! e: k7 m& l7 R* Q0 s: _8 D" r
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) }, " r- f/ B- w& v6 v
{ } /* Terminating entry */ - S$ {$ g/ w2 ?/ L
};
% G( k$ y' _+ w! i8 t! D" T! Y
1 k. x. O9 a5 H7 Z1 @& CMODULE_DEVICE_TABLE (usb, usb_kbd_id_table); ' A; O# n4 s, N5 h0 ^. Q
! Q1 n* i' s' Z' u; Y( o
static struct usb_driver usb_kbd_driver = { . z) X( ?) v8 m; l* r$ V2 \2 a
name: "Hotkey",
}& K( S1 u8 k, w1 s/ D4 ~, Hprobe: usb_kbd_probe,
" d9 _/ N6 k2 E" ^disconnect: usb_kbd_disconnect,
: Q5 g! {' u5 F N h+ [) s+ t: wid_table: usb_kbd_id_table, % J: c3 c6 a" `
NULL,
6 Q k1 Y/ P/ N$ {};
* R1 H5 }1 T( @ r% U: B8 V7 |: J5 d M# s
static int __init usb_kbd_init(void)
+ y( X9 V s' i$ O2 {* Y{ , V3 ?5 Z0 P6 Y3 R: N! e& Z
usb_register(&usb_kbd_driver); 4 Y0 P! ^8 t3 A
info(DRIVER_VERSION ":" DRIVER_DESC);
5 L2 t& ~! n3 U- [# freturn 0; 1 j$ p: C5 A6 R) q; q( c
}
5 M1 J* b: S+ n7 n
0 A; m3 W, g4 E1 astatic void __exit usb_kbd_exit(void)
& t, ?) F% j( Z4 O6 Q' q8 H{
5 ^9 ~- P9 B' `- s( P6 A' Vusb_deregister(&usb_kbd_driver);
$ ?( q( |( ]# L2 c}
* C- o' y. g: ^$ q7 w, i8 F2 {$ Q4 I: `" [
module_init(usb_kbd_init); ( j( E" a: u! y+ }% f
module_exit(usb_kbd_exit); |
|