UHCI | 低速/全速 |
OHCI | 低速/全速 |
EHCI | 高速(480Mbps) |
端点(endpoint):USB设备的通信是通过端点进行的,除了端点0之外每个端点只有读或者写的能力。端点类似于TCP/IP协议的端口号。
中断传输并不是真的中断,而是主机不断的进行查询
中断传输 | 鼠标 |
批量传输 | U盘 |
实时传输 | USB摄像头 |
控制传输 | USB设备的识别过程 |
static struct usb_driver usb2key_driver = { .name = "usb2key", //名字 .probe = usb2key_probe, //成功匹配时执行 .disconnect = usb2key_disconnect, //移除的时候执行,对应平台总线的.remove .id_table = usb2key_id_table, //设备标识,能支持哪些设备 };
static int usb2key_init(void) { usb_register(&usb2key_driver); return 0; } static void usb2key_exit(void) { usb_deregister(&usb2key_driver); } module_init(usb2key_init); module_exit(usb2key_exit); MODULE_LICENSE("GPL");
static int usb2key_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; int pipe, maxp; int error = -ENOMEM; /* 通过逻辑设备接口结构体获得usb_device的地址 */ usb_dev = interface_to_usbdev(intf); /* 最近活动的备选设置 */ interface = intf->cur_altsetting; /* 只有一个端点 */ if (interface->desc.bNumEndpoints != 1) return -ENODEV; /* 获取除了端点0之外的第一个端点描述符,USB鼠标没有输出端点,只有输入端点(相对于主机来说) */ endpoint = &interface->endpoint[0].desc; if (!usb_endpoint_is_int_in(endpoint)) //中断类型端点、输入端点 return -ENODEV; /* 端点地址以及最大传输包 */ pipe = usb_rcvintpipe(usb_dev, endpoint->bEndpointAddress); maxp = usb_maxpacket(usb_dev, pipe, usb_pipeout(pipe)); /* USB设备传输数据存放地址(虚拟地址) */ usb_data = usb_buffer_alloc(usb_dev, 8, GFP_ATOMIC, &usb_dma); /* USB request block:USB请求块,0表示不需要私有空间,后者表示是内核空间 */ usb2key_irq = usb_alloc_urb(0, GFP_KERNEL); usb2key_dev->name = "usb2key"; usb_to_input_id(usb_dev, &usb2key_dev->id); //输入id_table usb2key_dev->dev.parent = &intf->dev; /* 填充urb结构体:usb2key_irq-要填充的urb;pipe-端点地址; *(maxp > 8 ? 8 : maxp)-数据长度;usb2key_mouse_irq-中断处理函数; *endpoint->bInterval-查询时间间隔 */ usb_fill_int_urb(usb2key_irq, usb_dev, pipe, usb_data, (maxp > 8 ? 8 : maxp), usb2key_mouse_irq, NULL, endpoint->bInterval); usb2key_irq->transfer_dma = usb_dma; //传输数据的物理地址 usb2key_irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; //物理地址在传输时有效 usb_submit_urb(usb2key_irq, GFP_KERNEL); //提交urb到内核 return 0; } void usb2key_disconnect(struct usb_interface *intf) { input_unregister_device(usb2key_dev); usb_kill_urb(usb2key_irq); usb_free_urb(usb2key_irq); input_free_device(usb2key_dev); usb_buffer_free(usb_dev, 8, &usb_data, usb_dma); } /* 标识支持HID类(Human Interface Device),BOOT子类, MOUSE协议*/ static struct usb_device_id usb2key_id_table[] = { { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, USB_INTERFACE_PROTOCOL_MOUSE)}, { } /* 结束输入 */ };
static void usb2key_mouse_irq(struct urb *urb) { int i; /* 打印接收到的数据 */ for(i = 0; i < 8; i++) { printk("%02x\t", usb_data[i]); } /* 重新提交urb */ error = usb_submit_urb(usb2key_irq, GFP_ATOMIC); }
0002 0008 ffff ffff 0000 0000 0000 0000 |
鼠标下滚 |
0002 0008 0001 0000 0000 0000 0000 0000 |
上滚 |
0001 0110 0001 0000 0000 0000 0000 0000 |
左键按下 |
0001 0110 0000 0000 0000 0000 0000 0000 |
左键松开 |
在hub.c里面: usb_hub_init(void) usb_register(&hub_driver) //注册hub_driver结构体 kthread_run(hub_thread, NULL, "khubd"); //线程运行 hub_thread(void *__unused) hub_events(); hub_port_connect_change(hub, i, portstatus, portchange); udev = usb_alloc_dev(hdev, hdev->bus, port1); hub_port_init(hub, udev, port1, i); //打印 //usb 1-1: new low speed USB device using s3c2410-ohci and address 5 //usb 1-1: configuration #1 chosen from 1 choice usb_new_device(udev); usb_control_msg //询问设备 MKDEV(USB_DEVICE_MAJOR, (((udev->bus->busnum-1) * 128) + (udev->devnum-1))); //创建节点 device_add(&udev->dev); //添加设备,此时会由usb_bus_type的match函数查找到上面建立的driver进行匹配连接,并且传入设备描述 wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list) || kthread_should_stop()); //等待中断,阻塞 hub_probe(struct usb_interface *intf, const struct usb_device_id *id) hub_configure(hub, endpoint) usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq, hub, endpoint->bInterval); //构建出hub_irq hub_irq(struct urb *urb) kick_khubd(hub); wake_up(&khubd_wait); //唤醒中断
usb_register(&usb2key_driver); new_driver->drvwrap.driver.bus = &usb_bus_type; //总线类型 new_driver->drvwrap.driver.probe = usb_probe_interface; //驱动的probe函数 new_driver->drvwrap.driver.remove = usb_unbind_interface; //驱动的remove函数 new_driver->drvwrap.driver.owner = owner; //THIS_MODULE driver_register(&new_driver->drvwrap.driver); //注册driver结构体,把此结构体挂入总线的链表里面,并且总线的match函数被调用
Usb device connect! usb2key_probe(struct usb_interface *intf, const struct usb_device_id *id) usb_fill_int_urb(usb2key_irq, usb_dev, pipe, usb_data, (maxp > 8 ? 8 : maxp), usb2key_mouse_irq, NULL, endpoint->bInterval); static void usb2key_mouse_irq(struct urb *urb) //等待数据传输
usb总线:负责进行USB设备数据的处理,USB的设备结构体是在USB设备插入之后由hub总线的驱动获取USB设备信息之后才构建好的
usb总线的设备分支由hub总线的驱动构造
hub总线由编译器编译进内核,直接由内核构造