天天看點

簡單usb驅動代碼記錄

</pre><pre name="code" class="cpp">#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>


static struct usb_device *grh_usb_dev;
static struct input_dev *grh_input_dev;
static struct usb_host_interface *interface;
static struct usb_endpoint_descriptor *endpoint;
static char *usb_buffer_virtual; //緩存邏輯位址
static dma_addr_t usb_buffer_phys; //緩存實體位址
static int usb_buffer_len;
static struct urb *grh_urb;

//完成usb回饋資料資料傳輸之後的中斷處理函數
static void grh_usb_mouse_comp(struct urb *urb){
    static int count = 0;
    static char last_value = 0;
    char cur_value;
    int i;

/*
    printk(KERN_EMERG"count=%d\n", ++count);
    for(i=0; i<usb_buffer_len ;i++){
        printk(KERN_EMERG"%02x ", usb_buffer_virtual[i]);
    }
    printk(KERN_EMERG"\n");
*/
    //送出事件
    cur_value = usb_buffer_virtual[0];
    if( (cur_value&(1<<0)) != (last_value&(1<<0)) ){
        printk(KERN_EMERG"submit l\n");
        if(cur_value&(1<<0))
            input_event(grh_input_dev, EV_KEY, KEY_L, 1); //按下
        else
            input_event(grh_input_dev, EV_KEY, KEY_L, 0); //松開
    }
    if( (cur_value&(1<<1)) != (last_value&(1<<1)) ){
        printk(KERN_EMERG"submit s\n");
        if(cur_value&(1<<1))
            input_event(grh_input_dev, EV_KEY, KEY_S, 1); //按下
        else
            input_event(grh_input_dev, EV_KEY, KEY_S, 0); //松開
    }
    if( (cur_value&(1<<2)) != (last_value&(1<<2)) ){
        printk(KERN_EMERG"submit enter\n");
        if(cur_value&(1<<2))
            input_event(grh_input_dev, EV_KEY, KEY_ENTER, 1); //按下
        else
            input_event(grh_input_dev, EV_KEY, KEY_ENTER, 0); //松開
    }
    input_sync(grh_input_dev);

    last_value = cur_value;
    //重新送出urb
    usb_submit_urb(grh_urb, GFP_KERNEL);
}



static int grh_usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id){
    int pipe; //資料源

    printk(KERN_EMERG"GRH:find usb device!\n");
    grh_usb_dev = interface_to_usbdev(intf);
    printk(KERN_EMERG"GRH:product=%s\n", grh_usb_dev->product);
    printk(KERN_EMERG"GRH:manufacturer=%s\n", grh_usb_dev->manufacturer);
    printk(KERN_EMERG"GRH:serial=%s\n", grh_usb_dev->serial);
    printk(KERN_EMERG"GRH:usb version=%x\n", grh_usb_dev->descriptor.bcdUSB);
    printk(KERN_EMERG"GRH:idVendor=%x\n", grh_usb_dev->descriptor.idVendor);
    printk(KERN_EMERG"GRH:idProduct=%x\n", grh_usb_dev->descriptor.idProduct);

    grh_input_dev = input_allocate_device();

    //設定能夠産生哪些事件
    set_bit(EV_KEY, grh_input_dev->evbit);
    set_bit(EV_REP, grh_input_dev->evbit);
    set_bit(KEY_L, grh_input_dev->keybit);
    set_bit(KEY_S, grh_input_dev->keybit);
    set_bit(KEY_ENTER, grh_input_dev->keybit);

    input_register_device(grh_input_dev);



    //硬體操作
    interface = intf->cur_altsetting;
    endpoint = &interface->endpoint[0].desc; //擷取除了0号端點以外的第一個端點
    pipe = usb_rcvintpipe(grh_usb_dev, endpoint->bEndpointAddress); //資料源
    usb_buffer_len = endpoint->wMaxPacketSize;
    usb_buffer_virtual = usb_buffer_alloc(grh_usb_dev, usb_buffer_len, GFP_ATOMIC, &usb_buffer_phys); //資料目的
    grh_urb = usb_alloc_urb(0, GFP_KERNEL); //配置設定一個usb request block

    //設定ubr的内容
    usb_fill_int_urb(
        grh_urb, grh_usb_dev, pipe, usb_buffer_virtual,
        usb_buffer_len,
        grh_usb_mouse_comp, //資料傳輸完成後usb總線驅動會調用這個函數
        NULL,
        endpoint->bInterval
    );
    grh_urb->transfer_dma = usb_buffer_phys; //設定請求塊回饋資料的實體位址
    grh_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

    //向usb裝置送出urb
    usb_submit_urb(grh_urb, GFP_KERNEL);

    return 0;
}

static void grh_usb_mouse_disconnect(struct usb_interface *intf){
    printk(KERN_EMERG"GRH:usb device disconnect!\n");
    input_unregister_device(grh_input_dev);
    input_free_device(grh_input_dev);
    usb_kill_urb(grh_urb);
    usb_free_urb(grh_urb);
    usb_buffer_free(grh_usb_dev, usb_buffer_len, usb_buffer_virtual, usb_buffer_phys);
    return;
}


static struct usb_device_id usb_mouse_id_table [] = {
    { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
        USB_INTERFACE_PROTOCOL_MOUSE) },
    { } /* Terminating entry */
};



static struct usb_driver grh_usb_mouse_driver = {
    .name       = "grh_test_usb_driver",
    .probe      = grh_usb_mouse_probe,
    .disconnect = grh_usb_mouse_disconnect,
    .id_table   = usb_mouse_id_table,  //虛拟總線對比這個字段之後才能關聯usb接口和驅動子產品
};



static int usb_mouse_init(void){
    usb_register(&grh_usb_mouse_driver);
    return 0;
}


static void usb_mouse_exit(void){
    usb_deregister(&grh_usb_mouse_driver);
    return;
}

module_init(usb_mouse_init);
module_exit(usb_mouse_exit);
MODULE_AUTHOR("GRH");
MODULE_VERSION("1.0");
MODULE_DESCRIPTION("USB MOUSE DRIVER");
MODULE_LICENSE("GPL");

           

繼續閱讀