USB驱动之常规usb鼠标驱动

news/2024/11/7 8:35:57/

        常规usb鼠标驱动使用的是linux中常用的drivers/hid/usbhid/usbmouse.c驱动。

static const 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 */
};MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);static struct usb_driver usb_mouse_driver = {.name		= "usbmouse",.probe		= usb_mouse_probe,.disconnect	= usb_mouse_disconnect,.id_table	= usb_mouse_id_table,
};module_usb_driver(usb_mouse_driver);

        probe主要是初始化usb设备和input设备,终极目标是为了完成urb的提交和input设备的注册

static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id)
{struct usb_device *dev = interface_to_usbdev(intf);//由接口获取usb_devicestruct usb_host_interface *interface;struct usb_endpoint_descriptor *endpoint;//端点描述符struct usb_mouse *mouse;//本驱动私有结构体struct input_dev *input_dev;//输入结构体int pipe, maxp;int error = -ENOMEM;interface = intf->cur_altsetting;if (interface->desc.bNumEndpoints != 1)//鼠标端点只有1个return -ENODEV;endpoint = &interface->endpoint[0].desc;//获得端点描述符if (!usb_endpoint_is_int_in(endpoint))//检查该端点是否是中断输入端点return -ENODEV;pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);//建立中断输入端点maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));//返回端点能传输的最大的数据包,鼠标的返回的最大数据包为4个字节mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL);//分配mouse结构体input_dev = input_allocate_device();//分配input设备空间if (!mouse || !input_dev)goto fail1;mouse->data = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &mouse->data_dma);if (!mouse->data)goto fail1;mouse->irq = usb_alloc_urb(0, GFP_KERNEL);if (!mouse->irq)goto fail2;mouse->usbdev = dev;mouse->dev = input_dev;if (dev->manufacturer) //拷贝厂商IDstrlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name));if (dev->product) { //拷贝产品IDif (dev->manufacturer)strlcat(mouse->name, " ", sizeof(mouse->name));strlcat(mouse->name, dev->product, sizeof(mouse->name));}if (!strlen(mouse->name))snprintf(mouse->name, sizeof(mouse->name),"USB HIDBP Mouse %04x:%04x",le16_to_cpu(dev->descriptor.idVendor),le16_to_cpu(dev->descriptor.idProduct));usb_make_path(dev, mouse->phys, sizeof(mouse->phys));strlcat(mouse->phys, "/input0", sizeof(mouse->phys));input_dev->name = mouse->name;//将鼠标名赋给内嵌input结构体input_dev->phys = mouse->phys;//将鼠标设备节点名赋给内嵌input结构体usb_to_input_id(dev, &input_dev->id);//将usb_driver的支持项拷贝给inputinput_dev->dev.parent = &intf->dev;//evbit表明支持按键事件(EV_KEY)和相对坐标事件(EV_REL)input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);//keybit表明按键值包括左键、右键和中键input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);//relbit表明相对坐标事件值包括X坐标和Y坐标input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);//keybit表明除了左键、右键和中键,还支持其他按键input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |BIT_MASK(BTN_EXTRA);//relbit表明除了X坐标和Y坐标,还支持中键滚轮的滚动值input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);input_set_drvdata(input_dev, mouse);//将mouse设置为input的私有数据input_dev->open = usb_mouse_open; //input设备的openinput_dev->close = usb_mouse_close;//提交urb和中断服务程序usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data,(maxp > 8 ? 8 : maxp),usb_mouse_irq, mouse, endpoint->bInterval);mouse->irq->transfer_dma = mouse->data_dma;mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;/使用transfer_dmaerror = input_register_device(mouse->dev);//注册input设备if (error)goto fail3;usb_set_intfdata(intf, mouse);return 0;fail3:	usb_free_urb(mouse->irq);
fail2:	usb_free_coherent(dev, 8, mouse->data, mouse->data_dma);
fail1:	input_free_device(input_dev);kfree(mouse);return error;
}

        根据USB数据处理流程,当处理完毕后,USB核心会通知USB设备驱动程序,这里我们是响应中断服务程序,这就相当于该URB的回调函数。我们在提交urb时候定义了中断服务程序usb_mouse_irq

static void usb_mouse_irq(struct urb *urb)
{struct usb_mouse *mouse = urb->context;signed char *data = mouse->data;struct input_dev *dev = mouse->dev;int status;switch (urb->status) {case 0:			/* success */break;case -ECONNRESET:	/* unlink */case -ENOENT:case -ESHUTDOWN:return;/* -EPIPE:  should clear the halt */default:		/* error */goto resubmit;}input_report_key(dev, BTN_LEFT,   data[0] & 0x01);//鼠标左键input_report_key(dev, BTN_RIGHT,  data[0] & 0x02);input_report_key(dev, BTN_MIDDLE, data[0] & 0x04);input_report_key(dev, BTN_SIDE,   data[0] & 0x08);input_report_key(dev, BTN_EXTRA,  data[0] & 0x10);input_report_rel(dev, REL_X,     data[1]);input_report_rel(dev, REL_Y,     data[2]);input_report_rel(dev, REL_WHEEL, data[3]);input_sync(dev);
resubmit:status = usb_submit_urb (urb, GFP_ATOMIC);//提交urb,等待下次响应if (status)dev_err(&mouse->usbdev->dev,"can't resubmit intr, %s-%s/input0, status %d\n",mouse->usbdev->bus->bus_name,mouse->usbdev->devpath, status);
}


http://www.ppmy.cn/news/211222.html

相关文章

鼠标驱动有什么用?

我们知道电脑硬件方面显卡有驱动,网卡也有驱动,声卡也有驱动,那么还有什么有驱动呢?其中鼠标也是有驱动程序的。我们知道驱动程序时让计算机用来识别硬件的。那么鼠标的驱动同样也是让计算机来识别的。那么鼠标驱动有什么用呢。这…

Linux USB驱动-鼠标驱动

1.概述 通用串行总线(USB)用于连接主机和外围设备。USB总线采用拓扑结构,USB主机和USB设备的连接构成了一颗树,树的结点为USB节点或USB集线器(HUB),USB集线器(HUB)用于扩…

LInux usb mouse(鼠标)驱动分析

linux 下usb 鼠标的驱动基本上属于USB 协议中HID 设备的中断通信的应用。代码vendor\mstar\kernel\linaro\drivers\hid\usbhid\usbmouse.c,下面一起学习usb 鼠标驱动,usb 键盘vendor\mstar\kernel\linaro\drivers\hid\usbhid\usbkbd.c 后续在学习。 USB…

USB鼠标按键驱动

怎么写USB驱动: 1. 分配/设置usb_driver结构体 /* 1. 分配/设置usb_driver结构体 */ static struct usb_driver usbmouse_as_key_driver {.name "usbmouse_as_key",.probe usbmouse_as_key_probe,.disconnect usbmouse_as_key_disconnect,.id_tab…

USB驱动--USB鼠标

其实光看USB鼠标的驱动,不知道USB插到开发板上发生了什么事,感觉还是没有掌握。 一、USB插到开发板上发生了什么: 在linx 系统中,usb热插拔由两部分方面共同实现,即内核空间和用户空间,内核由一个守护进程…

usb hid驱动 - usb鼠标

usb鼠标符合usb hid协议, 一般是单一功能(即一个usb 接口) 该接口下有一个默认的双向控制端点, 以及1个中断 in端点 bulk in端点读取数据定义: (具体定义需参考hid report描述符, https://eleccelerator.com/tutorial-about-usb-hid-report-descriptors/) 通常大部分usb鼠标…

USB-HID鼠标键盘驱动

先说结果: 本章驱动,实现了一个USB slave接口模拟出鼠标、键盘设备。在windows10上验证通过。 可以通过本章配套的测试程序,可以完成任意位置的鼠标移动,左击、右击等操作。 键盘的测试程序没有写完,只写了部分案件。就没有贴上来。 下面的代码是在tiny4412开发板上面验…

雷柏MT750S鼠标使用总结(驱动|连接|模式|续航)

【什么值得买 摘要频道】下列精选内容摘自于《无线办公好帮手 雷柏MT750S无线蓝牙鼠标体验》的片段: 驱动 雷柏MT750S的驱动软件界面比较简单,因为没有灯光的原因,软件主要是鼠标按键功能的设置,在左侧显示了各种功能&#xff0c…