USB驱动框架

以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=0;
   static int cnt=0;
   printk("cnt = %d",++cnt);
   for (i = 0; i < usb_len; i++)
    {
        printk("%02x ", usb_buff[i]);
    }
    printk("
");
#endif 

#if 1
    static unsigned char pre_val;

    /*       bit[0] 左         bit[1] 右          bit[3] 滑轮安下
       */

    if ((pre_val & (1<<0)) != (usb_buff[0] & (1<<0)))
    {
        input_event(usb_mouse_dev, EV_KEY, KEY_L, (usb_buff[0] & (1<<0)) ? 1 : 0);
        input_sync(usb_mouse_dev);
    }

    if ((pre_val & (1<<1)) != (usb_buff[0] & (1<<1)))
    {        
        input_event(usb_mouse_dev, EV_KEY, KEY_S, (usb_buff[0] & (1<<1)) ? 1 : 0);
        input_sync(usb_mouse_dev);
    }

    if ((pre_val & (1<<2)) != (usb_buff[0] & (1<<2)))
    {
        input_event(usb_mouse_dev, EV_KEY, KEY_ENTER, (usb_buff[0] & (1<<2)) ? 1 : 0);
        input_sync(usb_mouse_dev);
    }
    
    pre_val = usb_buff[0];
#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[0].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(0,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 0;
  
}


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 0;
}

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-2/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
原文地址:https://www.cnblogs.com/zsy12138/p/10392677.html