USB驱动(一、概念介绍及USB总线驱动程序代码分析)
USB驱动程序分为两个层次
(1) USB总线驱动=》系统自带的;
USB总线驱动程序负责:
识别USB设备,给USB设备找到对应的驱动程序。
USB总线驱动程序作用:
a.识别USB设备;
b.查找并安装对应的设备驱动程序;
c.提供USB读写函数。不了解数据含义。
USB总线驱动程序可以通过调用libUSB(libUSB封装了端口函数)跳过USB设备驱动程序,来访问USB设备。
(2) 设备驱动=》需要我们自己编写;
设备驱动知道数据含义。
PC和USB设备都遵守一定的规范。
USB设备接入电脑后,USB总线驱动程序会发出某些命令来获取设备信息(描述符);
USB设备必须返回“描述符”给PC。
USB接口只有4条线:5V,GND,D+,D-。
每一个USB设备接入PC时,USB总线驱动程序都会给他分配一个编号;
接在USB总线上的每一个USB设备都有自己的编号(地址);
PC机想访问某个USB设备时,发出的命令都含有对应的编号(地址)。
新接入的USB 设备的默认编号是0,在未分配新编号前,PC使用0编号和它通信。
为了快速识别硬件,在USB主机上的D+和D-一般都会接15k的下拉电阻,而在USB从机上的D+和D-都会接1.5K的上拉电阻。
USB主机控制器,USB总线驱动程序是来支持USB主机控制器,也可以看做是USB总线驱动程序是USB主机控制器驱动程序,USB主机控制器下接有USB设备,设备驱动程序用来支持USB设备,为了能够访问USB设备,设备驱动程序必须调用USB总线驱动程序提供的函数,把那些命令、包,发给USB主机控制器,由USB主机控制器产生的信号发给USB设备。
插入和拔出USB设备后,会看到输出信息:
usb 1-1 :new full speed USB device using s3c2410-ohci and address 2
在系统的内核中查找
USB device using (grep “USB device using” * -nR),
发现在device /usb/core/hub.c :2186:
“%s %s speed %sUSB device using %s and address %d\n”,
每一个USB主机控制器内部都自带一个USB hub,可以认为hub为特殊的USB控制器。
static void hub_irq(struct urb *urb)
{
......
kick_khubd(hub);
......
}/*主机控制器产生的中断,不是USB设备产生的中断*/
static void kick_khubd(struct usb_hub *hub)
{unsigned long flags;/* Suppress autosuspend until khubd runs */to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;spin_lock_irqsave(&hub_event_lock, flags);if (list_empty(&hub->event_list)) {list_add_tail(&hub->event_list, &hub_event_list);wake_up(&khubd_wait);/*唤醒队列*/}spin_unlock_irqrestore(&hub_event_lock, flags);
}
static int hub_thread(void *__unused)
{do {hub_events();wait_event_interruptible(khubd_wait,!list_empty(&hub_event_list) ||kthread_should_stop());/*hub 线程一般是在这个队列里面休眠,*/try_to_freeze();} while (!kthread_should_stop() || !list_empty(&hub_event_list));pr_debug("%s: khubd exiting\n", usbcore_name);return 0;
}
static void hub_events(void)
.......
if (connect_change)hub_port_connect_change(hub, i,portstatus, portchange);........
static void hub_port_connect_change(struct usb_hub *hub, int port1,u16 portstatus, u16 portchange)
{
......
udev = usb_alloc_dev(hdev, hdev->bus, port1);
......
/* set the address */choose_address(udev);/*给新设备分配地址*/
......
status = hub_port_init(hub, udev, port1, i);
......
status = usb_new_device(udev);
......
}
在linux/device/usb/core/Usb.c下
usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
{
......
dev->dev.bus = &usb_bus_type;
......
}
在F:\linux-2.6.22.6\drivers\usb\core\driver.c下
struct bus_type usb_bus_type = {.name = "usb",.match = usb_device_match,.uevent = usb_uevent,.suspend = usb_suspend,.resume = usb_resume,
};
在F:\linux-2.6.22.6\drivers\usb\core\driver.c下
static int usb_device_match(struct device *dev, struct device_driver *drv)
{
.......
id = usb_match_dynamic_id(intf, usb_drv);
/*在usb_driver里面会有一个probe函数*/.......
}
hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,int retry_counter){.....dev_info (&udev->dev,"%s %s speed %sUSB device using %s and address %d\n",(udev->config) ? "reset" : "new", speed, type,udev->bus->controller->driver->name, udev->devnum);
......
retval = hub_set_address(udev);/*把编号(或地址)告诉给USB设备*/
......
retval = usb_get_device_descriptor(udev, 8);
/*获取设备描述符,此时获得的是8个字节的,linux/include/linux/usb/ch9.h下usb_device_descriptor结构体中 */
......retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
......}
在linux/include/linux/usb/ch9.h下
/* USB_DT_DEVICE: Device descriptor */
struct usb_device_descriptor {__u8 bLength;__u8 bDescriptorType;__le16 bcdUSB;__u8 bDeviceClass;__u8 bDeviceSubClass;__u8 bDeviceProtocol;__u8 bMaxPacketSize0;__le16 idVendor;__le16 idProduct;__le16 bcdDevice;__u8 iManufacturer;__u8 iProduct;__u8 iSerialNumber;__u8 bNumConfigurations;
} __attribute__ ((packed));
int usb_new_device(struct usb_device *udev)
{
......
err = usb_get_configuration(udev);/*把所有的配置读取出来并解析*/
......
err = device_add(&udev->dev);
......
}
在linux/device/usb/core/Config.c下
int usb_get_configuration(struct usb_device *dev)
{
......
result = usb_parse_configuration(&dev->dev, cfgno,&dev->config[cfgno], bigbuffer, length);/*解析配置信息*/.......
}