- 在线时间
- 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,
5 U2 t" r8 O9 N* u" P6 c" USB ", " Mass Storage ", + r9 m$ g" x7 t/ G( c2 p9 M
US_SC_SCSI, US_PR_BULK, NULL, 7 O% l! J m, m" b! H9 [! b
US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE ) & _3 K. n/ c, P" [5 G7 N- l5 J# j( L
) }. Z ~+ I1 X& U+ v; q& R p注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。 . U/ d$ M7 B" s7 l% o. C+ ?
最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 3 `7 t V! Z; t& b8 H% ?
键盘飞梭支持
" s& O4 F0 @9 ~! N1 {+ a7 n目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。
7 g- t- }8 U d; z- Y" g: ~) ~下面是具体看到的信息
6 P& D1 u- ^3 k
, D- R3 V0 |8 X* S aT: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
* X" m' a8 B9 [3 _B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
8 O1 G. I$ B) k V4 QD: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
9 D B0 w, d3 p7 \9 G5 N( V c% qP: Vendor=0000 ProdID=0000 Rev= 0.00
% R p1 \: I! n& C: d! l- D# B [S: Product=USB UHCI Root Hub 6 D0 d# w) \0 L9 t3 {
S: SerialNumber=d800 5 n( M$ M! F2 Z& `$ w9 ~
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA q) B1 v* A! Q
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
* n! T$ K3 E% o: mE: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
+ m, G) s9 V7 vT: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 $ J; w9 k% f- `$ }% d. \% r
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
) w: r6 i5 I' z, R9 }P: Vendor=07e4 ProdID=9473 Rev= 0.02
9 y) s F4 B* f6 n; @S: Manufacturer=ALCOR . K; a) ^; e& o. h. s' j8 V
S: Product=Movado USB Keyboard
* y. d" c; g8 p1 k% OC:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
9 U' X0 f0 ]2 `% cI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
* Z; O+ I6 P. b: E8 e* y- N) R+ VE: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
7 J8 [0 c) |, U& J& U1 }% B6 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函数中 7 M4 s. H6 O3 x/ M+ m
* X O3 C9 s- K. K8 Y- e( x
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
$ n5 ]6 J, V+ _7 R+ U. v& n% gusb_kbd_irq, kbd, endpoint->bInterval); 8 g0 y9 E+ V, i, I: ~: R3 N
8 f) g7 [( J. A6 A* e* j一句中实现。 2 U) g% r; O4 R) H$ M
从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。
9 h7 g) I" \" P+ X# U在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 1 B- _) k9 W/ B5 |2 F
程序见附录1:键盘飞梭驱动。
, p0 b; [/ h$ t8 W+ S使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。
, V- C! H0 s8 {3 l: k参考资料
- h( G8 M( t$ D: a# s3 C- X- m: W1. 《LINUX设备驱动程序》
8 { `1 C8 q6 XALESSANDRO RUBINI著 # P' @. Z. Q( O8 K. {3 B; S
LISOLEG 译
. B4 L0 m( H* k2. 《Linux系统分析与高级编程技术》 % T3 k" U' _3 o, Q7 r
周巍松 编著 , g5 ?/ M' ^. w" U4 w# v4 w9 T
3. Linux Kernel-2.4.20源码和文档说明 + {9 Y$ z! ~/ H( R
附录1:键盘飞梭驱动 : S9 D) N7 t" j) T# @& Y
# ~3 }: R' {, U% X$ ]4 Q
#include <linux/kernel.h>
" U# B4 w" G ~- I) H9 m2 B#include <linux/slab.h> ) Z9 `2 U% u# _
#include <linux/module.h> 3 c# p. s7 M6 l: m0 t
#include <linux/input.h>
; p' |2 w& b C! Y; L2 t, J#include <linux/init.h> 2 u4 x5 Q3 q9 p1 g& E" t) J. [; R- P
#include <linux/usb.h> # w+ x! Z! V4 \. g/ G, ^2 v
#include <linux/kbd_ll.h>
% D" O8 \/ p* E( t6 Z7 n
" V' q; B" O# X1 v- }9 }; q/* # \/ C6 ?& C* R9 L" H
* Version Information 2 S) S0 ~: r9 J& w
*/ 3 A# G3 q5 D q' Z5 x4 |
#define DRIVER_VERSION "" 5 Y/ g7 P+ m2 R7 _! c; k; v8 P
#define DRIVER_AUTHOR "TGE HOTKEY " 8 Q* p. a2 Y, @" N8 n3 b0 f
#define DRIVER_DESC "USB HID Tge hotkey driver" : \; t: e$ M4 }% x: j% M! |
$ h2 k7 h! {/ X$ P% m! a
#define USB_HOTKEY_VENDOR_ID 0x07e4
' e m1 Q4 V: D# Y6 d#define USB_HOTKEY_PRODUCT_ID 0x9473
/ f0 N" [% X {" {- B9 ]//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
2 V+ `( L+ O* i5 T3 g4 n! Y) f
: A: G3 ]8 I7 X1 i) ?" sMODULE_AUTHOR( DRIVER_AUTHOR ); + x# w+ }) R+ S- p
MODULE_DESCRIPTION( DRIVER_DESC ); 5 h6 p& G! E( D) d3 G7 K
- @: p/ T7 J, s, K T6 G
struct usb_kbd {
- Q' U2 V, u6 h6 K9 G4 D( M3 e# bstruct input_dev dev;
' z& o$ S5 U4 P; F9 {+ vstruct usb_device *usbdev;
" L: _4 { F+ G* y6 Q' Hunsigned char new[8]; $ {3 f: r; F* Y& `% N
unsigned char old[8];
1 R6 B( F0 q' {3 ~! q% K, `struct urb irq, led; ( q, ~9 k" p6 Q' A! t
// devrequest dr; 8 S0 b# q1 v1 h4 a
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
/ _& L+ G) T1 |. N; U/ n struct usb_ctrlrequest dr; * _" e8 i) ^$ b! G; o$ M7 p+ x
unsigned char leds, newleds; / } U7 G1 H7 C
char name[128]; % w4 [- L- X! S: m# U3 ?2 P/ ^4 o3 K
int open;
% R2 u; ^+ R8 h}; * L- b2 t% E+ j
//此结构来自内核中drivers/usb/usbkbd..c
+ u1 L( |- p" A h- g9 T6 p" T- a% b9 `# t
static void usb_kbd_irq(struct urb *urb) - v( P! `: z$ g9 y/ h
{ / [9 Y- x# r4 R
struct usb_kbd *kbd = urb->context; 1 {) o2 u X& A
int *new;
* { L" O( I. n new = (int *) kbd->new; / u4 S; J/ o o* @
$ ?9 F# l) D& w5 }4 x' K$ @if(kbd->new[0] == (char)0x01) d, `( G0 K& f# n% y! D9 {6 Y# T
{
: N7 R1 L: J5 P: g+ Aif(((kbd->new[1]>>4)&0x0f)!=0x7) 9 R* a& P7 @3 P& h
{
6 }! j3 K! x; G. r9 b' H' {handle_scancode(0xe0,1); K* g2 C# S/ `) f' Z
handle_scancode(0x4b,1); 7 n% o" I1 }: W4 n3 W. n
handle_scancode(0xe0,0); # t. {/ f. w( [) _7 x
handle_scancode(0x4b,0);
5 g& Y ^! h$ I1 \# g} u3 u- Z. C6 B& d' w7 V/ @
else
2 b& [7 y' u1 l0 R% s{ 5 P) P. J/ ]" d" z; q
handle_scancode(0xe0,1);
0 y% x; Q7 S/ E* P) w handle_scancode(0x4d,1);
' B4 k0 s a$ `" \" l3 d. u handle_scancode(0xe0,0); 0 B6 ?! u1 n% D) I9 v
handle_scancode(0x4d,0);
. @, m$ f& }! @} + h3 |" ~4 m) ^+ _! C! S- N
}
" [. h( h3 {) ^. ~5 O1 y) h
S! C$ H; V' u; Z- r5 e
# F1 X7 V) a% ^printk("new=%x %x %x %x %x %x %x %x",
! ~# y+ w6 o0 `1 `$ Gkbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], & W e. ^% O9 h) U3 r: _
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
+ P1 s' p5 {- k, ]6 U9 p/ V2 ]0 i/ I% Y' B9 g4 Y1 K$ l& E
}
" `1 F# v! ]2 X8 J v& w; q1 G: p2 ]8 }1 g7 g! ?# G+ d& [
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, % U* D8 J# ^- l% @. U
const struct usb_device_id *id)
[. ?$ \7 _' Y9 A' q1 z% x$ ]{
1 X" R) R. [; G% L8 zstruct usb_interface *iface;
: A1 \4 L2 m; ?- N) w struct usb_interface_descriptor *interface;
% f8 f8 ]7 z# y5 fstruct usb_endpoint_descriptor *endpoint; * o7 |, S) _$ J% U
struct usb_kbd *kbd; 5 j& `. {; t# W' R6 s+ F
int pipe, maxp;
3 P2 n% p6 p3 e2 q+ J( Z* s. y' W
5 z7 J9 \3 l: o7 T& v3 eiface = &dev->actconfig->interface[ifnum]; 0 W6 N7 t- U) u" d
interface = &iface->altsetting[iface->act_altsetting]; + X( s5 W, L' I
! \6 @1 V! {, G5 G) `9 _3 x. Xif ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) ||
3 I5 s! ]! A5 B+ ](dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) ||
2 k% a4 e' q$ u$ c, {(ifnum != 1))
( F) q- d" C7 X. S) r, V5 J7 w{
3 C) T3 |* V" X' p2 a3 [3 a$ D7 Qreturn NULL; & J: y, B" G/ P5 {4 \
}
9 |( G" Q0 w* C3 S2 a' c* n6 _if (dev->actconfig->bNumInterfaces != 2)
8 M0 q- v) N' B) b4 F{
1 L4 Q4 s' Z- A! k8 H wreturn NULL;
! b; D$ ~4 i) o! W) m$ H4 Q% }}
$ L# p. B( K/ d. \0 b& i8 F- ?
! N9 K7 ~! O4 V2 Y, C* z8 Q$ Iif (interface->bNumEndpoints != 1) return NULL;
! T* y- q! p% V
6 ~! I* z, z1 B- e$ b endpoint = interface->endpoint + 0;
' {/ \" b' z. X* H6 |! G
( o$ r+ V4 C( i' o pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
! k; G3 ?% ]; A3 i. ]4 g- o maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
# n6 W7 A2 x+ b5 @' U" W6 E$ i4 \& c8 B" x+ F3 Q* Z1 J
usb_set_protocol(dev, interface->bInterfaceNumber, 0);
8 J) g# e( J' S) V usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); , V' C% H1 \5 V8 m' k
: X+ r7 L1 R M4 Z$ n9 u. f7 H9 Fprintk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
! z( V5 ]9 U7 d9 M) Tdev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp);
, e. a& g* n" x$ J7 W, y1 G; \0 A7 `2 H' j0 z7 M$ T
if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; : Q G7 ?6 U2 J, [# T
memset(kbd, 0, sizeof(struct usb_kbd)); 4 _( G$ k7 V a/ z0 Z
$ o( u0 @* K( T0 o) {
kbd->usbdev = dev; 9 I" X: w- G4 I, ?3 @) _
" H7 T1 D* Q# j8 p# ~* b4 B
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, ! x. N& Z4 N( k6 j
usb_kbd_irq, kbd, endpoint->bInterval);
6 ]3 o ~% K# G$ t6 H6 b
2 A# g7 [' c) l9 F/ ikbd->irq.dev = kbd->usbdev;
4 }( N8 ~+ D: S& \
6 o7 a5 r6 p; o+ X" x4 Rif (dev->descriptor.iManufacturer)
! d3 V. j2 h" ^ r6 @: m' t9 }1 t usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63); 7 W7 E' L* a% [- K) ~3 V1 C
& p( Z U$ N, m8 `# @
if (usb_submit_urb(&kbd->irq)) { 9 a: L6 |7 }# d/ j0 H/ s
kfree(kbd);
& W( J7 s, a! K return NULL; $ ?: I2 @1 ]% n" @
}
5 p2 j2 N$ D4 K8 f3 B. p. H+ \2 Q6 H
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", - t; `! K5 a+ |$ I+ |5 h
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
1 B8 s9 _1 J. n, }8 g* q
1 g4 I5 w# m( H9 P+ _6 u return kbd; ! n! ]' S" B4 c2 _! w2 p! l. s5 Y
}
3 n4 J+ a& Z& G) C0 h6 ~$ W9 i0 H" `+ X4 v* m' @
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
& N F# |9 h( G) W! H* [! ^{
. M, ~& J" r3 W' |2 Qstruct usb_kbd *kbd = ptr;
( N+ N' k7 q J usb_unlink_urb(&kbd->irq);
% ^: N+ c" a1 c$ U. e2 F kfree(kbd); % `2 f# A3 ]. b' B/ r1 U! a
! n3 ^. c6 ~- V! m
}
( [4 P. P9 \ j) U
, K8 E3 [* q8 E4 z0 `! P+ }static struct usb_device_id usb_kbd_id_table [] = { # w; @% L1 q# N/ v% `7 o
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) },
* O% B* \) ~1 J( Q4 Q{ } /* Terminating entry */
# i f1 }3 @9 G1 e( I}; , U6 w) [ a; B3 w% D' t
! p& L1 q* C$ {MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
9 p9 w, c; N& j' d
* ^( e8 H; R, h- N! F4 i7 Ystatic struct usb_driver usb_kbd_driver = {
# u0 r/ L; i' \2 Xname: "Hotkey", 5 o, Z% D' z+ R7 ?$ Z4 d5 }
probe: usb_kbd_probe, 8 m; m+ W. m% v- T, h
disconnect: usb_kbd_disconnect, % m: _% K8 Z( n9 n0 e8 W' C
id_table: usb_kbd_id_table, 0 Y" X5 w; W4 J* K
NULL, 2 S3 B# R; ?- ~" x7 v
};
/ D. T1 s+ A$ h# K" I9 |2 Q3 }* M9 G1 u" b8 e/ s6 l* c' @' g2 T
static int __init usb_kbd_init(void) 8 p( {. M! H# F3 a+ ~7 z/ L3 l5 Y$ g5 Y
{ $ K2 ^0 s" e0 y. h$ w7 ^
usb_register(&usb_kbd_driver);
3 \6 u/ b$ p. Z2 @info(DRIVER_VERSION ":" DRIVER_DESC); ) r+ S& P8 D: Q- S& t) b8 w' e
return 0;
- E$ \1 K# R" c) O0 u( ?9 V}
7 U6 ^" a& K. `" I, U* y8 u1 V1 p' U
! L- f# {) H/ B9 t$ r: I. Y. jstatic void __exit usb_kbd_exit(void)
3 O& F* i9 {$ `- \) Q; T) [{
7 ]9 K" a/ c$ d- K: P: m" Iusb_deregister(&usb_kbd_driver);
# ^9 ~4 C: k. _& w/ }} ) j% ]. ^& x& G5 }
% M+ A @; R1 L' `module_init(usb_kbd_init);
9 S" a. ~2 `% Q3 O+ T; ^% zmodule_exit(usb_kbd_exit); |
|