</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");