- 在线时间
- 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, ' \3 ~1 _( T! C- u- f3 O. y* D+ ?
" USB ", " Mass Storage ",
! v: Y& f! K" z% Q7 pUS_SC_SCSI, US_PR_BULK, NULL, ( R+ t9 E! P( V
US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE )
& P( u4 k- \0 g7 J- b8 Q
5 @$ w/ T* x1 L; W( T注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
' `" _6 v; K: m最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。 - ^3 e8 G6 j/ o" U) }% h
键盘飞梭支持 ! L* a* t2 E% ?
目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 % |) k/ T& b' p ]( {# n A
下面是具体看到的信息
9 h* Y# r8 e: D: N1 D3 U/ ~% I
/ s, l# r4 ?9 H S( I+ D8 ~T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
! ~. t; T5 G7 i# L- Z" D ~# f0 EB: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0 6 R2 }, J, d' n. ^& Y$ q! U) i
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
& g0 U6 L2 c2 U6 t! }& c! PP: Vendor=0000 ProdID=0000 Rev= 0.00 5 B$ v8 _ j" D" i S
S: Product=USB UHCI Root Hub % r* I) p. v9 {
S: SerialNumber=d800 3 w4 Q' Z, M4 j, j* r* @
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
1 C/ ~* s5 w4 X# l0 ]4 RI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub ' b7 L- R6 s" X& A* T' k
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms , F- k3 G5 n/ C. }
T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3
% [6 a( J. N( gD: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 ! h9 B/ Q9 j1 Y) C$ T4 t. L
P: Vendor=07e4 ProdID=9473 Rev= 0.02
$ u9 U7 L$ R9 t- kS: Manufacturer=ALCOR " c7 Q: S5 B" s% c+ X
S: Product=Movado USB Keyboard
0 _ W% f2 d* k7 j* y; GC:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA 3 p+ Q5 H. ?0 h+ c
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
: b8 \' t3 `6 I9 c) E: T: uE: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms 5 j( m- n! {! E: [4 a
找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中 0 G" o( B4 j- a
& E) m( x0 e! K kFILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 6 q L- g; {- F+ o7 m" o+ F( d N
usb_kbd_irq, kbd, endpoint->bInterval);
/ [, ]3 B0 v" d$ G v$ n6 }- n" |9 P
一句中实现。
% t( u7 B# {% n1 h6 r, m% ~从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。 " p7 W6 ]# G N8 y/ `: p
在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。 - f- f7 v x( t$ B3 U; T8 l/ ~
程序见附录1:键盘飞梭驱动。
% Z3 H& @9 g) t8 Y5 O使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。
1 u2 Q! O5 Z: z: x9 Y8 A Z% X5 E参考资料 7 q n6 ?- J" ?3 a( X, O+ t6 W
1. 《LINUX设备驱动程序》
. h" J- I4 q/ X8 {ALESSANDRO RUBINI著
4 T, |$ @0 U# p- ^' p8 D D3 v& kLISOLEG 译 ) c z: V: R8 W
2. 《Linux系统分析与高级编程技术》 5 M O; `4 [% U6 ^
周巍松 编著
6 z. b* g' @( u5 q3. Linux Kernel-2.4.20源码和文档说明
6 k( m& \; F1 u4 f附录1:键盘飞梭驱动
( o! P7 T# K3 o X3 H0 R: \* j( V. b; m# j
#include <linux/kernel.h> 6 r7 j" M$ j p, z ]2 c Q8 m
#include <linux/slab.h> ) q3 c# J8 J3 ~/ z8 }4 A5 B
#include <linux/module.h>
1 M( w: \: V) `, D7 `! @+ E#include <linux/input.h>
; n$ L/ E( q- \1 b#include <linux/init.h>
. o. y# Y1 E0 S) i7 w. M+ z#include <linux/usb.h> # M$ G+ j, a1 o+ C; W
#include <linux/kbd_ll.h>
) Z- K2 r6 a4 k9 o+ N+ [1 l9 e( ?% c
9 c3 F3 {$ _* U/ R! {$ S/*
# H. m0 w+ j( G% j1 o6 `% E * Version Information
0 y% c& G- f) f8 ], i# E+ ~% H5 O */ % N. x- _' O7 f6 E; y
#define DRIVER_VERSION ""
, K! K0 d. O- O( q. j: Y#define DRIVER_AUTHOR "TGE HOTKEY "
+ ]5 y) s' v/ \0 u2 s7 r" ~' _. ~#define DRIVER_DESC "USB HID Tge hotkey driver"
3 q6 l5 |5 M. p/ {- W+ j7 @4 {6 a6 k( o |1 L" {& P3 ~# X/ ?/ [
#define USB_HOTKEY_VENDOR_ID 0x07e4
2 h& K8 r& f! z/ b* S% y#define USB_HOTKEY_PRODUCT_ID 0x9473
- |: J Z! L; t% @8 C6 x//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
! O& T6 [9 B4 n1 x9 u4 u. `: ~& G( \, v; b$ a) S6 s) S" K, w0 o1 E
MODULE_AUTHOR( DRIVER_AUTHOR ); 7 B0 y, A- V$ u/ A M
MODULE_DESCRIPTION( DRIVER_DESC );
; u; B7 d: m6 _8 E- z% p3 X/ x2 k* e6 n8 Z2 m/ a1 D, v
struct usb_kbd {
. K" V9 b: U+ P9 M/ fstruct input_dev dev; 9 T& a5 {& a$ T2 Z8 x. f
struct usb_device *usbdev;
) |/ o$ ^! A9 Q$ I5 Tunsigned char new[8]; / a) Z% f1 u( T
unsigned char old[8];
6 K8 s! ]7 }) Z: {" Wstruct urb irq, led;
% _3 r+ w( T$ R9 I// devrequest dr; 1 h2 P3 j% w* t1 Z* p
//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化
0 Q$ ?9 R0 E( _3 D% N struct usb_ctrlrequest dr;
. u. L* i3 G+ Y+ p' s @unsigned char leds, newleds;
# p+ D& T( x( c/ ~$ N* K; mchar name[128]; 2 r" d( q9 r& i% j, z
int open; : c" s( m9 d, U: r- b* S+ t2 m$ v
};
$ ?' N/ a, |( k2 a5 ?' f5 p+ _) H//此结构来自内核中drivers/usb/usbkbd..c
2 W% E' [: }+ _" |* `, s
9 A: {7 y! t% y8 A& J7 cstatic void usb_kbd_irq(struct urb *urb) 1 D# M! q, m( B8 i1 U: _& M% c
{
, j! D3 q7 u) }3 }5 x3 fstruct usb_kbd *kbd = urb->context;
* ^7 [4 b! W1 J; k1 c7 O int *new;
% L; c3 @2 K: m% L0 x2 \: @ new = (int *) kbd->new; 6 Z: `0 U( h& o% w
s1 d" T# `& D; X9 D# K) `5 A$ Nif(kbd->new[0] == (char)0x01)
. w6 D, ]7 }' O. z{
( g8 W: h" h8 p4 U# c, Aif(((kbd->new[1]>>4)&0x0f)!=0x7) ) {& |5 X9 N7 U7 I1 l8 ?/ L" _6 B( P
{ ( x5 p# B4 N( Z* _6 ?
handle_scancode(0xe0,1);
" P+ ^* [& I' u! yhandle_scancode(0x4b,1); & B+ h) h6 |9 w, A
handle_scancode(0xe0,0);
6 r2 P/ \ q2 _2 C1 h4 ? handle_scancode(0x4b,0);
4 ^! l: P' c' k) J, {}
& _( J+ C' o6 }6 Zelse
2 D m5 _) B3 \; s# X2 S6 b{
/ M2 ~! s4 R6 ^& E& l7 b0 ]$ Ihandle_scancode(0xe0,1);
& \6 f" v8 a" @! z ]9 [5 J0 e handle_scancode(0x4d,1);
$ k$ s5 U1 R3 `' V8 R7 f1 l" y handle_scancode(0xe0,0); 5 K3 \% |8 M/ |" n4 u3 \ J% w
handle_scancode(0x4d,0); 1 v$ u' P5 W0 u# _ s$ b( i
}
4 K+ |: u" a) k9 Z/ `4 b& U} 1 ~# W& m; p, V" c5 l; _/ J
* V; C( n" b$ n" K, q2 ?$ u! o5 S6 y3 P# O2 v9 S5 X0 T7 x
printk("new=%x %x %x %x %x %x %x %x",
; G6 L4 e5 e7 N8 }9 G/ Skbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3], 3 i% r. n3 z+ ] t2 f! y5 |
kbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
, g2 ^! ~3 p# g8 [) c- G9 k# `. a' x4 [: E
} + V+ Z9 Z; n- L
1 c6 _3 X0 b. Z' ~' S% Zstatic void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, 5 `0 ?: J0 T3 ]3 B( y7 K: a* ~
const struct usb_device_id *id) , \$ _' V+ T9 n6 s5 ~3 h4 l% }, U
{
8 N+ M2 u( e4 A; Y. D) n9 |! @/ H8 K+ _) mstruct usb_interface *iface;
9 o1 C" `- ^$ e6 J- R" R; Q1 h struct usb_interface_descriptor *interface; " \* [& c7 `8 ?8 U% } Z/ s7 C
struct usb_endpoint_descriptor *endpoint; 8 W8 J/ {6 [& C; R* k
struct usb_kbd *kbd;
8 a5 b0 I. _& ~* o1 ^ int pipe, maxp; * d$ k$ z+ {/ H, ^2 p
+ u( F* B- _& u' ?( ?
iface = &dev->actconfig->interface[ifnum]; 8 n# X- Y2 g2 T4 o
interface = &iface->altsetting[iface->act_altsetting]; ' @9 q5 P7 L8 ~
: m u, n$ d- k3 Z" R8 nif ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || 3 q; }4 j5 M1 Q" H; E8 U
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || & W# l% n3 i* X" z) r
(ifnum != 1)) 6 Q. U8 v$ U7 u4 k& ~, ^
{ * ?7 v; Q. K' o
return NULL; 1 X: Z- n4 E! s5 ]4 ^: J6 i
}
4 b* Z7 g2 M7 L( e) T$ U$ uif (dev->actconfig->bNumInterfaces != 2) . K1 [9 J. i8 M$ E8 p
{
7 p8 x* N( V+ G( x0 \5 d& g4 m, @return NULL; % @; ~. J( ^. h; x7 V7 u" i: v; A
}
! @0 H' `' o: {6 S# J+ y. x ~, p7 P1 |$ T4 b, Y6 m3 w: |; `
if (interface->bNumEndpoints != 1) return NULL;
( O' q- s7 W% x2 S% H( G- }* _8 E" w% j
endpoint = interface->endpoint + 0;
% V8 A: j) N& I/ _6 O: M* @; }& D
% H: d% a; C- y6 C/ Z \! g pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); ) L7 @' \; y, K- e- p2 A( {
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
* c8 k4 t% b( h: H( T' l. c3 P3 }! L Q- a, W6 u, [
usb_set_protocol(dev, interface->bInterfaceNumber, 0); , `9 X- X. w! b+ a8 C5 F% |
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); # \. h+ B7 f5 a8 U7 Q
# K& ?( [% S& u& ]0 F9 B5 ~7 xprintk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n", 5 o- Q2 _3 w& z4 ]( @+ D! g
dev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp); * A9 Y; r7 I0 ~8 ^6 ?6 U
9 J$ m* k# A6 ]: x if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; 9 k0 K0 h4 a2 Q' s. `5 D0 r* ^
memset(kbd, 0, sizeof(struct usb_kbd));
6 M; _6 O* j/ J' C3 U2 H4 j$ D
2 T) }; |8 J7 t kbd->usbdev = dev;
. H. q3 J, ]% x2 b1 u; F. }/ f/ N0 h9 l8 Z9 K! R3 |6 t
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, + J% ]. f( P+ J8 O; v
usb_kbd_irq, kbd, endpoint->bInterval);
; }& ?9 H v2 j w- _5 D, {. c
! C, Y. i. K. y7 F; f$ @$ ~# R8 v: ukbd->irq.dev = kbd->usbdev;
, q) G6 t) I# w3 ?3 ?8 u8 {* i& ?* U' S3 k! ~ K! R* S
if (dev->descriptor.iManufacturer) 0 z, P' W3 o9 P: U' o
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63);
) x" l0 f4 r% L( j, t; k
! ]6 p7 Y. ~' E( Iif (usb_submit_urb(&kbd->irq)) { 8 b. K; w4 q- P1 @$ ^1 x8 f
kfree(kbd);
8 Y. y& y7 [5 m# L, [ u, _0 Z" X return NULL;
4 I) ]4 E* Z3 _5 n3 [: m: x, n } 8 M) S6 Z* f$ {
) j8 u. i3 g0 U) B3 o' zprintk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", ! Z; K( X# K& A5 P/ N
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); ; `% ~ l l5 h4 Q6 {
& U d) `1 G' F0 [7 b- X return kbd;
7 J; d# N# n1 I/ G/ Q} T) f: i* j5 g9 C7 Z* e
% X$ X9 o( J$ G. F* R- \
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr) # Q6 J3 _) h8 h2 R+ k
{
5 _+ I3 M& z3 ?5 k3 i" _struct usb_kbd *kbd = ptr; 9 Z/ L0 X8 t/ v; A) ?5 E+ C
usb_unlink_urb(&kbd->irq); 9 y( @% R6 {) u! K6 f
kfree(kbd);
0 i9 ~9 h1 G/ C5 d1 M/ j
& v# z' q2 s3 V9 s( H$ ]8 C) P}
3 Q8 R" o1 C; [! K3 j# j( {5 a
- Y) y, X; E$ R$ m5 y8 }static struct usb_device_id usb_kbd_id_table [] = { * a' j) y1 ~5 W0 m/ ^/ O/ L
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) }, + ^- q" ~6 B5 Q# s
{ } /* Terminating entry */ g$ U3 w" o7 y% o
}; @2 n8 \. M6 e! E- g
. k2 U+ f- D. V1 s1 Z, `
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
c1 c. z" \6 U: ?' M
0 F9 S* i! e( r7 t: hstatic struct usb_driver usb_kbd_driver = {
5 [$ K, y# ~ x) E0 G- h. Y9 T2 G" Nname: "Hotkey", ' z3 E! T% ?1 c4 u
probe: usb_kbd_probe,
6 r5 q. [6 d- ~/ ~4 h4 q7 C, Z \& qdisconnect: usb_kbd_disconnect,
: N% K) Y& W+ z/ c( \id_table: usb_kbd_id_table, : R' ~+ a; t( i+ \3 l9 G
NULL,
7 |" R8 g i: r}; ( J7 V3 c7 O3 v3 _3 S. `
: O6 R& C& k; ~" y ostatic int __init usb_kbd_init(void) % L* ?; h0 m( w$ d
{ & N- d+ g! D8 @6 ~- \; w
usb_register(&usb_kbd_driver);
% M/ J* l& u" x! `( I# V6 V# Jinfo(DRIVER_VERSION ":" DRIVER_DESC); 3 Q+ Y' Z( t( G" a6 P6 N2 u2 H
return 0;
& L5 a, o- x0 Y} + c! i6 R# m! s* e2 e% k
) ~& t- l1 L' U3 @) v5 [' y* c0 P) }
static void __exit usb_kbd_exit(void)
: \' F; P' l0 Y6 B: h/ d{
( g/ `( T7 t! o' u6 q0 u4 Musb_deregister(&usb_kbd_driver); 1 M1 _5 g( \4 m. F. z/ q6 j
}
+ ?- w4 J0 I( ]* B% o. o
3 {' \$ t2 ~3 T' f* r8 zmodule_init(usb_kbd_init); & b# L j" r- H0 P
module_exit(usb_kbd_exit); |
|