- 在线时间
- 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, 9 _2 y/ c6 u7 w1 M0 J" u% I, u
" USB ", " Mass Storage ", 5 N9 J: j8 W0 l; f' [. k) _
US_SC_SCSI, US_PR_BULK, NULL, & z& w# `3 q/ i* c- m2 I. X3 b: I
US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE ) }& J5 J3 K8 }3 N
; s K6 t6 g8 e# i' Y1 C6 R+ ^3 k4 i+ L注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
; b; w' {7 ~! ~( r( t+ k2 p4 x4 m最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 - j! R0 d. e. X" s4 a
键盘飞梭支持
" y! i7 G1 p+ j* \目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 / F+ X9 j# d9 l) o3 K7 A
下面是具体看到的信息 ' G C( p9 B7 m) d
- T* f6 F( }" n1 _$ C7 j# ]
T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
: d; T6 w. [; J- @2 G6 hB: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0 8 j9 d4 Z+ [2 a; P
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 + A W) i! S. G1 m2 w7 J# B( x
P: Vendor=0000 ProdID=0000 Rev= 0.00
. |7 `' F+ A; s5 f% c5 S( oS: Product=USB UHCI Root Hub
& |, ]7 j' Q5 \& G( \. QS: SerialNumber=d800 / G2 ]! c, @# @) G# w; p
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA 6 n3 T8 H1 o9 L
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
3 {8 Q: x- O; NE: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
5 X" t u, ?! T8 E. N/ KT: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 * [/ S* u- e% O- R
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 - o, K9 ~, |! T3 a: O; M
P: Vendor=07e4 ProdID=9473 Rev= 0.02 ( J) ]" ^* }7 H* A
S: Manufacturer=ALCOR ; Y' z0 K" d: B; c. P; q( m
S: Product=Movado USB Keyboard
! ^4 x& u j4 M+ u( G5 t6 \. xC:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA 2 P2 f" `( C/ [" I7 s' z+ y
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub ( m O% P2 X& K8 p
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
4 ]/ B+ ~7 f2 R! O( J找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中
; [4 ? L! x0 C2 B, X% X' S7 F/ @; _6 r' |+ I3 q. E3 k
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
: ?$ [- I# n7 y& C4 uusb_kbd_irq, kbd, endpoint->bInterval);
4 F4 H. g7 Z# w" x
% T q( v, f8 W一句中实现。 : C& Q/ a1 g6 X7 K0 I
从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。
C i5 g ^$ {在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。
* [$ B3 D e6 h2 k$ U# y程序见附录1:键盘飞梭驱动。 s6 r+ L) r4 y6 Z
使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。 5 X5 d2 |1 a; V* e/ y/ ?* X; c" g
参考资料
4 ~% \. e* Y( y0 r1. 《LINUX设备驱动程序》 $ B% w# G7 v; S# l' l; P
ALESSANDRO RUBINI著 ( y) k' c5 Q" K! x+ n
LISOLEG 译
3 z" s9 A7 K/ K- N! e! D2. 《Linux系统分析与高级编程技术》
: Z8 @3 y. R4 W. P. w0 o' h4 B; ~周巍松 编著 0 E7 ^$ v4 q* Q
3. Linux Kernel-2.4.20源码和文档说明
: K+ O# {6 l9 W. z1 L6 d0 G/ w附录1:键盘飞梭驱动 ! l7 s, I8 `- ?3 `
6 A* [0 I! B( H7 {8 p F#include <linux/kernel.h>
1 {. z: \( v0 Z' ?" C#include <linux/slab.h> j- O2 h; f, w" s) G; {- Z
#include <linux/module.h> 6 u( r ]: |9 J5 O& v7 z
#include <linux/input.h>
F# j3 j5 G8 G' @; N#include <linux/init.h>
: Y+ |1 T* d+ i+ I! v#include <linux/usb.h>
0 G5 m F+ p+ l! t$ ]$ w#include <linux/kbd_ll.h>
' G. o' _ S2 \0 f; h# j# N$ A6 {8 B
/*
7 B Z e5 |9 u0 Q* T6 f * Version Information
" f% a4 U$ h; h4 w0 |% d */
) V! L0 N: P7 I9 @: o' O! p#define DRIVER_VERSION ""
6 u, G- ?! m/ x! K' n8 t#define DRIVER_AUTHOR "TGE HOTKEY "
1 t& {8 ~# V5 {5 N- M$ x; O5 {6 f#define DRIVER_DESC "USB HID Tge hotkey driver" 3 {- x6 |, L1 M0 ] L" C/ R
8 s! K6 z. a2 n#define USB_HOTKEY_VENDOR_ID 0x07e4 1 K7 e# O& o5 N) k1 W; r# m. h( X
#define USB_HOTKEY_PRODUCT_ID 0x9473
$ l8 k! x, Z1 u1 Q; Z3 g0 A6 X//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
2 A+ s, E0 h4 T7 j) i" {) w% L W- R. M3 s; @( R2 @6 W, v
MODULE_AUTHOR( DRIVER_AUTHOR );
6 e: x% ^! {" J1 Z8 mMODULE_DESCRIPTION( DRIVER_DESC ); 1 @' H2 @( z" T8 C* \0 E
& K- h; R9 e' J
struct usb_kbd { 4 W D6 H% S% y; Q
struct input_dev dev; ( K9 Z% F5 d4 B4 o
struct usb_device *usbdev; ' Q. d9 z6 P$ q; K$ `- f
unsigned char new[8];
" O) B- Y8 u6 O' f1 p0 hunsigned char old[8]; 4 l0 S- I ?( B
struct urb irq, led;
! }9 k9 ?: r2 q D* O// devrequest dr;
' P% S) F7 d/ @//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化 : o2 `( Q, ^+ J& ]" q( U1 \
struct usb_ctrlrequest dr; 6 \! W8 Z! x% k4 k
unsigned char leds, newleds;
& N" g% e5 x5 ^char name[128];
2 r$ v/ k# g4 C# r* Uint open;
3 P _6 Z* d+ A) {};
# A* d4 U1 N6 l' p% p//此结构来自内核中drivers/usb/usbkbd..c
( X5 t$ O7 @- ~" e/ t, n6 \! Y( l9 R7 H! ?( Q v' C
static void usb_kbd_irq(struct urb *urb) % Y# A4 o6 T" Z! l
{ ; r4 Q0 b$ j$ C5 E
struct usb_kbd *kbd = urb->context;
0 V! R# |- V+ o- g2 r j0 a int *new;
+ n8 T8 u+ P- Z, k/ T new = (int *) kbd->new;
; t! d1 |$ m" D+ _( G* }7 G
, U- Q1 X! _2 ^6 j$ hif(kbd->new[0] == (char)0x01) 0 f) `; z' }0 p
{ % K0 i$ d4 S8 A6 z2 X8 b# z" w0 v
if(((kbd->new[1]>>4)&0x0f)!=0x7) 0 e$ H, e5 K6 e( C E x( @# f
{ ) B: s/ z4 D/ h) D- m: s* f- |' k
handle_scancode(0xe0,1); ) k9 n- A9 I% ?* l% K: x
handle_scancode(0x4b,1); 2 g( a/ G% c9 Z/ }
handle_scancode(0xe0,0); 0 N- j! U6 }5 n% t) s
handle_scancode(0x4b,0); ) y/ ?' r% _7 V5 F& b3 P
}
5 ? Y# _* m3 |5 H- x/ belse + f, P5 n) M1 O
{ / p; d5 ~% }$ p+ g- O
handle_scancode(0xe0,1);
' J' ~4 z; F c& t% A, J handle_scancode(0x4d,1); 1 u' j7 k$ |9 N& J0 J( J. w" p
handle_scancode(0xe0,0);
' S: X8 d5 Z* m# T1 O6 z: `& I handle_scancode(0x4d,0);
2 Z/ V, w& h j( E5 H% ]3 g}
: n5 F3 p! B$ z$ h) [- }}
6 T) x* p" l3 v5 N2 ^- c8 p( x
. h+ o( P- P5 Y9 N' [/ W3 X) ]# {- I% c- u# r2 \
printk("new=%x %x %x %x %x %x %x %x",
- Q/ z: X0 s2 ^kbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], * Y/ r+ K7 W5 V% `' o3 W( V
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]); j7 |& |/ V t( @, ^! [1 A9 F
1 {- j# Y7 j( M6 L$ ]
} ) h5 h3 _ {- v0 A/ N
5 M6 |( V; h$ l7 i2 v/ Q
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, & }6 H0 a" e2 u3 d! L# b N3 h) b( ^
const struct usb_device_id *id)
* X- Q1 Y% v4 R! G: a; }{ * w2 c0 B4 y, `
struct usb_interface *iface;
3 g" w$ l2 ?9 z& R [ struct usb_interface_descriptor *interface;
4 G, x% R& b- k. Ustruct usb_endpoint_descriptor *endpoint;
- W' v5 m+ _& p; s6 v9 r c9 m struct usb_kbd *kbd;
: L* B& ^3 `: L3 U1 m; K# I4 x/ l" c int pipe, maxp;
7 C& _1 |% j t N3 F N/ M- o, u/ a2 l
iface = &dev->actconfig->interface[ifnum];
' x1 \% I8 L# j6 Z8 w( ? interface = &iface->altsetting[iface->act_altsetting]; & O! G& s( d& i) i) s
" ]. X1 w4 X3 I9 s( b) `
if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) ||
8 a C) b/ r4 z5 q9 N) c(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) ||
, Z; h! I* W0 S$ f" O1 y9 ?9 |9 B(ifnum != 1))
) r( [3 t7 H$ p; S; q- ^{ 3 z! C$ C2 E7 |
return NULL; 4 ~4 J% w8 S U9 h# o: D
}
7 v1 C2 L. F! j$ _5 U: q5 A. dif (dev->actconfig->bNumInterfaces != 2) 9 i+ h* o& ~/ @0 t
{
) ?5 {" ^6 g9 V9 w8 h2 o: Wreturn NULL; 0 i+ ~# Z* `7 @% r D
}
0 |& A- z$ D o% S0 Z+ A* ? M& @ P, ] R6 \" l8 G
if (interface->bNumEndpoints != 1) return NULL;
& T$ o I) D* R i A/ d! M- a1 U7 I& }8 X4 W b) a
endpoint = interface->endpoint + 0;
2 L4 L. C' M! F7 s. w* n, F+ W, _& ^
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); 5 G; ?/ ?+ X1 V( h: W& e& O- N; c
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
8 K( p/ _& ?& c7 m8 a! l( J/ v0 ^9 c) }* n: N- r
usb_set_protocol(dev, interface->bInterfaceNumber, 0); ' }8 Y, Z0 N. A! B
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); , C/ A7 F8 C. K$ G8 [1 V" P
1 p( U. Y" ~; u% k+ W$ ? v6 U
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
9 ^6 i2 i% w- d* A# e% _/ m7 k6 Idev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp);
+ Q7 F. h Q' q( I- _0 |3 W/ X; c z/ O9 ~, d/ r
if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; 8 r# k% y3 }1 U+ W9 N+ R e2 E
memset(kbd, 0, sizeof(struct usb_kbd));
* p' G% B; G# E! N* d) P; H" n1 y& j9 H) t' j3 \2 S1 V" {1 ?
kbd->usbdev = dev; 5 ~, y6 Q6 ~) N/ H
/ Q/ H* T0 T* v7 f
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 6 w9 y; i4 u) ~) `' ^- B! D
usb_kbd_irq, kbd, endpoint->bInterval);
; H4 a7 `' |, `7 {
- E; g. s* l# vkbd->irq.dev = kbd->usbdev; * M p- ~& @/ d3 {. a
! s+ [3 X! F; p1 I: K
if (dev->descriptor.iManufacturer)
0 w3 R) |* J7 ]9 ]7 p3 m usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63);
" H$ v) O$ _$ ^+ s* y" i1 D ?" U( j: J" v$ x5 B+ {% e+ o6 d+ c
if (usb_submit_urb(&kbd->irq)) {
# t& N( ?# x& H3 W0 D% Z kfree(kbd); 8 v% m3 N" V. v- N* `2 ? {
return NULL;
/ O2 x7 P7 ]0 k! [" m; c5 p }
. K3 D- t" b% b) \- B, e R
4 K/ G" R k8 zprintk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n",
4 o; D r# v9 H5 _+ K1 {; i# M kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); / {, `& u) e8 k# j5 |
- n5 q0 C' l7 W$ G5 N
return kbd;
' o* C E! K7 E2 w} ( z6 T& X3 u' r7 `3 f
' q& d& F0 i- |
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
) Q1 z' A' K4 e! ~4 X{ 3 C5 \; e' e& f+ O2 r& z6 [4 T
struct usb_kbd *kbd = ptr; ) t2 e8 a8 E- R- A% B% }6 R
usb_unlink_urb(&kbd->irq); 4 C) H* v* ^# M& m# d8 H
kfree(kbd); 8 o6 L/ p9 A4 V
$ H" X% r& T/ ~- a- T6 j* y}
. l( x$ k- q9 @; Z I* M
$ u, `4 l* \+ v6 ]static struct usb_device_id usb_kbd_id_table [] = { 3 U* l. ^- d! O( a6 E; B
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) }, " g" \ u! h7 I9 i
{ } /* Terminating entry */
* k: y' A" j6 T# v+ V. r; R* R}; ( H) F/ `; n0 U, s+ Q/ _
2 [0 n; T0 y# ~) qMODULE_DEVICE_TABLE (usb, usb_kbd_id_table); 0 E2 Q8 p' K5 e- v7 I \
" N6 H7 q k# x
static struct usb_driver usb_kbd_driver = { S% j- |' N# ?" p) L
name: "Hotkey", ( @1 o1 Y/ g* b
probe: usb_kbd_probe,
$ u9 b8 B4 @& p. a0 Kdisconnect: usb_kbd_disconnect,
/ J' u- Q' r% J0 R0 u" F, d% Tid_table: usb_kbd_id_table, " V; ^. E/ @' Z8 y3 u7 ~
NULL,
' }- S. z. y; ]% q};
" m* ]/ R/ ^; G+ @! j% p; \4 A7 m8 ~0 t& |6 d
static int __init usb_kbd_init(void)
; x$ A8 y2 c( ~{ % D# Q" o$ l: [. \9 a
usb_register(&usb_kbd_driver); ) b: w% k. b2 Y3 M; @2 n+ u Q
info(DRIVER_VERSION ":" DRIVER_DESC);
" q6 L& N1 H2 j+ C2 ~return 0; ! p1 c& @$ o, l# H; h, x( p5 G
} }4 y! B2 A' X! K
6 t& q1 P- d" Q8 m- y5 p* @9 estatic void __exit usb_kbd_exit(void)
6 [/ \& h# i8 f9 `{ + @2 o4 E+ R2 Q! ?" K/ D+ ?; e
usb_deregister(&usb_kbd_driver); x( q6 O) p0 {- U0 }
}
$ a& U" g: b \$ @9 G
/ J4 l! S, x5 Jmodule_init(usb_kbd_init);
5 v4 U: Y0 X! x& x2 D s& N' zmodule_exit(usb_kbd_exit); |
|