- 在线时间
- 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,
- Z$ ?) F. M5 K6 x- R" USB ", " Mass Storage ", 1 u( b3 p& P8 }7 s4 n
US_SC_SCSI, US_PR_BULK, NULL, : }! r9 }/ G0 A, L9 K& o! M
US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE )
9 v4 U5 q+ a& I8 o: n7 F
7 C1 h: N1 h; }% Y( L, Y注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
! Q3 n" c W( e最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 # w n5 m# e! M4 X' }% r
键盘飞梭支持 4 s4 s9 Y* B4 c7 w
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。
0 e; {) d! N& w4 C2 Y下面是具体看到的信息
2 x3 d+ G$ d/ c) M! I5 P$ r9 T
: Z. m. X% X' ~' ^ g2 I0 I: DT: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
0 e9 R& Y5 C- X, a3 ?8 OB: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0 # `% {: ^7 G+ f6 R: L; p
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
8 T6 _( J( v9 p) U# jP: Vendor=0000 ProdID=0000 Rev= 0.00
+ {* M D. X* `' WS: Product=USB UHCI Root Hub ' {, {; W* D6 |+ C7 ^: o
S: SerialNumber=d800
# K4 Z+ b) f( ?3 o9 G# h4 ]6 m5 mC:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
- v2 b7 Q/ ]: \2 hI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
- Q/ ?) Y( Z/ p& YE: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
; e. D4 t$ f+ ^8 d6 xT: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 / o/ S: O1 i* W1 S8 F6 z
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 ; X$ h$ C: [- e5 x. ^. B
P: Vendor=07e4 ProdID=9473 Rev= 0.02
9 o$ @4 I O1 mS: Manufacturer=ALCOR 3 Z! ]' M: r# ~* r: [
S: Product=Movado USB Keyboard
5 X0 q; D% y" ^& T. B1 b0 rC:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA ; y% p, {' m9 }$ S
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
, U- r8 ~+ l$ r7 y& }& zE: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
/ h; W4 @6 E. a5 V3 C找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中
2 N! m, H' m! Y! h4 m* T# {2 _2 F- z8 g$ r6 p
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, ) Z1 \8 [4 Y$ \% ]6 T; t7 m
usb_kbd_irq, kbd, endpoint->bInterval); ; g4 i/ Q9 q3 ]% [5 ~
/ x( J* y" I7 z& }$ h: H一句中实现。
' y: }3 x6 D2 P% S0 g从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。 : i& M! F9 Y( k8 q
在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。
7 i9 H5 |( ~# @- ] F- E2 Q& i b+ Q程序见附录1:键盘飞梭驱动。 ! S/ U$ }" Z& v6 \; U
使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。 2 ]% A: N9 j& W6 d+ O
参考资料 6 b9 t* |) S( w" c: B7 i
1. 《LINUX设备驱动程序》
9 ^% v0 E) h! Z1 o( q3 TALESSANDRO RUBINI著 * Z9 I- p' s+ h( r
LISOLEG 译 8 C3 L2 ]! N5 ]& H7 h) |4 Y
2. 《Linux系统分析与高级编程技术》
* [5 p& U. D5 @3 d5 [周巍松 编著 - \% S3 h+ l. [8 \
3. Linux Kernel-2.4.20源码和文档说明 ' Q2 r- P% v$ v3 R) Y9 d( J
附录1:键盘飞梭驱动 " \" _+ M J. X' y9 B5 M3 ?
2 b, e \. q: x( L#include <linux/kernel.h>
( }2 n6 M |4 f- B9 Q: N- R#include <linux/slab.h>
3 ?0 k* H% o2 S3 r0 F4 y#include <linux/module.h> ; |& Z( Q7 [) G i% X" I
#include <linux/input.h>
7 d# O, f; \3 X! C. M#include <linux/init.h>
9 H4 e7 b8 S4 g9 u#include <linux/usb.h>
1 B8 p) Q+ S9 U+ N#include <linux/kbd_ll.h> : W" V ]+ B$ _& u$ A+ m9 r
4 e! j6 |( `: F; w. {4 _5 |/*
& D5 _, Q: R2 F- o8 ]) E3 v * Version Information ( N V/ p& M, \7 u4 R0 ?
*/
% Z* O, ^: z& e5 ^0 X; A#define DRIVER_VERSION "" ! b! N; G3 Z, M% _
#define DRIVER_AUTHOR "TGE HOTKEY " 9 }: E9 g2 f' L2 g; F
#define DRIVER_DESC "USB HID Tge hotkey driver"
( `) W/ G5 {) q, V" g8 O& N7 [" G' \4 L
#define USB_HOTKEY_VENDOR_ID 0x07e4 & `: B0 [) H! l# m# f
#define USB_HOTKEY_PRODUCT_ID 0x9473
3 K5 L" y' t/ \* P//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
, p( s& h ?. S( U9 O F3 {0 b' e7 }5 V/ v1 H& d# {
MODULE_AUTHOR( DRIVER_AUTHOR ); 8 S0 H! K8 g2 j: I+ G
MODULE_DESCRIPTION( DRIVER_DESC );
; N4 L! s. f2 `" {% `( R+ L- w/ |6 F8 x
struct usb_kbd { : l* K- o) R: `) H7 `* V
struct input_dev dev;
- m9 h/ y" o8 L) }struct usb_device *usbdev;
6 |/ y' V, p% N! Y. r% E/ Iunsigned char new[8]; $ T0 y9 Q; `8 v1 t7 K6 a
unsigned char old[8];
3 _# `, n/ g4 z; [struct urb irq, led; # L a. R( q; k9 |
// devrequest dr; 6 s6 L$ G4 J/ \+ S& u# a6 K! Q8 w
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
& A X7 g+ X- C' p struct usb_ctrlrequest dr;
- y, I; I7 {& _% _/ Cunsigned char leds, newleds;
6 h2 q( |' F# S4 Uchar name[128];
- ^" L8 ^0 D" G$ I! [& Q: G6 Lint open;
; q5 G/ Y: \1 P" m2 ?1 O};
7 t$ q) A4 f0 g |5 a//此结构来自内核中drivers/usb/usbkbd..c
3 E: e- t$ n) B8 [2 G' s# g; G% g% i, _# U6 p/ f
static void usb_kbd_irq(struct urb *urb)
D$ O F( K4 Q& n+ @ Z{
5 `3 Z& r- r7 H' V+ `, j$ \struct usb_kbd *kbd = urb->context; & Z% r# T0 f4 Q, @. w( O5 y
int *new;
( h' K1 l u( Z6 Z2 } new = (int *) kbd->new;
# e7 ?+ ~" E# I, v `# w' q
* i# @6 W6 B0 @( \! V9 t* @if(kbd->new[0] == (char)0x01) ) F; N8 U( J2 ^) p) i" T# N
{
5 s* a. |! O, r" a8 k$ Nif(((kbd->new[1]>>4)&0x0f)!=0x7) ( o G/ k) H1 F! a( m ]- i/ }
{ & k! s, V7 O0 Y9 \3 t/ e
handle_scancode(0xe0,1); 9 V8 v1 ]9 _) I0 p9 E: B" S8 F
handle_scancode(0x4b,1);
/ l2 P8 W2 {2 m i handle_scancode(0xe0,0); 7 q4 o0 J1 M: |* Z: ~1 Y
handle_scancode(0x4b,0); 8 ^# f1 U+ _& m% H* z; \
}
* f) f: W& @- Gelse
) Q# ~7 M7 q( G5 ^$ ~1 C5 A{
1 W5 u% Z! n" r) }9 w8 Qhandle_scancode(0xe0,1);
3 H. r+ k& ^! d. @+ s handle_scancode(0x4d,1); 0 s f: [ q0 {7 J9 p& k/ [2 Q
handle_scancode(0xe0,0);
5 A/ k% v* T- A' e handle_scancode(0x4d,0);
, G* m! _8 s% ^; f} ( ~) K& _1 ^# V. O& {
} % s1 V4 A6 n. e
' N: D! W1 _* j( \, I' w1 ?7 \3 P0 z8 ] ?" h
printk("new=%x %x %x %x %x %x %x %x",
2 B' F1 e$ D: D, I7 Qkbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], 4 r8 F5 N. }+ d: s( Z# w; L" R
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]); 3 P, Z0 t9 d% i- x7 n
6 O; J6 h1 Y6 U' X! C}
# v% ]' |. Q# i. A ]
2 n8 o: ]! K# G9 w( h/ E3 Bstatic void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
& w0 _* L) w$ {; D const struct usb_device_id *id)
9 t. j; L# H# d{ ! x A1 t: t$ y. T5 N! m
struct usb_interface *iface;
H( v, V% _: X1 p# r; r) n+ O struct usb_interface_descriptor *interface; 6 g! Y0 f& W0 p: @/ ^
struct usb_endpoint_descriptor *endpoint;
) {' S W3 m+ q7 f" T struct usb_kbd *kbd; # ?" u: b5 U3 Z/ Z& `6 {) E& Y* ]* k
int pipe, maxp; 7 x+ {( ]# R& s! A; j* s0 O4 R
, j# z/ Q2 Z$ Q9 F# l
iface = &dev->actconfig->interface[ifnum]; q5 H4 C. G6 \, @
interface = &iface->altsetting[iface->act_altsetting];
* R9 M2 @+ q, M+ ^- @" P' O+ \8 Q/ P5 a' O4 H7 A7 D! l' P& |( N
if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || 8 N$ t" Y5 ]! \ Q/ }
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) ||
5 |& y4 E, W* @2 {(ifnum != 1)) 1 `0 c9 g: `; o4 L
{
% x% |' J. |+ Ereturn NULL; ) t$ V# E6 J ]) n: C' U
} ( D" G! x, W u, ~ A6 Y" c: p( D
if (dev->actconfig->bNumInterfaces != 2) $ X- k* g- o) r$ E0 c) L2 I* \* J
{
, j, r" x* h, H( C9 Breturn NULL;
6 E: h# W' A) e4 r$ R5 s0 }} . w1 e, g. L4 g$ B. h
$ A1 d7 D$ I. Y$ E6 Y1 r
if (interface->bNumEndpoints != 1) return NULL; n6 [9 a+ s! q/ \3 ?2 n- O& y
& c4 j5 A1 W* m: e; B
endpoint = interface->endpoint + 0;
6 N4 V3 `- i# A1 H0 G% |6 |4 ]' h( K: ~( ^5 u" w* i( p) _
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
9 y3 w$ w: v9 R6 _4 v maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); ; x2 X: @( Z1 _+ M& i! m) O2 f
2 c9 z- @! R$ o. B, m usb_set_protocol(dev, interface->bInterfaceNumber, 0);
V- ]* h6 J" j8 |6 I% u% E, u# R usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); : |: v. M/ Z% X8 p; w
: ? P7 z m) A( qprintk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
' @. F, q5 b& o' b% g6 p' r: udev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); $ Y& _* M7 H r
" ]+ i2 R# t9 t+ R if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; / V- C9 z. b& x) s! f6 M |3 q
memset(kbd, 0, sizeof(struct usb_kbd)); 3 T- N" \. j; _1 e8 N" l: a- r Q
6 Z, k* v8 V, y: @) u6 P$ i
kbd->usbdev = dev; 7 l, o% A4 j1 v8 f' s
" O8 z! r: J& q
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
( R6 D0 D& L6 y' ^1 Xusb_kbd_irq, kbd, endpoint->bInterval); 6 H/ `$ V. A9 F% k7 t) ^
2 e8 {. K! {4 k; Y. o& B
kbd->irq.dev = kbd->usbdev;
" r! E/ X% X: ?+ c2 q) \3 N" S N2 a& o; X9 r( E5 J
if (dev->descriptor.iManufacturer) 5 j& n3 y; N: t2 Y5 B' k2 a
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63);
) x( i& b# |, F: H6 E6 c" d8 M7 Q
`3 V# ^6 j/ T4 tif (usb_submit_urb(&kbd->irq)) {
2 s1 V% m8 o% ^$ q. I kfree(kbd);
+ i# w. ~, v% V* d; S% [ return NULL;
' r& N. h- O' {9 }9 i$ l8 f8 R }
: s0 P- H. s, g2 R% ?* k# d1 r, f6 {" b% w5 c2 {
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n",
) Y0 v. z3 `$ L kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
7 w w* Q: y: e1 L$ \1 y: ^# n% j* H0 J: @9 U- J
return kbd;
7 W: Y% v7 n1 d0 v: W} ' z( U* S8 Z8 q1 {: A2 x5 e
+ c& K" r* h9 a2 w* ~3 V+ h
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
& @. t$ ^; c' [# M# V! ~) q8 `{ % i2 }$ y3 W" T1 y4 j
struct usb_kbd *kbd = ptr; # s% F# F N& P+ C5 r+ K
usb_unlink_urb(&kbd->irq);
, m' s8 s# I4 ]0 P+ J$ D" C kfree(kbd);
( |/ C, |+ {3 P+ x
) _0 B0 I! v* {" u7 o: I& G! P} 7 M( l% v! o7 x* s
4 s( p* R' G7 y4 Ostatic struct usb_device_id usb_kbd_id_table [] = {
% F# @5 r" g2 M$ t3 f) j A{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) },
" i. ~* i( {% n) V* |/ @) `{ } /* Terminating entry */ 8 {% o6 C" B: k( H1 f- v. ]: O
};
: L7 }7 b5 U) l3 d$ l
' e7 K4 f) F: O- {1 jMODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
8 D7 A% ]7 P& ~
: [! Z8 C A) g c7 {) |6 I- X8 nstatic struct usb_driver usb_kbd_driver = { 4 m- T; e- {# a* {1 H2 ?$ R
name: "Hotkey", 8 R# a+ P6 o9 _1 Q8 L, F" n
probe: usb_kbd_probe, 4 B8 M- U$ m, o. r- j& L
disconnect: usb_kbd_disconnect,
1 y! H2 s0 k) r* C- l; E- ]id_table: usb_kbd_id_table, 3 f- Q# a" T% x8 w5 r
NULL, * n* G% j' ~, y6 n0 \) k' G
};
0 ~( U/ n+ g8 m% m+ h$ ^* Q/ N$ [3 f2 Z
static int __init usb_kbd_init(void) # y1 S a9 V4 f9 R) M+ J* P
{
: v! p' m; [4 _5 V+ N: rusb_register(&usb_kbd_driver); $ e! x6 f* t" a( Z
info(DRIVER_VERSION ":" DRIVER_DESC);
" _7 F$ e/ M+ a$ u3 o- E/ Jreturn 0; 3 @- E4 A9 s7 b! P0 O, f+ M0 }: X
} + F1 a6 u/ @% B$ S/ c6 \5 D. B; S
) C7 Z A4 I# o q' pstatic void __exit usb_kbd_exit(void) & B1 Y# d* o% b" H" w `
{ * k: U8 n* Q0 W, e+ t
usb_deregister(&usb_kbd_driver); : D4 F4 J- i8 m0 o- z3 K4 \) y! }0 r
} x, V, v @/ D$ D
! v+ S8 x8 F1 @; _0 R6 r
module_init(usb_kbd_init); , n3 [- _* c# h5 g m4 p
module_exit(usb_kbd_exit); |
|