- 在线时间
- 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,
7 z5 D' P; ?2 R0 ?& G" USB ", " Mass Storage ",
& G2 W3 F0 X d' e5 t. R2 C7 {US_SC_SCSI, US_PR_BULK, NULL,
- s0 }' s5 F" z$ X, ^US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE ) + I" L+ W8 l1 ]( b) W1 j% s8 b
* I$ N B. l" o m$ y' M注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
" h) e- c! o3 G2 g) z3 i0 W& t最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 1 X1 M$ b( m X6 x: _1 O" X& f
键盘飞梭支持
( q7 f9 b9 Z% ]0 ]' T目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 . [7 v v2 {* B6 r6 H
下面是具体看到的信息 - v- s5 w( T( o J4 u$ o5 u& ~" R6 u
5 ~3 g' s m+ e: Q Q7 ?+ u) M- X
T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
2 e/ d9 ~! l% ^! _" K/ XB: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0 ! _! d" W3 V. U1 z5 w) z4 Q9 q8 a
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
1 D# r% i" v6 [- yP: Vendor=0000 ProdID=0000 Rev= 0.00 + y8 {/ _ C$ y# ^" }4 M6 G* m
S: Product=USB UHCI Root Hub
, H8 n1 o) s" d4 _" a: b9 cS: SerialNumber=d800
O5 J( e! Q8 DC:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA B: \1 N' p# X. R7 j w$ I
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub : p1 U3 q; `4 O6 k0 S2 G, w
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms 1 [/ L+ W+ t W8 K- R9 M( Q* K
T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3
5 d T& o8 l( P! k! f. }0 zD: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
# m! U$ S9 W$ i1 BP: Vendor=07e4 ProdID=9473 Rev= 0.02
* f0 B( E" q' hS: Manufacturer=ALCOR
1 R7 L" ~9 K# Y9 s1 `9 pS: Product=Movado USB Keyboard
7 e7 A# T. S5 E- e2 wC:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
8 ]# p3 N; w, {0 A$ f: ZI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub 7 k' Y5 y0 ^6 t* s E+ y
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
. k4 s1 A# g' y$ W, M找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中 9 P% p: Q* k8 {" C
$ ^$ J6 R7 t$ n$ S& a+ ]. ZFILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
2 ~9 @; p" F1 S2 `usb_kbd_irq, kbd, endpoint->bInterval);
" n% @6 Z& | Y: R6 b2 w+ H
& G; d/ @: u) z% L& r$ A% F一句中实现。
- z% M9 J+ n: e, t9 C从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。 2 |* z9 ^1 U* C9 ^7 Q8 ~6 n% b
在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。
, b/ ^- r3 O( ?" R& W+ C4 V程序见附录1:键盘飞梭驱动。
2 w! ?% [+ x/ [ f9 s4 J使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。 $ }' m9 N2 H9 Q; _
参考资料 7 {& D3 h! g& D
1. 《LINUX设备驱动程序》
( e8 m- m& t$ x; y$ |6 a7 FALESSANDRO RUBINI著 ' J$ N7 Q5 w/ p
LISOLEG 译 6 ^& j* [1 W/ A7 e7 T$ T2 H
2. 《Linux系统分析与高级编程技术》 k, p, I5 D6 ?. Y
周巍松 编著
1 o0 o3 [, y2 l, N3. Linux Kernel-2.4.20源码和文档说明 * z9 f9 d. v! v" d! m8 F7 Z* ^( k$ b
附录1:键盘飞梭驱动 2 J% \* x- Z4 o/ I& i0 U
' Z, v" J( j0 j6 F3 J#include <linux/kernel.h> j5 @3 |* f u" `9 b, H
#include <linux/slab.h> 5 b$ [1 V7 z! V2 M
#include <linux/module.h>
7 @/ e3 K2 r9 r6 [7 R* {#include <linux/input.h>
0 u( J p, W4 C. X#include <linux/init.h> 0 c. y( @' Y3 D) D o
#include <linux/usb.h>
, Y2 P! O# l. M5 D! F7 Z#include <linux/kbd_ll.h> % _: `$ d6 g0 `# i# |! f3 T6 o# [3 ~
1 q9 ]8 q/ L! O0 \* J- N( u
/* ( s/ f" M. u% K
* Version Information , w, I: s9 _* t0 d* d
*/
: o" @. j; h6 ^4 [* m7 M& i3 I# g#define DRIVER_VERSION ""
* L5 E/ f, f# r& B, n7 |#define DRIVER_AUTHOR "TGE HOTKEY " / [( T0 B1 J+ z0 y8 l
#define DRIVER_DESC "USB HID Tge hotkey driver" 0 Y3 F# |" e# x$ P& X% l) _
; `; f3 C3 I. @5 p#define USB_HOTKEY_VENDOR_ID 0x07e4 & c }* N) j% u& G2 C. U+ O5 \
#define USB_HOTKEY_PRODUCT_ID 0x9473 0 i7 c* S7 M) c
//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值 - u; j4 G3 b. A
( [" f; \% F+ \
MODULE_AUTHOR( DRIVER_AUTHOR );
- Y; l. V$ g8 L% @1 ]2 lMODULE_DESCRIPTION( DRIVER_DESC );
) o1 y1 ]: L- D! d, W8 l7 L3 [+ ~4 f; i$ y
struct usb_kbd {
) j6 N/ F. L- a( G9 {, Vstruct input_dev dev;
* @2 x- _/ I; v2 U, [/ ?; w" cstruct usb_device *usbdev;
- Y% n, [! t; X' T2 `0 R+ w. Ounsigned char new[8]; ! M/ e. j2 @ b: D) W8 p
unsigned char old[8];
0 a+ w' H6 P) w8 C4 @struct urb irq, led;
# ]$ V, l; y, O' B5 j// devrequest dr;
0 G' s+ N5 h- |- H: e//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化 0 t0 u" L: @0 n! o( X
struct usb_ctrlrequest dr; % ?% G9 n3 S4 b
unsigned char leds, newleds; ; j1 Y2 L! e( L1 {1 ]' g* N# |
char name[128];
8 X) r* a- y5 h* N3 o( T- nint open;
9 O- h j; y# P};
: m$ \0 l3 |* j# T7 Y$ F0 _//此结构来自内核中drivers/usb/usbkbd..c a% M9 Y4 x6 R2 n0 }9 V
5 p0 \0 X( v) `9 n5 R Y8 m% u
static void usb_kbd_irq(struct urb *urb) # X% f/ N' m. u. r+ D; n
{
6 v L% _- ^) L/ d6 r/ h% astruct usb_kbd *kbd = urb->context;
: R9 [/ P: m0 h' F int *new; 1 W; N6 D! I( ^6 D( n& j: ?
new = (int *) kbd->new;
% n; u; j! p2 S# j3 y
. O/ g2 B" h: [$ D% g) o' f6 @if(kbd->new[0] == (char)0x01)
! w+ C* Z& Q- J& p7 Q. }( j{
. O2 U. o. i$ y4 ~+ Q, tif(((kbd->new[1]>>4)&0x0f)!=0x7)
& F* ?2 h$ S- B& g# W1 H7 X4 y) T{ * b+ j7 \9 p+ [) \; J
handle_scancode(0xe0,1); 9 U" r' D9 r1 g
handle_scancode(0x4b,1); : w2 d0 l$ k' q A, {5 k1 [, s
handle_scancode(0xe0,0); ) V5 Y. C1 E, x! l& ?0 t6 G
handle_scancode(0x4b,0);
6 M4 w% v* l( H6 C) B4 Q} 7 j2 f( @" ^- v* H4 _3 ]6 T! r
else
# K- K* k* O/ B4 _$ L# x4 H{ + u( @ Z/ ?# p; q
handle_scancode(0xe0,1); - S/ k4 ]( M( G) n$ T, a+ G8 r
handle_scancode(0x4d,1); * ]" h$ k) H! R
handle_scancode(0xe0,0); 7 _% A& Z! i' Q, ~ O
handle_scancode(0x4d,0); Z, `' l$ s' z1 v' v0 e
} & u- P7 `: |; v6 n
} 5 O0 E ?: E1 r, T8 a7 _
5 s, h$ R+ ?0 b2 J1 ^ @% l: D* e- j' m7 v: e
printk("new=%x %x %x %x %x %x %x %x",
1 c! Q% t/ D7 A" {+ M0 n( Zkbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], # o3 D" q5 |7 ?! L( y; J6 X3 P, g
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
: r2 O2 U# m# {) H8 w5 y. n* \* [
} % X2 p! N) A* x4 p1 G5 S
, X! n. E( R) f) @$ Z1 L
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, * M* I) [' i+ ?1 _$ I0 w' W
const struct usb_device_id *id) : b/ J4 x! b9 e6 n
{
$ m @2 }" [( ~! q+ M) q$ `struct usb_interface *iface; 6 J d- O7 M( w8 R. ]
struct usb_interface_descriptor *interface;
! ^; k% M$ `4 [! ostruct usb_endpoint_descriptor *endpoint; * o; }& V; n( ~/ U. ]+ x; o
struct usb_kbd *kbd;
! Q4 h6 q- [; E5 e7 A) H$ N- u/ w int pipe, maxp; : c3 a. c/ ~8 a" N' h; \* k' c1 J
; G5 H' u* v1 g# T! ?3 P! P6 u
iface = &dev->actconfig->interface[ifnum]; ) N' K8 O& E, K J9 P
interface = &iface->altsetting[iface->act_altsetting];
k: J5 v e% B% T& O
( e& G( k2 V4 G' yif ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || 6 n9 ~5 D/ T1 V9 h* X
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || + ]( B- k$ t& h& y: c
(ifnum != 1))
; U" u$ T; ?1 `. C: X0 p{
! h- I* m8 F1 J a! V$ V# ^return NULL;
4 w' J& d4 u [4 }2 }" r# @} ! G: ?: O" ^ D- n
if (dev->actconfig->bNumInterfaces != 2)
+ Z8 _6 }4 z) b# {{ 3 U \3 V; X) V8 Z% y
return NULL;
) p5 c% C" A" D2 Z0 Y1 k}
3 [* C5 J$ ~3 D4 ?
4 \$ N9 O. |: n; V J* h6 Vif (interface->bNumEndpoints != 1) return NULL; - A0 O. n1 j9 B; k- E
& D" ~8 k- v) }3 M* C endpoint = interface->endpoint + 0;
) |9 f- ?2 K. S/ H5 o9 O, r4 K/ h" a* ~, [. c
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
7 e' d7 d; V P9 n! _6 h% X! X maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + @" B8 c- C8 C6 T$ T$ }
5 t/ \9 I# d7 \# l4 h$ n$ v usb_set_protocol(dev, interface->bInterfaceNumber, 0); % j, n" t. `6 X+ C
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
! {1 F2 e/ c, [2 x0 M% n
; d+ P5 m. \: h, cprintk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n", 0 g, Y. H9 j& G7 O) y* E
dev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp);
9 B# k' r) v9 h/ Q& W+ ~
, u, l. E+ e7 T5 U+ Q, R9 n' p if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
: y' \) e) ^: C3 _0 k3 d8 y memset(kbd, 0, sizeof(struct usb_kbd));
8 [- K# t; F M: Z0 N" u/ \0 _4 h3 v! ~
kbd->usbdev = dev; # C- h: {3 b6 q3 k: ~
5 M% B2 k4 _/ ^$ M9 a FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, & d; h/ K9 y& N6 u& U* l
usb_kbd_irq, kbd, endpoint->bInterval);
- U8 [# [0 O1 V. g2 G3 _( K9 s- N9 g3 @+ Y/ S
kbd->irq.dev = kbd->usbdev; 4 Q- o& m. X1 u# A! i
) K) W. c: L8 \3 f. sif (dev->descriptor.iManufacturer)
% h* f# I/ }6 ~" \- R6 X usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63); 0 n0 M I# q, \7 m' G7 p
0 o, l- r! t/ I5 }& vif (usb_submit_urb(&kbd->irq)) { % ]7 e- [2 m1 y' h
kfree(kbd);
0 p4 Q) p }. |# P: p- K. V return NULL;
- R& {/ B8 e! C+ g# S, T } 7 p2 t* r! L* V$ ~4 w6 D, M
' p9 W5 f% i- G3 s$ u6 ~9 C- C
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", ) y" P% u" ^9 a0 s5 G% B [; P
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); & J& v1 [2 K" J( F% o
8 i5 G+ u4 j$ E7 g; _ return kbd;
* u/ j% n8 k; o* v& h( N4 s {} 5 R) @8 v% t' K8 z( ?/ u9 e$ p
6 k% c3 g- N/ V. q Dstatic void usb_kbd_disconnect(struct usb_device *dev, void *ptr) ; K# ]2 E0 d h$ c; j( l
{ * O3 |1 v( X) J
struct usb_kbd *kbd = ptr; 2 [4 A. L% L: \+ U6 k7 U
usb_unlink_urb(&kbd->irq);
3 T6 Z! }% Q" x) M! j/ v kfree(kbd);
4 ~; I9 r0 z2 {/ R5 s2 M7 v0 g5 m
$ T& C5 `, T- v( P5 v! f}
2 o6 A) S) L' H7 R( e4 Z8 d* m% m5 n& s2 I+ a* J
static struct usb_device_id usb_kbd_id_table [] = {
1 M$ O& O8 S) |{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) }, / y+ [8 x; B! |8 `5 l7 J
{ } /* Terminating entry */
& `0 H5 u4 t1 Q6 t6 ^) m* Y' j) G0 s7 t};
, ^+ n, J1 A1 S4 @) h/ w
" u) z' Q" W4 M( GMODULE_DEVICE_TABLE (usb, usb_kbd_id_table); ! W1 y, n6 r% \
( c) y t9 J. E- ?static struct usb_driver usb_kbd_driver = {
4 I) c3 j: h8 j% w' w- nname: "Hotkey", % c# j4 B. [0 }/ F3 d; @
probe: usb_kbd_probe,
5 [/ I2 j1 R! ]/ Sdisconnect: usb_kbd_disconnect,
* u0 j' h* F6 p S; `8 xid_table: usb_kbd_id_table,
@7 t7 D6 f; WNULL,
7 \$ X! n ^: J% z: Q) d};
. K4 @) A8 z" f4 U) l" D3 j I( D/ K. j3 w) u: `
static int __init usb_kbd_init(void) 5 z& d Q' \5 R8 c3 Z: i$ b% O, t2 r, A
{ & s& _+ o4 W; C+ m3 O
usb_register(&usb_kbd_driver); * c9 x S) J( K8 ~0 u6 q
info(DRIVER_VERSION ":" DRIVER_DESC);
3 O" K. b% P/ D) C3 @return 0;
/ E% O! C$ _6 c& |; n K# j} & ^. J6 D7 v; C+ s( b+ j$ w6 @
, X/ N) Q: d2 F& Y/ Z/ m9 ?
static void __exit usb_kbd_exit(void)
! v6 r/ g. ^) ~2 e. u' e. |{ 5 t5 e, h/ {! j3 l) r* [: w7 A! e: |
usb_deregister(&usb_kbd_driver); . Y& c) b, q0 @& b
}
. H( \/ D& ^! Z# Q* Y9 {0 t3 X( T5 q$ b8 S5 C& N
module_init(usb_kbd_init); % Z! n3 B! ~# Z( D* m
module_exit(usb_kbd_exit); |
|