编写USB驱动程序的基本步骤如下:
定义USB驱动结构体
定义一个`struct usb_driver`结构体,包含以下成员:
`struct module *owner`:指向模块的指针,用于引用计数。
`const char *name`:驱动程序的名称。
`const struct usb_device_id *id_table`:包含驱动程序支持的所有设备ID的数组。
`int (*probe)(struct usb_interface *intf, const struct usb_device_id *id)`:探测函数,用于初始化设备并返回0(成功)或负值(失败)。
`void (*disconnect)(struct usb_interface *intf)`:断开函数,当设备被移除或驱动卸载时调用。
编写探测函数
`probe`函数在设备匹配`id_table`时被调用。需要完成以下任务:
分配并初始化`input_dev`结构体。
设置`input_dev`以支持所需的输入事件(如按键、鼠标移动等)。
注册`input_dev`结构体。
设置USB数据传输要素,包括创建urb(USB请求块)并初始化。
提交urb以开始数据传输。
编写断开函数
`disconnect`函数在设备被移除或驱动卸载时调用。需要完成以下任务:
清理并释放所有分配的资源,如input_dev结构体和urb。
注册和注销驱动
使用`usb_register()`函数注册驱动程序,并在驱动程序不再需要时调用`usb_unregister()`函数注销。
处理USB请求
根据需要实现其他USB请求处理函数,如`open`、`close`、`read`、`write`等。
```c
include include include include static struct usb_device_id skel_table[] = { { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) }, { } // 结束 }; static int skel_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct input_dev *input_dev; int ret; input_dev = input_allocate_device(INPUT_DEV_TYPE_MOUSE); if (!input_dev) { pr_err("Failed to allocate input device\n"); return -ENOMEM; } input_dev->name = "USB Mouse"; input_dev->id.bustype = BUS_USB; input_dev->id.vendor = USB_SKEL_VENDOR_ID; input_dev->id.product = USB_SKEL_PRODUCT_ID; input_dev->id.version = 1; input_set_drvdata(input_dev, intf); ret = input_register_device(input_dev); if (ret) { pr_err("Failed to register input device\n"); input_free_device(input_dev); return ret; } // 设置USB数据传输要素和urb结构体 // ... return 0; } static void skel_disconnect(struct usb_interface *intf) { struct input_dev *input_dev = input_get_drvdata(intf); if (input_dev) { input_unregister_device(input_dev); input_free_device(input_dev); } } static struct usb_driver skel_driver = { .name = "skeleton", .id_table = skel_table, .probe = skel_probe, .disconnect = skel_disconnect, }; module_usb_driver(skel_driver); ``` 这个示例展示了如何定义一个简单的USB鼠标驱动程序,包括探测和断开函数的基本结构。实际应用中,还需要根据具体的硬件设备进行更详细的初始化和资源管理。