USB设备驱动程序的编写:
1分配一个struct 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_table = usbmouse_as_key_id_table,
};
1.1分配成员id_table
static struct usb_device_id usbmouse_as_key_id_table [] = {
{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
USB_INTERFACE_PROTOCOL_MOUSE) },
{ } /* Terminating entry */
};
usb_device_id结构体包含了设备驱动程序支持的设备。
2:注册:
入口函数里面注册:
usb_register(&usbmouse_as_key_driver);
在出口函数里面取消注册:
usb_deregister(&usbmouse_as_key_driver);
3具体函数的设置和实现:
几个usb设备概念:
端口:USB 通讯的最基本形式是通过某些称为 端点 的. 一个 USB 端点只能在一个方
向承载数据, 或者从主机到设备(称为输出端点)或者从设备到主机(称为输入端
点). 端点可看作一个单向的管道.
struct usb_endpoint_descriptor *endpoint;
接口:
USB 端点被绑在接口中. USB 接口只处理一类 USB 逻辑连接, 例如一个鼠标,
一个键盘, 或者一个音频流. 一些 USB 设备有多个接口, 例如一个 USB 扬声
器可能有 2 个接口: 一个 USB 键盘给按钮和一个 USB 音频流。
USBurb:
linux内核中的USB代码通过urb(usb请求块)和所有的usb设备通信。这个块使用struct urb来描述。
static int usbmouse_as_key_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
static dma_addr_t *buf_phys;
struct usb_host_interface *interface; //定义接口变量
struct usb_endpoint_descriptor *endpoint; //定义端点变量
struct usb_device *dev = interface_to_usbdev(intf);//根据接口信息分配一个usb_dev结构体。
interface = intf->cur_altsetting; //
endpoint = &interface->endpoint[0].desc;//接口和端口的信息填充
/*创建urb结构体*/
urb_uk = usb_alloc_urb(0, GFP_KERNEL);
/*创建一个DMA缓冲区来以最高效的方式发送数据*/
buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &buf_phys);
/*把指定的USB设备端点号设置成一个控制IN型端口*/
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
/*端口一次可以处理的最大字节数 /
len = endpoint->wMaxPacketSize;
/*初始化即将被发送到usb设备的中断端点的urb*/
usb_fill_int_urb(urb_uk, dev, pipe, buf,len,usb_mouse_as_key_irq, NULL, endpoint->bInterval);
urb_uk->transfer_dma = buf_phys; //以DMA方式传输数据到USB设备的缓冲区
urb_uk->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
/*urb被创建和初始化之后, 提交到usb核心以发送到usb设备*/
usb_submit_urb(urb_uk,GFP_KERNEL);
/*urb被成功的传输到usb设备之后,urb里面的回调函数(usb_mouse_as_key_irq)将被usb核心调用*/
}
static void usb_mouse_as_key_irq(struct urb *urb)
{
/*将usb鼠标用作按键使用, 用到输入子系统*/
int pipe;
/*1:分配一个input_dev结构体*/
input_mk = input_allocate_device();
/*2:设置*/
set_bit(EV_KEY,input_mk->evbit);
set_bit(EV_REP,input_mk->evbit);
set_bit(KEY_L,input_mk->keybit);
set_bit(KEY_S,input_mk->keybit);
set_bit(KEY_ENTER,input_mk->keybit);
/*3:注册*/
input_register_device(input_mk);
/* USB鼠标数据含义
* data[0]: bit0-左键, 1-按下, 0-松开
* bit1-右键, 1-按下, 0-松开
* bit2-中键, 1-按下, 0-松开
*
*/
static unsigned char pre_val;
if ((pre_val & (1<<0)) != (buf[0] & (1 << 0)))
{
input_event(input_mk, EV_KEY, KEY_L,(buf[0] & (1 << 0) ? 1 : 0));
input_sync(input_mk);
}
else if ((pre_val & (1<<1)) != (buf[0] & (1 << 1)))
{
input_event(input_mk, EV_KEY, KEY_S,(buf[0] & (1 << 1) ? 1 : 0));
input_sync(input_mk);
}
else if ((pre_val & (1<<2)) != (buf[0] & (1 << 2)))
{
input_event(input_mk, EV_KEY, KEY_ENTER,(buf[0] & (1 << 2) ? 1 : 0));
input_sync(input_mk);
}
pre_val = buf[0];
/*再次提交*/
usb_submit_urb(urb_uk,GFP_KERNEL);
}
static void usbmouse_as_key_disconnect(struct usb_interface *intf)
{
struct usb_device *dev = interface_to_usbdev(intf);
usb_free_urb(buf);
usb_kill_urb(buf);
usb_buffer_free(dev,len, buf, buf_phys);
input_unregister_device(input_mk);
input_free_device(input_mk);
}
1分配一个struct 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_table = usbmouse_as_key_id_table,
};
1.1分配成员id_table
static struct usb_device_id usbmouse_as_key_id_table [] = {
{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
USB_INTERFACE_PROTOCOL_MOUSE) },
{ } /* Terminating entry */
};
usb_device_id结构体包含了设备驱动程序支持的设备。
2:注册:
入口函数里面注册:
usb_register(&usbmouse_as_key_driver);
在出口函数里面取消注册:
usb_deregister(&usbmouse_as_key_driver);
3具体函数的设置和实现:
几个usb设备概念:
端口:USB 通讯的最基本形式是通过某些称为 端点 的. 一个 USB 端点只能在一个方
向承载数据, 或者从主机到设备(称为输出端点)或者从设备到主机(称为输入端
点). 端点可看作一个单向的管道.
struct usb_endpoint_descriptor *endpoint;
接口:
USB 端点被绑在接口中. USB 接口只处理一类 USB 逻辑连接, 例如一个鼠标,
一个键盘, 或者一个音频流. 一些 USB 设备有多个接口, 例如一个 USB 扬声
器可能有 2 个接口: 一个 USB 键盘给按钮和一个 USB 音频流。
USBurb:
linux内核中的USB代码通过urb(usb请求块)和所有的usb设备通信。这个块使用struct urb来描述。
static int usbmouse_as_key_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
static dma_addr_t *buf_phys;
struct usb_host_interface *interface; //定义接口变量
struct usb_endpoint_descriptor *endpoint; //定义端点变量
struct usb_device *dev = interface_to_usbdev(intf);//根据接口信息分配一个usb_dev结构体。
interface = intf->cur_altsetting; //
endpoint = &interface->endpoint[0].desc;//接口和端口的信息填充
/*创建urb结构体*/
urb_uk = usb_alloc_urb(0, GFP_KERNEL);
/*创建一个DMA缓冲区来以最高效的方式发送数据*/
buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &buf_phys);
/*把指定的USB设备端点号设置成一个控制IN型端口*/
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
/*端口一次可以处理的最大字节数 /
len = endpoint->wMaxPacketSize;
/*初始化即将被发送到usb设备的中断端点的urb*/
usb_fill_int_urb(urb_uk, dev, pipe, buf,len,usb_mouse_as_key_irq, NULL, endpoint->bInterval);
urb_uk->transfer_dma = buf_phys; //以DMA方式传输数据到USB设备的缓冲区
urb_uk->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
/*urb被创建和初始化之后, 提交到usb核心以发送到usb设备*/
usb_submit_urb(urb_uk,GFP_KERNEL);
/*urb被成功的传输到usb设备之后,urb里面的回调函数(usb_mouse_as_key_irq)将被usb核心调用*/
}
static void usb_mouse_as_key_irq(struct urb *urb)
{
/*将usb鼠标用作按键使用, 用到输入子系统*/
int pipe;
/*1:分配一个input_dev结构体*/
input_mk = input_allocate_device();
/*2:设置*/
set_bit(EV_KEY,input_mk->evbit);
set_bit(EV_REP,input_mk->evbit);
set_bit(KEY_L,input_mk->keybit);
set_bit(KEY_S,input_mk->keybit);
set_bit(KEY_ENTER,input_mk->keybit);
/*3:注册*/
input_register_device(input_mk);
/* USB鼠标数据含义
* data[0]: bit0-左键, 1-按下, 0-松开
* bit1-右键, 1-按下, 0-松开
* bit2-中键, 1-按下, 0-松开
*
*/
static unsigned char pre_val;
if ((pre_val & (1<<0)) != (buf[0] & (1 << 0)))
{
input_event(input_mk, EV_KEY, KEY_L,(buf[0] & (1 << 0) ? 1 : 0));
input_sync(input_mk);
}
else if ((pre_val & (1<<1)) != (buf[0] & (1 << 1)))
{
input_event(input_mk, EV_KEY, KEY_S,(buf[0] & (1 << 1) ? 1 : 0));
input_sync(input_mk);
}
else if ((pre_val & (1<<2)) != (buf[0] & (1 << 2)))
{
input_event(input_mk, EV_KEY, KEY_ENTER,(buf[0] & (1 << 2) ? 1 : 0));
input_sync(input_mk);
}
pre_val = buf[0];
/*再次提交*/
usb_submit_urb(urb_uk,GFP_KERNEL);
}
static void usbmouse_as_key_disconnect(struct usb_interface *intf)
{
struct usb_device *dev = interface_to_usbdev(intf);
usb_free_urb(buf);
usb_kill_urb(buf);
usb_buffer_free(dev,len, buf, buf_phys);
input_unregister_device(input_mk);
input_free_device(input_mk);
}