1. 指定USB键盘驱动所需的头文件:
% x/ M8 {9 G4 Y, G/ O6 o+ m( H! q+ I2 d8 V. @, D0 Y8 l
#include <linux/kernel.h>/*内核头文件,含有内核一些常用函数的原型定义*/
6 i' B1 I7 @3 ]1 _
#include <linux/slab.h>/*定义内存分配的一些函数*/
9 |/ l3 Q/ F! }0 D% E# h' B3 W
#include <linux/module.h>/*模块编译必须的头文件*/
( {6 G2 G: U4 L8 b( J
#include <linux/input.h>/*输入设备相关函数的头文件*/
$ Z! t- D* ^% J2 H; W+ b# c
#include <linux/init.h>/*linux初始化模块函数定义*/
1 f8 B0 ?( i4 l. z
#include <linux/usb.h> /*USB设备相关函数定义*/
/ L {, X, t" U* ?2. 定义键盘码表数组:
7 ]" F0 a( V) p" Z; s
/*使用第一套键盘扫描码表:A-1E;B-30;C-2E…*/
- j- S, z% `, s( Y( O
static unsigned char usb_kbd_keycode[256] = {
1 V+ g# X4 S" n
0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
7 t9 d- b- _9 v; t3 r2 K; Z+ _: o
50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
& S! S% t* A7 w- P7 d4 c! h7 S
4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
/ Q+ b. r( D, k" }0 f' {; z
27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
8 P- y6 M* g; a* w4 M$ [
65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
- B0 m) ?7 J- P
105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
6 R2 v- Q2 i: p4 N- Y
72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
' L; [8 t0 ^8 U8 |8 ?4 F
191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
2 o/ p0 u- @/ h- I7 z
115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0,
* D+ N% W" M5 W- t
122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7 {* N: s j* u3 t6 w* s4 ^+ c
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
) l, D# \8 V; o5 l4 W0 c9 `2 e
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
# w# I+ y* j$ b# ]* }4 g7 ]$ h
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! q) k I3 ^4 v3 e
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6 ?! P4 F m- g+ W- `
29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
( k, J2 d" i3 h
150,158,159,128,136,177,178,176,142,152,173,140
, u. ]) |9 R5 v5 e};
3 Q5 Z0 m! L% y$ V4 r1 G6 A# R3. 编写设备ID表:
( u" @, F2 t0 N) ~
static struct usb_device_id usb_kbd_id_table [] = {
+ h% l/ [8 V; g7 Y4 ]' ~) K
{ USB_INTERFACE_INFO(3, 1, 1) },/*3,1,1分别表示接口类,接口子类,接口协议;3,1,1为键盘接口类;鼠标为3,1,2*/
, K( l5 ^& Q8 W" A: a
{ } /* Terminating entry */
& P3 ^8 E* }* W+ b' u& \
};
4 Z4 ~( {/ _ K1 ]MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);/*指定设备ID表*/
( Y7 a; y* h' n4. 定义USB键盘结构体:
" T5 s( ^. V) K. `. e1 f0 v+ c! U
struct usb_kbd {
& D) _/ ]4 c+ H5 |! P+ ]
struct input_dev *dev; /*定义一个输入设备*/
0 `8 \ w* R, ]2 Z3 f" u& V
struct usb_device *usbdev;/*定义一个usb设备*/
* i/ d" y, \; u" D& E; D/ i# V. E
unsigned char old[8]; /*按键离开时所用之数据缓冲区*/
+ m% u( P! T& d& B
struct urb *irq/*usb键盘之中断请求块*/, *led/*usb键盘之指示灯请求块*/;
# b, O; c. u* a( `' F6 v
unsigned char newleds;/*目标指定灯状态*/
' A6 Q8 [, E9 J: w2 n# N
char name[128];/*存放厂商名字及产品名字*/
2 f2 z$ m3 m& D% Z, B& Z
char phys[64];/*设备之节点*/
6 w/ ?9 ?# E8 Y6 }6 v O7 Q
, j, ?. y8 g% k/ N& A
unsigned char *new;/*按键按下时所用之数据缓冲区*/
; `4 |+ B8 i2 s. E$ L
struct usb_ctrlrequest *cr;/*控制请求结构*/
4 q1 N6 R3 ~4 d0 U, O% ?
unsigned char *leds;/*当前指示灯状态*/
* U7 i% `* G4 a/ E4 H) A) ?4 `. Z
dma_addr_t cr_dma; /*控制请求DMA缓冲地址*/
$ ?; S* u% Q! S8 F* {- `
dma_addr_t new_dma; /*中断urb会使用该DMA缓冲区*/
8 o9 ?$ K1 B9 T6 z4 F& t
dma_addr_t leds_dma; /*指示灯DAM缓冲地址*/
( a0 C! {/ a# G' Z) S6 o" c% v};
" `# T6 H$ d# x5 a- B3 ^5. 编写USB键盘驱动结构(任何一个LINUX下的驱动都有个类似的驱动结构):
( u; \" u" V2 d2 Y
/*USB键盘驱动结构体*/
0 P7 V1 G4 I# o# s# N9 n
static struct usb_driver usb_kbd_driver = {
; F) L9 Q/ s$ F# h
.name = "usbkbd",/*驱动名字*/
( Z5 |/ Q* X4 Y! \# f9 C
.probe = usb_kbd_probe,/*驱动探测函数,加载时用到*/
# {" n5 \1 t6 K j1 v
.disconnect = usb_kbd_disconnect,/*驱动断开函数,在卸载时用到*/
2 S) |0 K, a o/ f, `; F
.id_table = usb_kbd_id_table,/*驱动设备ID表,用来指定设备或接口*/
- |" s( J; g! Z; n7 i
};
. K9 [0 h. ?4 a, B( O6. 编写模块加载函数(每个驱动都会有一个加载函数,由module_init调用):
9 H1 \ a( y" t+ t3 [ ^
/*驱动程序生命周期的开始点,向 USB core 注册这个键盘驱动程序。*/
9 K: P) y8 ?- d
static int __init usb_kbd_init(void)
4 O7 @ r. r9 ^$ q. G
{
$ y9 m8 w0 V2 r# h; |6 f N: G
int result = usb_register(&usb_kbd_driver);/*注册USB键盘驱动*/
7 w/ S: x. p+ N' g1 R) k9 ]1 H
if (result == 0) /*注册失败*/