1、ARM-Linux下USB驱动程序开发
1.1.1、linux下USB配置:
*********(MassStorage:存储设备)************************************
-> Device Drivers
-> SCSI device support(通用设备)
-> SCSI disk support (磁盘支持)
-> SCSI device support(设备支持)
-> Device Drivers
-> USB support (USB设备)
-> USB device filesystem (USB设备文件系统)
-> OHCI HCD support (主要是非PC上的USB芯片)
-> USB Mass Storage support(USB大容量设备)
-> USB Monitor (USB 主设备)
-> File systems
-> DOS/FAT/NT Filesystems
-> MSDOS fs support
-> VFAT (Windows-95) fs support
-> Partition Types (分区类型)
-> PC BIOS (MSDOS partition tables) support
-> Native Language Suppor (本地语言设置)
-> Simplified Chinese charset (CP936, GB2312)
-> NLS UTF-8
make uImage (生成uImage)
测试 mount /dev/sda1 /mnt/
*********(HID:人机接口(鼠标、键盘))********************************
-> Device Drivers
HID Devices --->
-> USB Human Interface Device (full HID) support
USB support --->
-> Support for Host-side USB
make uImage (生成uImage)
测试 cat /dev/mouse1
*********(RNDIS:网卡)********************************
-> Device Drivers x
-> USB support x
-> USB Gadget Support
[*] RNDIS support (EXPERIMENTAL) (NEW)
编译内核模块
cp drivers/usb/gadget/_ether.ko /work/nfs_root/first_fs/
cp /arch/arm/boot/uImage /work/nfs_root/new_uImage
*********(CDC-ACM:USB虚拟串口)********************************
(未能识别USB driver)可能是没有配置USB设备
1.2.1、驱动程序编写
struct usb_driver {
const char *name; /*USB驱动名字*/
int (*probe) (struct usb_interface *intf,const struct usb_device_id *id);/*USB core发现该驱动程序能够处理USB接口时,调用*/
void (*disconnect) (struct usb_interface *intf);/*USB移除的时候调用*/
const struct usb_device_id *id_table; /*该驱动程序支持哪些设备 idVendor(制造商ID) idProduct(产品id)*/
};
1.2.2、linux提供宏来定义 一种 设备 :
USB_DEVICE(vend,prod)
vend:USB Vendor ID 制造商ID
prod:USB Product ID 设备ID
1.2.3、linux提供宏来定义 一类 设备 :
USB_INTERFACE_INFO(cl,sc,pr)
cl:类 blnterfaceClass Value
sc:子类 blnterfaceSubClass value
pr:协议 blnterfaceProtocil Value
1.2.4、USB注册:传入一个参数usb_driver
static inline int usb_register(struct usb_driver *driver)
1.2.5、usb_device结构
int devnum; /* Address on USB bus */
char devpath [16]; /* Use in messages: /port/port/... */
enum usb_device_state state; /* configured, not attached, etc */
enum usb_device_speed speed; /* high/full/low (or error) */
struct usb_device_descriptor descriptor; /* Descriptor 设备描述符号*/
struct usb_host_config *config; /* All of the configs */
struct usb_config_descriptor desc; /*usb配置描述符*/
struct usb_interface *interface[USB_MAXINTERFACES];
ruct usb_host_interface *cur_altsetting; /* the currently
/*USB 接口描述符 一个[配置]包含一个或者多个接口,一个接口包含一个或者多个[设置] */
struct usb_interface_descriptor desc;
struct usb_host_endpoint *endpoint; /*USB端点*/
struct usb_endpoint_descriptor desc;/*USB 端点描述符 */
1.3.1、URB(usb request block)请求块 ,承载USB之间的数据传输
①URB处理流程:
1、USB设备驱动程序创建并初始化一个访问特点USB设备指定的端点的URB,并提交给USB Core
2、USB core提交该URB到USB主控制驱动程序
3、USB主控制器驱动程序根据该URB的描述信息,来访问USB设备
4、当访问设备结束后,USB主控制器驱动程序通知USB设备驱动(device)程序
②创建urb的函数为:
struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
参数1:iso_packets:urb所含的等时数据包个数
参数2:mem_flags:内存分配标示
③初始化urb函数为:interrupt
static inline void usb_fill_int_urb (
struct urb *urb, //要初始化urb指针
struct usb_device *dev, //usb_device设备
unsigned int pipe, //要访问的端点所对应的管道,使用usb_sndintpipe()/usb_rcvintpipe()
void *transfer_buffer, //要传输数据的缓冲区
int buffer_length, //要传输数据的长度
usb_complete_t complete_fn, //当完成urb所请求的操作时候调用的回调函数
void *context, //通常取值为DEV
int interval //URB被调度的时间间隔
);
问:何为管道?
答:管道:驱动程序的数据缓冲区与一个端点的连接,代表一个在两者之间要移动数据的能力。
批量urb:使用usb_fill_bulk_urb()
控制urb: 使用usb_control_urb()
等时urb没有像中断、控制、批量传输那样有URB初始化函数,我们只有手动初始化urb.
④提交URB
在完成urb的创建和初始化后,URB就可以通过usb_smbmit_urb函数来提交给usb core
int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
urb:指向URB的指针
mem_flags:内存分配标示,用于告知USB core如何分配内存换成区。
⑤URB处理 以下三种情况被认为URB处理完成,调用complete_fn函数
1、URB成功发送给设备,并且设备返回正确,URB->status = 0
2、如果接收和发送发生错误时候 urb->status = error
3、urb被取消,就发生在驱动程序通过,usb_unlink_urb() / usb_kill_urb()
鼠标驱动程序:
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12
13
14 /*创建输入设备*/
15 static struct input_dev *uk_dev;
16 static int len;
17 static char *usb_buf;
18 static dma_addr_t usb_data_dma;
19 static struct urb *uk_urb;
20
21
22
23
24 //usb支持的设备列表
25 static struct usb_device_id usbmouse_key_table [] = {
26 { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
27 USB_INTERFACE_PROTOCOL_MOUSE) },
28 //{USB_DEVICE(0x1234,0x5678)},
29 { } /* Terminating entry */
30 };
31
32 static void usb_mouse_irq(struct urb *urb)
33 {
34 static unsigned char pre_val;
35 #if 0
36 int i;
37 char b[100];
38 static int cnt = 0;
39 printk("data cnt %d: ", ++cnt);
40 for (i = 0; i < len; i++)
41 {
42 printk("%02x ", usb_buf[i]);
43 }
44 printk("n");
45
46
47
48 /* USB鼠标数据含义
49 * data[1]: bit0-左键, 1-按下, 0-松开
50 * bit1-右键, 1-按下, 0-松开
51 * bit2-中键, 1-按下, 0-松开
52 *
53 */
54 // if ((pre_val & (1<<0)) != (usb_buf[1] & (1<<0)))
55 // {
56 // /* 左键发生了变化 */
57 // input_event(uk_dev, EV_KEY, KEY_L, (usb_buf[1] & (1<<0)) ? 1 : 0);
58 // input_sync(uk_dev);
59 // }
60
61 // if ((pre_val & (1<<1)) != (usb_buf[1] & (1<<1)))
62 // {
63 // /* 右键发生了变化 */
64 // input_event(uk_dev, EV_KEY, KEY_S, (usb_buf[1] & (1<<1)) ? 1 : 0);
65 // input_sync(uk_dev);
66 // }
67
68 // if ((pre_val & (1<<2)) != (usb_buf[1] & (1<<2)))
69 // {
70 // /* 中键发生了变化 */
71 // input_event(uk_dev, EV_KEY, KEY_ENTER, (usb_buf[1] & (1<<2)) ? 1 : 0);
72 // input_sync(uk_dev);
73 // }
74
75 // pre_val = usb_buf[1];
76 /* 重新提交urb */
77 usb_submit_urb(uk_urb, GFP_KERNEL);
78
79 #else
80
81 switch (urb->status) {
82 case 0: /* success */
83 break;
84 case -ECONNRESET: /* unlink */
85 case -ENOENT:
86 case -ESHUTDOWN:
87 return;
88 /* -EPIPE: should clear the halt */
89 default: /* error */
90 goto resubmit;
91 }
92
93 input_report_key(uk_dev, BTN_LEFT, usb_buf[1] & 0x01);
94 input_report_key(uk_dev, BTN_RIGHT, usb_buf[1] & 0x02);
95 input_report_key(uk_dev, BTN_MIDDLE, usb_buf[1] & 0x04);
96 input_report_key(uk_dev, BTN_SIDE, usb_buf[1] & 0x08);
97 input_report_key(uk_dev, BTN_EXTRA, usb_buf[1] & 0x10);
98
99 input_report_rel(uk_dev, REL_X, usb_buf[3]);
100 input_report_rel(uk_dev, REL_Y, usb_buf[4]);
101 input_report_rel(uk_dev, REL_WHEEL, usb_buf[5]);
102
103 input_sync(uk_dev);
104 resubmit:
105 usb_submit_urb (urb, GFP_ATOMIC);
106 #endif
107
108
109
110
111 }
112
113 static int usbmouse_key_probe(struct usb_interface *intf, const struct usb_device_id *id)
114 {
115 struct usb_device *dev = interface_to_usbdev(intf);
116 struct usb_host_interface *interface;
117 struct usb_endpoint_descriptor *endpoint;
118 int pipe;
119 /*获取当前usb接口的设置*/
120 interface = intf->cur_altsetting;
121 endpoint = &interface->endpoint[0].desc;
122
123 /* a. 分配一个input_dev */
124 uk_dev = input_allocate_device();
125 /* b. 设置 */
126 /* b.1 能产生哪类事件 */
127 set_bit(EV_KEY, uk_dev->evbit);
128 set_bit(EV_REL, uk_dev->evbit);
129
130 // /* b.2 能产生这类操作里的哪些事件: L,S,ENTER,LEFTSHIT */
131 // set_bit(BTN_LEFT, uk_dev->keybit);