- 在线时间
- 63 小时
- 最后登录
- 2019-5-3
- 注册时间
- 2004-5-10
- 听众数
- 442
- 收听数
- 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, # e' w; K$ J- B+ N, Q
" USB ", " Mass Storage ",
8 q; I( p2 S0 ?2 j+ kUS_SC_SCSI, US_PR_BULK, NULL, ( p; v& H5 a% Z: J( ^& x) i5 t3 O
US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE )
- h) w/ R- h. G9 x
9 W) c( j4 B% z' M5 {% _( }注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
3 b+ T# ^& R. ^: p; q4 W5 w; ^最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 : [5 R: i4 K* p+ W( k: `2 \3 F) Y
键盘飞梭支持
9 L7 z! W1 c( C4 F目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 : E" G4 A- C- m7 x
下面是具体看到的信息
$ i: u7 ?2 [$ n1 b. `1 @' Y/ K5 i& D) w, Z7 t2 z# W
T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 9 [" z4 [' k+ E
B: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
9 `, ]; `; r7 H# @D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
: ^; c6 l9 i; X/ a5 \. ~: W5 }P: Vendor=0000 ProdID=0000 Rev= 0.00 & N" e1 v0 l6 }( E6 Y( q, l6 \
S: Product=USB UHCI Root Hub
! G) ]5 B; l9 j) u6 aS: SerialNumber=d800
* d% r2 ^3 s! S$ S: d4 qC:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
. u. x( I& ~/ I, J2 _: @+ eI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
q: T% E o' c9 x- DE: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
" x' K1 W& ?4 F; x1 Y8 Q: ET: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3
2 E. e r1 }) U5 F: HD: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 ; J2 ?; O; z0 ]: u
P: Vendor=07e4 ProdID=9473 Rev= 0.02 ( ?: c' F4 V2 P3 X) {! ?) y; _
S: Manufacturer=ALCOR
! r/ W( M* p5 N5 g- }, O' oS: Product=Movado USB Keyboard . a: z. S6 e" k9 {5 }) r
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA 2 S3 `! c: | ]: K: E
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub & C6 b# V' A0 @
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms ! ^ F( ]5 w' y( {
找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中
( E- t. W: M! P) H
. C" [4 L5 q) T: b- h- ]FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
; _: N( r5 @0 j/ K- q( |2 _usb_kbd_irq, kbd, endpoint->bInterval);
0 C% h3 E0 c/ g+ O9 f
$ A* z6 s a! y% i! ] |8 @7 i一句中实现。
4 X y2 g" b/ f6 u: w& ^' R从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。 9 ~8 j- i% h9 b
在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 0 b! A, i+ G' ~4 E
程序见附录1:键盘飞梭驱动。 8 M8 K4 g3 [4 j/ ^+ w1 W
使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。
+ M- q5 d$ |1 s, y参考资料
5 x- F7 ? I/ x( f6 r8 l& B1. 《LINUX设备驱动程序》
! e# t5 Q% Y% f3 W! o+ Y0 SALESSANDRO RUBINI著 1 l6 m( K$ s" |8 z- X* B
LISOLEG 译
3 Y, F& W4 u0 H+ Y7 t) C2. 《Linux系统分析与高级编程技术》
7 U: k& c6 s+ {! L m周巍松 编著
2 l6 ]; L9 ^) V, }/ E: a3. Linux Kernel-2.4.20源码和文档说明
2 I5 G3 f. t b: _附录1:键盘飞梭驱动 8 l2 X4 N, d! z
) b) A+ ~0 K6 n2 ?4 J! w& a
#include <linux/kernel.h> ; ?5 E# Z. x. ] x) v
#include <linux/slab.h>
/ s/ q3 r; k Y+ l, W3 v#include <linux/module.h> ( y; I& O' ~4 a+ ^+ G) g1 s
#include <linux/input.h>
8 j; `1 D i- ] l* g& D#include <linux/init.h>
! {) ?# k. C: |% C, Y$ j* d% W#include <linux/usb.h> 9 t# j- n1 L4 s5 U+ g% x- n2 X
#include <linux/kbd_ll.h>
, O7 {8 g2 }1 i/ b/ A# t5 E& ~* Y7 d4 z# `- x7 R4 x1 l) o: @6 ]# a& r- H
/* : U# c6 E0 ]6 u2 ~+ l! g
* Version Information
' f2 k+ z# x: `. `9 ?6 E */
5 B. d& Q& Q8 J6 j7 ?#define DRIVER_VERSION ""
" |; n' f. V" [' V4 K#define DRIVER_AUTHOR "TGE HOTKEY " " d" w' V5 s. R3 {3 c$ D) R; K
#define DRIVER_DESC "USB HID Tge hotkey driver" 3 d; N/ |! Q' ^: R. o1 D. r
- g" D7 f. ^& y, ~; a; b" V* @! }5 s
#define USB_HOTKEY_VENDOR_ID 0x07e4
2 l3 v5 I3 N0 T S- q/ _+ V- ?#define USB_HOTKEY_PRODUCT_ID 0x9473
3 F4 X- q$ d M( i//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值 X6 e; |9 N+ \' W. T- V- L1 F+ S8 D
: s T* X+ T* ^ n3 O1 @MODULE_AUTHOR( DRIVER_AUTHOR );
; g$ l% c: j2 wMODULE_DESCRIPTION( DRIVER_DESC );
U' U# i1 z. q/ G& @* L
. D- [ |1 g; ^. G: d, W2 p vstruct usb_kbd {
" w$ M) r$ T3 _3 T$ j! h# u! ]struct input_dev dev;
- \$ i2 T4 d/ K, l, c7 _( mstruct usb_device *usbdev; 4 Z+ w5 U4 D8 X: B. z
unsigned char new[8]; 9 U1 P* z; p& p
unsigned char old[8];
7 j6 x6 f7 a E* H3 v! K( fstruct urb irq, led;
7 [$ v6 @/ G8 E1 c// devrequest dr; 7 X; `" c5 ?0 [4 |: G
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
2 s9 m: W& N; W struct usb_ctrlrequest dr; / S% w' M* P+ F5 S9 ^
unsigned char leds, newleds;
% t4 j6 o6 v5 X9 F& j: A9 O( rchar name[128];
; P4 s3 t: u- K: \* _8 D7 _int open;
. u8 ]8 i- r) @+ h$ X: p- {+ j6 E& F};
& D3 w; }. D4 {' S; n//此结构来自内核中drivers/usb/usbkbd..c 1 ]4 y" o, X0 |: Q, w
( S# x7 z# n) t3 \/ d% S
static void usb_kbd_irq(struct urb *urb)
% [# d, I0 i2 K) y{ ; z/ ~6 ~0 A$ M, G! Y& M6 T
struct usb_kbd *kbd = urb->context;
$ v* {, d3 D# k: O: D9 _: u int *new; % Y9 n- o2 o2 g3 w# {* \! d) a
new = (int *) kbd->new;
$ l! [* i" @0 b
( y. d4 _' E( v+ U7 c/ bif(kbd->new[0] == (char)0x01)
# j* \# Y8 M3 Y* u{ , G" n8 c1 G4 I9 J7 ?$ k y% X
if(((kbd->new[1]>>4)&0x0f)!=0x7) ; e& w) o% `: ~! v& ^: U& B
{ ; k7 E7 }" n0 v. y5 }& {1 f
handle_scancode(0xe0,1); # y6 J! M8 w3 b: j9 p3 a) v
handle_scancode(0x4b,1);
7 }1 L% T( p, S: t% w* { handle_scancode(0xe0,0);
n3 c$ L' g6 y$ m- @3 V( e; a handle_scancode(0x4b,0); 8 v/ d/ z3 P* T9 g# _5 M- E% A
} / Z. s" A8 P8 C/ j
else ( z* L, {, S$ X
{ 2 J( j# s: P- u) e( p
handle_scancode(0xe0,1); 6 p7 u- D$ c2 H8 t7 V0 e
handle_scancode(0x4d,1);
% n- v& S+ f! v% P& q+ X0 K handle_scancode(0xe0,0);
6 Z) t0 g1 a) W8 K: c! z8 B handle_scancode(0x4d,0); : m( u6 w1 J5 c+ o* O6 H8 s
}
5 m( f6 O/ b% y1 c! ^% ?8 `}
, W+ e. H" F; w J3 B1 i+ n* m" d- I7 N8 f1 h+ o/ g
% c# A+ G# Z7 l) Rprintk("new=%x %x %x %x %x %x %x %x", p; p# X, x' B: |4 d. g
kbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3],
$ P" k0 w* I5 e( Pkbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
7 \, r N4 u2 M; d+ r9 W7 E
' H2 L/ L% `" p$ C}
0 G7 V h; P2 ~* K. L+ W x9 L, H2 P- ~( R/ j& L9 y' `) S
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, 7 R$ h6 @$ S/ ?: @
const struct usb_device_id *id)
2 k7 K C2 s) t{
1 i$ f. F8 b3 K2 f9 i9 astruct usb_interface *iface;
. p! H4 C* e# G) e$ h struct usb_interface_descriptor *interface; / b- I8 i8 m+ ^& P/ C. R7 E* {; Q
struct usb_endpoint_descriptor *endpoint; ! e. V {0 u1 g+ R, X$ z! {
struct usb_kbd *kbd;
# \- o2 \( p+ p, s! B1 f- C3 q- Y int pipe, maxp;
3 H* m3 F- v7 W3 x
: c; q8 G) ~- k6 H6 Xiface = &dev->actconfig->interface[ifnum]; 3 Q& S8 D( e2 ^& A1 U
interface = &iface->altsetting[iface->act_altsetting];
+ p8 l' I* e6 b2 a% z8 \: q% r5 N2 H' d! K- d
if ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || ; @- c4 d( Y9 \) ]' Z- w
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || ) p6 m8 \) R' i- p4 M& K: S* Q- o
(ifnum != 1))
0 e6 [3 c: M% g+ q, [{
9 f2 D" r3 x% Creturn NULL;
. o$ l# u1 o6 I% d}
9 h3 _2 D+ R3 s- V. G) F Vif (dev->actconfig->bNumInterfaces != 2) . C" A4 I: _! m. k" k5 D8 q2 B
{ 7 `1 Y" f$ H. Z) l' d
return NULL;
8 P& \( U2 }2 r* m} {5 I) }3 N+ _, V, a" ]
% ^$ r4 |) T# ]4 ]
if (interface->bNumEndpoints != 1) return NULL;
" l( w$ \+ ]$ `4 V% X2 X8 i$ ^
2 Z# E' k6 U' g# x0 E d# G endpoint = interface->endpoint + 0; * F4 J3 x T; w1 f4 k# y
& h$ r* D# V0 v
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); 4 y, q; S+ |5 U1 k4 _: U
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
2 ]% u8 z Q8 @
1 F. A s8 Q1 }; Z" o5 E usb_set_protocol(dev, interface->bInterfaceNumber, 0);
- j ~1 G- N! C8 O, h usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
4 `3 w7 k1 @ L2 F/ G9 \# _$ `% U$ p2 c, c( |6 C. _' R
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
( Q3 \1 y5 B; g; E& x" f5 R4 K- pdev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp);
! ^% i* I( `0 U1 o* D: m& L* ?* \; o7 D7 T3 d8 A$ V
if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
, W6 B2 B2 {) P/ U memset(kbd, 0, sizeof(struct usb_kbd));
1 p4 C! F, o' q* @' s5 o$ L9 W8 V. ? }- y
kbd->usbdev = dev; ( A: ^. ]: E5 C d# z& _7 x1 {
. s1 D4 V6 ~5 \/ c
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 6 ]+ t q9 W/ A; R, Q
usb_kbd_irq, kbd, endpoint->bInterval); ) p; g4 I5 \# B5 b, c `7 G
6 s3 a# i2 }$ K: h* C& Akbd->irq.dev = kbd->usbdev;
( h% Y, l) d- L7 U& S) V% s& U: A3 e% J5 i
if (dev->descriptor.iManufacturer) 5 f1 [! |9 U- W
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63);
/ j' ?; |1 k: \, \
1 N9 z" C$ Q hif (usb_submit_urb(&kbd->irq)) {
q2 [& b3 ]1 s7 i2 V kfree(kbd); 7 ]! Y0 z% ~9 F
return NULL; 8 _0 U6 [8 I! o+ o. S5 Z
} . J9 w4 l/ y0 R% Q
% A, f8 g, A" ]' c5 ?9 w# u, T( y
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", 8 T2 Y8 Q! ]% v" E
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); 5 m8 m$ X, \0 _6 F( B. |
. _" J# F, O. U5 Y# Z return kbd; 6 o2 x, p) t! Z5 E" K9 |
} e4 @1 [" Y( S3 m& ~$ L: i
, [" B1 X$ A/ kstatic void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
+ z2 Z7 C! G4 C{ 6 ]' c8 |/ H! r5 k7 n( w
struct usb_kbd *kbd = ptr; / f; ?5 i- D3 l% u% ?' {( m
usb_unlink_urb(&kbd->irq); 7 l$ y. P- T7 y8 `; ^
kfree(kbd);
# b5 g' f: Y/ L4 r
3 O0 Q0 A# w8 _} : f7 P9 o. F( \4 g M
8 m6 U# z; v: l) L1 V: l
static struct usb_device_id usb_kbd_id_table [] = {
' F! Q; q$ X! a' `2 W8 @{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) }, 2 h) @' @. Z3 j. N7 }2 D
{ } /* Terminating entry */ 7 M3 y$ \3 k3 {
}; . o$ v$ N. k2 E$ |- j& k" i# B$ x
8 G1 v Q P; i/ ?1 M
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table); 9 d0 w3 B; n" d6 D2 r& g
& q7 X- P3 x- ~static struct usb_driver usb_kbd_driver = { % {4 W' m6 H. n2 G$ F, h3 a# T% p
name: "Hotkey", - |# y3 j* P; o) T" A9 t5 J2 [/ @
probe: usb_kbd_probe, - y" x6 O _. x$ ]" P
disconnect: usb_kbd_disconnect,
4 v- m/ C. W" G* s- qid_table: usb_kbd_id_table,
- v2 X4 u, S9 E$ S6 U7 }NULL, 5 y6 H' {3 P% p1 C2 b0 B
}; $ N# P9 v" Z7 v" p- Y) b
, v& q/ y r" M H" J2 G( q, W0 ~
static int __init usb_kbd_init(void)
+ N5 c) O) C, O. G! c, K' k* c# f{
- n+ K) O1 t. n H' v3 ~8 z Vusb_register(&usb_kbd_driver);
- [4 x5 B- |2 k- e+ @" Finfo(DRIVER_VERSION ":" DRIVER_DESC);
1 t. S& F! K* A& s6 T& x; nreturn 0;
3 M; m/ e K! G l0 i( f: K/ v% W}
8 ]# N% }1 y D3 g t5 ~0 I- u1 I1 ]3 d( Y5 p
static void __exit usb_kbd_exit(void)
[/ [4 L3 {, Z6 N; K2 c/ T; K{
/ U, |, s) h+ {( M- p8 l. |usb_deregister(&usb_kbd_driver); & s9 K- l4 q0 e$ r3 n
}
" b' }$ X0 k( F* j& Z/ ]; G5 V% R4 r) d# i2 b7 d. {( v9 }9 V7 y
module_init(usb_kbd_init);
" P) j4 h! d' j+ b, ]- amodule_exit(usb_kbd_exit); |
|