- 在线时间
- 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, & N* H+ n# d/ Y9 J
" USB ", " Mass Storage ",
- I- j. y' t0 YUS_SC_SCSI, US_PR_BULK, NULL,
1 B- W; n+ Z7 H+ |US_FL_FIX_INQUIRY | US_FL_START_STOP |US_FL_MODE_XLATE ) + r: }( ~; H7 E5 t$ |
# y( n4 m- `! l注意:添加以上几句的位置,一定要正确。比较发现,usb-storage驱动对所有注册都是按idVendor, idProduct数值从小到大排列的。我们也要放在相应位置。
% t1 f7 ]- X7 w( O最后,填入以上信息,我们就可以重新编译生成内核或usb-storage.o模块。这时候插入我们的设备就可以跟其他U盘一样作为SCSI设备去访问了。
5 _1 o# ~/ `% k5 D$ @) H键盘飞梭支持
# l& B1 K+ N A0 y) x目前很多键盘都有飞梭和手写板,下面我们就尝试为一款键盘飞梭加入一个驱动。在通常情况,当我们插入USB接口键盘时,在/proc/bus/usb/devices会看到多个USB设备。比如:你的USB键盘上的飞梭会是一个,你的手写板会是一个,若是你的USB键盘有USB扩展连接埠,也会看到。 " Y8 |( h1 w, S- ^
下面是具体看到的信息
4 }* u2 ]& }0 F/ P# z( H* V
5 w2 U: H0 g/ e4 E( w" k" d% TT: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
* Q4 S2 s0 x1 pB: Alloc= 11/900 us ( 1%), #Int= 1, #Iso= 0
8 d+ e7 q( v- A! ~D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
( L5 p, U9 X( u s( ?P: Vendor=0000 ProdID=0000 Rev= 0.00
/ v2 R) t0 r! p* yS: Product=USB UHCI Root Hub
) q& p& s( Q' T" `( j/ U& H9 U3 {S: SerialNumber=d800
$ z8 }% I# B& Q; W5 S3 y# @: zC:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
# w- R* Z6 c) ?) N8 b/ K, p: QI: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
4 I3 x6 \' d- fE: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms * [! S/ b2 \ ~
T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 3 * b' o( e0 k- ]
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
3 D/ e' W- l* C' ~8 J: {8 a9 gP: Vendor=07e4 ProdID=9473 Rev= 0.02 1 l2 o; m8 d# h$ O5 {
S: Manufacturer=ALCOR
4 O8 Q0 E7 b& Y& ]5 c4 PS: Product=Movado USB Keyboard
0 z' `2 n* D1 v: X# \3 s- _' PC:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA 2 n+ v: ^) J6 h
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
- K, E0 z2 R8 JE: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms 6 T) ]% x: s9 X! @
找到相应的信息后就可开始工作了。实际上,飞梭的定义和键盘键码通常是一样的,所以我们参照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函数中
. w: O% S" b( B7 C6 Q S! ?. M; n# t. }( A4 v1 @! w' P- ?
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, 4 t2 m$ u, J5 x7 B/ x
usb_kbd_irq, kbd, endpoint->bInterval);
! A! a. ]4 x$ P) W/ o. y! z. a0 c9 ?& Z9 U& n$ _
一句中实现。
( N+ C1 l. d5 H% K6 W4 g; x5 j从usb骨架中我们知道,usb_kbd_probe函数就是在USB设备被系统发现是运行的。其他部分就都不是关键了。你可以根据具体的探测值(Vendor=07e4 ProdID=9473等)进行一些修改就可以了。值得一提的是,在键盘中断中,我们的做法是收到USB飞梭消息后,把它模拟成左方向键和右方向键,在这里,就看你想怎么去响应它了。当然你也可以响应模拟成F14、F15等扩展键码。 : c0 j' Q" s* W0 @% B$ A
在了解了此基本的驱动后,对于一个你已经拿到通讯协议的键盘所带手写板,你就应该能进行相应驱动的开发了吧。
' Q4 g" I9 [6 n$ }$ a; @0 I程序见附录1:键盘飞梭驱动。
0 Y$ o: D8 V7 }% r% B- ^: N {使用此驱动要注意的问题:在加载此驱动时你必须先把hid设备卸载,加载完usbhkey.o模块后再加载hid.o。因为若hid存在,它的probe会屏蔽系统去利用我们的驱动发现我们的设备。其实,飞梭本来就是一个hid设备,正确的方法,或许你应该修改hid的probe函数,然后把我们的驱动融入其中。
4 s3 ^& W8 |' v( Y$ Z2 M' O5 F, v参考资料 $ Y( m4 K7 ]3 U3 E" |' Z. N4 U5 L! p
1. 《LINUX设备驱动程序》
& r. k1 t5 M" f' M' H+ QALESSANDRO RUBINI著
4 {4 F; v1 v3 n1 E. @+ zLISOLEG 译
/ e, D# ?" ?7 {2. 《Linux系统分析与高级编程技术》 5 c+ b/ ?) L) G; W* }& W
周巍松 编著 / _& ?: a& \! y3 S, `
3. Linux Kernel-2.4.20源码和文档说明
; o! g) \2 M+ K$ U" I* W" O附录1:键盘飞梭驱动
5 R: u; a3 I% D& J% m
/ E) S5 d. u' B6 N. m; ` b! Q+ y3 A#include <linux/kernel.h> 1 k3 s$ s. k$ y+ V
#include <linux/slab.h>
! i7 I3 C, _. C5 e; W#include <linux/module.h> . E- O9 Z& \0 |% K# B- ^
#include <linux/input.h> ( q. |$ e# x+ I
#include <linux/init.h> 4 D, O* G: I2 `7 V F$ E
#include <linux/usb.h> + D3 f6 {9 b' J% R
#include <linux/kbd_ll.h>
+ F# p& `# Z: V& ^1 K! O2 G4 T) ?, e/ M9 K$ d6 Q0 [" j9 P. Q
/*
) `$ d9 K8 S2 I. s" P' I) @7 K9 ~! V * Version Information
: i$ W. K L& z! L */ 7 J0 y/ h) N9 B# p7 Q" e& X
#define DRIVER_VERSION ""
% M8 p% ?2 G" `- P#define DRIVER_AUTHOR "TGE HOTKEY "
( T; h# v, Z5 F# E#define DRIVER_DESC "USB HID Tge hotkey driver"
$ p9 X; g) g& D0 `1 f E
" X _. G% }2 y+ d* k/ J#define USB_HOTKEY_VENDOR_ID 0x07e4
+ p$ f+ K8 j# A0 r8 I8 g#define USB_HOTKEY_PRODUCT_ID 0x9473 7 g0 _# }/ }1 c4 v* T/ h$ i# J
//厂商和产品ID信息就是/proc/bus/usb/devices中看到的值
4 G) P1 p/ o* y+ t
$ V) }2 ]; j! zMODULE_AUTHOR( DRIVER_AUTHOR ); ! a i3 z$ F6 B/ _+ Z
MODULE_DESCRIPTION( DRIVER_DESC );
" ]6 W& K- A$ V3 k1 K
0 u& X6 T4 P& [struct usb_kbd {
: G6 {2 }: T4 ^" Hstruct input_dev dev; , G# n' ^4 O. t: c2 J6 C
struct usb_device *usbdev; $ }6 @# V7 X$ _" K# V
unsigned char new[8];
! S1 V7 V. p! c$ Y# p4 Runsigned char old[8];
6 j/ z! W j$ E# e8 ?struct urb irq, led; 6 s1 s! T |, h- T
// devrequest dr;
: D: U$ {; Y( ~. V/ I! s//这一行和下一行的区别在于kernel2.4.20版本对usb_kbd键盘结构定义发生了变化 6 |) M% Z3 ~4 [
struct usb_ctrlrequest dr;
; }" E2 A* v' H- funsigned char leds, newleds;
! g& j) y* m' ichar name[128];
' V9 b6 A. W' B" v- ^int open; 3 }, R& k! A3 `& c
};
4 }, d5 Z: g3 ?% j//此结构来自内核中drivers/usb/usbkbd..c
9 Y. U @" ^! N5 `* V- W" L0 O5 p9 z9 @
static void usb_kbd_irq(struct urb *urb)
# G1 y3 Q3 n! L* @; [- @ D{
6 W0 f4 N( M" jstruct usb_kbd *kbd = urb->context;
) P! K' d6 [! l3 x% P! | int *new;
! O; `' k& `+ q1 N new = (int *) kbd->new;
1 b% O8 z, k# f7 t; _/ V, W7 M- S! u6 x
if(kbd->new[0] == (char)0x01)
2 N |/ D/ H5 b+ i+ P{
- l* O% T7 L0 O- ^if(((kbd->new[1]>>4)&0x0f)!=0x7)
( u9 A+ r0 c, D3 z% O{
$ m/ n( w/ K1 S0 u: ? phandle_scancode(0xe0,1); / C+ B. N# ], O" H" C% [- c: C
handle_scancode(0x4b,1); 8 G5 k( C5 C8 A( D7 Y2 i
handle_scancode(0xe0,0); , p! P4 ?1 d( j7 M, U! {
handle_scancode(0x4b,0); 2 H! U+ s; n7 G6 `
}
% c9 \/ _, y, aelse
, e; q0 j+ |% W7 u# X{ 0 ?* o6 C+ K# O' r( r& K
handle_scancode(0xe0,1);
: y- E5 y0 G' i1 k1 U handle_scancode(0x4d,1);
" [2 |8 j! i! X$ ]6 P handle_scancode(0xe0,0); 0 }5 Q$ J0 R- ^) ]
handle_scancode(0x4d,0);
. w3 T9 m3 D7 }7 v}
$ t# m* |. g/ J- [9 M}
, n) }2 U, ]/ g5 \6 E" r0 n3 T1 d8 ]4 t3 ~
( {! h7 d- ]6 C! Yprintk("new=%x %x %x %x %x %x %x %x", 2 G6 U% y) w2 U, m h
kbd->new[0],kbd->new[1],kbd->new[2],kbd->new[3],
K& c* q: m1 F* T7 hkbd->new[4],kbd->new[5],kbd->new[6],kbd->new[7]);
. [& a$ v7 _/ e5 z
2 G; n- `5 g! L6 ]2 V. g2 b2 W% _# ^, `}
7 H6 |; P6 Q. T5 G) l$ I$ u4 Q5 P8 ?& c. P: F
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, # g" b6 D& f4 A3 x& } Z3 R% D
const struct usb_device_id *id)
1 H( X! t. S5 m& W6 P1 V! {* W8 k K{ + y i3 u$ ~( {5 h
struct usb_interface *iface;
4 O ?3 @ X6 S' F: f struct usb_interface_descriptor *interface;
* S0 n0 o( h; b2 n+ l; R; Zstruct usb_endpoint_descriptor *endpoint;
& g j* b5 Z; O- b& A0 b% d( o struct usb_kbd *kbd;
+ K3 U. T& O- l# Q4 \: p int pipe, maxp; c0 t1 i# |, \# `% d
: ~) t p3 j7 \9 `7 Oiface = &dev->actconfig->interface[ifnum]; 7 F$ c! Q0 G$ w& Z1 j$ d6 ]
interface = &iface->altsetting[iface->act_altsetting]; 9 r1 p1 y; d3 ~6 p, J
$ s5 N: x$ q* D8 a3 j" Gif ((dev->descriptor.idVendor != USB_HOTKEY_VENDOR_ID) || + X1 Q- b: M) ?. i4 b* K
(dev->descriptor.idProduct != USB_HOTKEY_PRODUCT_ID) || - v; c4 A% g! S: [9 q' |
(ifnum != 1))
* g# G2 U2 _% l4 T) Q$ V7 V{ 6 q3 d: f% r" _
return NULL;
9 u- h! g- |# n K0 G( {2 c9 d} , q* W+ e i9 O7 A
if (dev->actconfig->bNumInterfaces != 2)
1 v& q8 X6 n! p1 y& E{
4 ~( H1 Z# S! m. t' [& l2 Creturn NULL; ' T- Z$ b/ q) F, Z7 k
}
! G6 E/ ?4 ?9 k6 b* r5 ~4 b0 }
; `- G: L8 d$ M& Jif (interface->bNumEndpoints != 1) return NULL; * u$ h# S0 ^1 ]8 L3 c& r
9 N {2 M4 s. ] B. ^ S$ ]
endpoint = interface->endpoint + 0; & C" e3 h) F4 T& }& n
9 n/ C6 l5 i* k- i pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); : M8 e& W3 Q: |1 k
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
6 q! l& |" l0 P1 {1 S3 b
+ \- G/ y# x' q' @( t) q usb_set_protocol(dev, interface->bInterfaceNumber, 0); % G5 x9 a( V9 J% n! d; g$ p) B7 C
usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
& ~* D! J9 C3 {9 j5 T! n/ Z; Y' k" o, S6 w2 E8 t8 ]) c
printk(KERN_INFO "GU Vid = %.4x, Pid = %.4x, Device = %.2x, ifnum = %.2x, bufCount = %.8x\\n",
5 q$ z( ?. \2 p% Q# w6 D# w7 \. b) n1 ddev->descriptor.idVendor,dev->descriptor.idProduct,dev->descriptor.bcdDevice, ifnum, maxp);
( K' b8 A0 x% E0 ]6 t' Q" J$ S/ l. d" p8 v) J+ m ^! v
if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
% J3 H* t T } memset(kbd, 0, sizeof(struct usb_kbd));
+ \7 [- H; T5 Q6 Q4 I. N1 y# U( |; W* s
kbd->usbdev = dev;
; c' M1 K/ i' y! q- S) d1 I. _. G0 i/ G- _# p* K; u
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
, h, i# ~& _# I7 T Iusb_kbd_irq, kbd, endpoint->bInterval); 4 J- H# c6 N) ]* j1 y
+ ]' V: q9 l/ N
kbd->irq.dev = kbd->usbdev; + K3 A/ [5 Z; Q
2 f: N q( {; U( i7 |
if (dev->descriptor.iManufacturer) F/ x5 `! v6 e7 j. [$ h9 p1 H
usb_string(dev, dev->descriptor.iManufacturer, kbd->name, 63);
: B1 n( V$ c. n2 w1 C
' z& b4 d& s, y' N0 O3 ?4 ?% wif (usb_submit_urb(&kbd->irq)) {
+ \0 Z3 t1 g; c kfree(kbd); 2 t- ?7 }/ p" P
return NULL; ) Q# h3 a5 _+ {
}
* o5 v+ B; I' R/ _5 ~0 \% I2 r: f
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\\n", * b# m; p0 W; F/ ~" I
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); % h9 ^$ q6 Y- J5 r: F- B, O
/ S! L7 _: [5 Z! k+ ]& {
return kbd; : s0 a: x: h) g7 p4 z8 z
}
( B$ M: I- I3 S3 x4 v. d9 K% A; C% k- K* r/ W( q
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr) / c# N0 ]( Z: d. A O6 }
{
+ F* \% H* G# s3 H" Bstruct usb_kbd *kbd = ptr; 3 P# \3 E; i, N) ^, H
usb_unlink_urb(&kbd->irq); w& D1 d- F' d6 r b
kfree(kbd);
" Y& n5 D4 {& y/ s! ]
- x/ a3 a5 ?2 l' [8 Z}
9 @. F! @2 D. z; o$ H' K% i! r5 |4 d3 v3 z. ?
static struct usb_device_id usb_kbd_id_table [] = { / a i, |2 x$ c; N
{ USB_DEVICE(USB_HOTKEY_VENDOR_ID, USB_HOTKEY_PRODUCT_ID) },
! ?. ^/ m ~8 L% O7 q; v{ } /* Terminating entry */
9 V$ h' u" ?. w! s};
" r# d9 R5 ~; M1 G0 @1 b9 y' X5 v7 C2 a
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table); " ?5 T$ l$ z5 U! D7 h- x: \
9 N( x) j# b( d; N- u
static struct usb_driver usb_kbd_driver = { : O6 w7 W# O- J: l) }3 D
name: "Hotkey",
4 E, J! k @, M4 pprobe: usb_kbd_probe, : v' L: A( ?% G/ g x3 m: @/ Z
disconnect: usb_kbd_disconnect, ) H% w6 s y6 h# f& A2 B
id_table: usb_kbd_id_table,
2 V* x2 X. G+ W1 VNULL,
; h" Z0 M4 B2 b5 p5 J! ~4 P; ]. N}; 8 l* o& R" p y
8 X1 X2 q0 e' ]0 M) ^. s! b, C
static int __init usb_kbd_init(void) % [# K- T, q% P3 U
{
( q! b2 o- e5 o+ D# D( H B! rusb_register(&usb_kbd_driver);
" }6 j+ Q H8 Y7 Z( p, q6 U0 {8 zinfo(DRIVER_VERSION ":" DRIVER_DESC);
. ]+ f9 J) x$ lreturn 0; 1 u# W' ?( _) ?" Q: p' ` @0 Q
} 1 v8 \) g! L1 L8 s
* k; M( z3 k% F+ p% |
static void __exit usb_kbd_exit(void)
e# Z- F5 k) Q# H# j{
@: J$ Z2 b' Eusb_deregister(&usb_kbd_driver);
% S' E9 {2 r5 Q8 i/ j} 6 h2 s! ~9 z" C4 h7 f: U3 X% w. `! s, v
+ F( H2 B& p1 Z2 b
module_init(usb_kbd_init); 8 B k a9 _7 A
module_exit(usb_kbd_exit); |
|