以USB鼠标驱动为例
框架入口源文件: usb_mouse.c hub.c
(可根据入口源文件,再按着框架到内核走一遍)
内核版本:linux_2.6.22.6 硬件平台:JZ2440
以下是驱动框架:
以下是驱动代码 usb_mouse.c :
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb/input.h>
#include <linux/hid.h> //定义一个input_dev 结构体
static struct input_dev *usb_mouse_dev; static int usb_pipe;
static char *usb_buff;
static int usb_len;
static struct urb *usb_urb;
static dma_addr_t usb_buff_phy; // id_table .bInterfaceClass = (cl), .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
static struct usb_device_id usb_mouse_driver_id_table[] =
{
{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID,USB_INTERFACE_SUBCLASS_BOOT,USB_INTERFACE_PROTOCOL_MOUSE)},
}; //usb 中断
static void usb_mouse_int(struct urb *urb) {
#if 0
int i=;
static int cnt=;
printk("cnt = %d",++cnt);
for (i = ; i < usb_len; i++)
{
printk("%02x ", usb_buff[i]);
}
printk("\n");
#endif #if 1
static unsigned char pre_val; /* bit[0] 左 bit[1] 右 bit[3] 滑轮安下
*/ if ((pre_val & (<<)) != (usb_buff[] & (<<)))
{
input_event(usb_mouse_dev, EV_KEY, KEY_L, (usb_buff[] & (<<)) ? : );
input_sync(usb_mouse_dev);
} if ((pre_val & (<<)) != (usb_buff[] & (<<)))
{
input_event(usb_mouse_dev, EV_KEY, KEY_S, (usb_buff[] & (<<)) ? : );
input_sync(usb_mouse_dev);
} if ((pre_val & (<<)) != (usb_buff[] & (<<)))
{
input_event(usb_mouse_dev, EV_KEY, KEY_ENTER, (usb_buff[] & (<<)) ? : );
input_sync(usb_mouse_dev);
} pre_val = usb_buff[];
#endif //重新提交
usb_submit_urb(usb_urb, GFP_KERNEL);
} static int usb_mouse_driver_probe(struct usb_interface *intf,const struct usb_device_id *id)
{ struct usb_device *usb_dev;
//接口 端点
struct usb_host_interface *usb_interface;
struct usb_endpoint_descriptor *usb_endpoint; usb_interface = intf->cur_altsetting;
usb_endpoint = &usb_interface->endpoint[].desc; //输入子系统
//分配一个input_dev
usb_mouse_dev = input_allocate_device(); //初始化 input_dev 结构体
set_bit(EV_KEY,usb_mouse_dev->evbit);
set_bit(EV_REP,usb_mouse_dev->evbit); set_bit(KEY_L,usb_mouse_dev->keybit);
set_bit(KEY_S,usb_mouse_dev->keybit);
set_bit(KEY_ENTER,usb_mouse_dev->keybit); //注册 input_dev 结构体
input_register_device(usb_mouse_dev); //USB
// 起点:usb_dev usb_pipe 终点:usb_urb usb_buff 长度:usb_len 函数:usb_mouse_int
usb_dev = interface_to_usbdev(intf);
usb_pipe = usb_rcvintpipe(usb_dev, usb_endpoint->bEndpointAddress); usb_len = usb_endpoint->wMaxPacketSize; usb_urb = usb_alloc_urb(,GFP_KERNEL);
usb_buff = usb_buffer_alloc(usb_dev, usb_len, GFP_ATOMIC,&usb_buff_phy); //设置 URB
usb_fill_int_urb(usb_urb,usb_dev,usb_pipe,usb_buff, usb_len, usb_mouse_int, NULL, usb_endpoint->bInterval); usb_urb->transfer_dma = usb_buff_phy;
usb_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; //提交 URB
usb_submit_urb(usb_urb, GFP_KERNEL);
return ; } static void usb_mouse_driver_disconnect(struct usb_interface *intf)
{
struct usb_device *usb_dev= interface_to_usbdev(intf);
//usb
usb_kill_urb(usb_urb);
usb_free_urb(usb_urb);
usb_buffer_free(usb_dev, usb_len, usb_buff, usb_buff_phy);
// input_dev
input_unregister_device(usb_mouse_dev);
input_free_device(usb_mouse_dev);
} //定义一个usb_driver结构体
static struct usb_driver usb_mouse_driver =
{
.name = "usb_mouse_driver",
.probe =usb_mouse_driver_probe,
.disconnect =usb_mouse_driver_disconnect,
.id_table = usb_mouse_driver_id_table,
}; static int usb_mouse_driver_init(void)
{
usb_register(&usb_mouse_driver);
return ;
} static void usb_mouse_driver_exit(void)
{
usb_deregister(&usb_mouse_driver);
} module_init(usb_mouse_driver_init);
module_exit(usb_mouse_driver_exit);
MODULE_LICENSE("GPL");
以下是编译驱动的Makefile:
KERN_DIR = /work/systems/kernel/linux-/linux-2.6.22.6 all:
make -C $(KERN_DIR) M=`pwd` modules clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order obj-m += usb_mouse.o