概述
介绍USB系统框架,只关注框架部分,不涉及细节
USB设备注册过程
usb_add_hcd -> register_root_hub -> usb_new_device -> device_add(添加设备) ->
usb_device_match(驱动匹配) -> generic_probe -> usb_set_configuration -> device_add(添加接口) ->
usb_device_match(ID 匹配) -> usb接口驱动的probe
USB初始化
usb_int
usb_int初始化整个usb系统的基础部分
注册USB总线
bus_register(&usb_bus_type);
注册usbfs驱动
usb_register(&usbfs_driver);
注册usb hub驱动
usb_hub_init -> usb_register(&hub_driver)
注册通用设备驱动
usb_register_device_driver(&usb_generic_driver, THIS_MODULE)
host总线初始化
以msm ehci为例
初始化echi驱动数据结构
ehci_init_driver(&msm_hc_driver, &msm_overrides);
使用ehci_hc_driver数据结构为基础
创建hcd
1
2hcd = usb_create_hcd(&msm_hc_driver, &pdev->dev,
dev_name(&pdev->dev));
其中msm_hc_driver在上一步初始化,以ehci_hc_driver为基础
重点:hcd->self是一条usb总线
1
2
3struct usb_hcd {
struct usb_busself;/* hcd is-a bus */
......
添加hcd到系统中
usb_add_hcd(hcd, hcd->irq, IRQF_SHARED)
向usb系统中注册一条总线
usb_register_bus(&hcd->self))
创建一个USB设备,作为根hub
rhdev = usb_alloc_dev(NULL, &hcd->self, 0)
hcd->self.root_hub = rhdev
详见:usb设备创建
为该总线注册根hub
register_root_hub(hcd)
根hub注册过程
获取根hub的描述信息
usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
向usb系统中添加了一个usb设备:usb_new_device (usb_dev);
该设备是上一步创建的根hub设备struct usb_device usb_dev = hcd->self.root_hub;*
usb设备创建
usb_alloc_dev(struct usb_device parent,
struct usb_busbus, unsigned port1)
设备类型:
1
2
3
4
5
6dev->dev.bus = &usb_bus_type;
dev->dev.type = &usb_device_type;
...
if (unlikely(!parent)) {
root_hub = 1;
}
设备路径&设备名字:
根hub:很简单,路径为”0”, 名字直接是总线编号
dev->devpath[0] = ‘0’;
dev_set_name(&dev->dev, “usb%d”, bus->busnum);
普通设备
hub设备自身(父设备为根hub):路径为端口编号
snprintf(dev->devpath, sizeof dev->devpath, “%d”, port1);
普通设备(父设备为hub设备):路径为hub路径+端口编号
snprintf(dev->devpath, sizeof dev->devpath,”%s.%d”, parent->devpath, port1);
设备名字:总线编号 + 设备路径
dev_set_name(&dev->dev, “%d-%s”, bus->busnum, dev->devpath);
usb添加设备
int usb_new_device(struct usb_device *udev)
USB枚举设备
usb_enumerate_device(udev)
获取USB配置:usb_get_configuration(udev)
显示usb设备信息
announce_device(udev);
添加设备
device_add(&udev->dev)
重点:会触发probe
创建endpoint设备
usb_create_ep_devs(&udev->dev, &udev->ep0, udev)
1
2
3
4
5
6ep_dev->udev = udev;
ep_dev->dev.groups = ep_dev_groups;
ep_dev->dev.type = &usb_ep_device_type;
ep_dev->dev.parent = parent;
dev_set_name(&ep_dev->dev, "ep_%02x", endpoint->desc.bEndpointAddress);
device_register(&ep_dev->dev);
usb probe过程查找驱动
usb_device_match
usb设备probe:generic_probe
选择配置:usb_choose_configuration
设置配置:usb_set_configuration (重点)
usb接口probe:
配置id表:usb驱动的id_tableusb_match_id(intf, usb_drv->id_table)动态匹配(非常有用)
usb 动态匹配表
usb probe过程中,优先使用静态表(代码中写死,编译后不可更改),如果静态表中没有当前设备(usb 接口)则使用动态表
动态表由应用层写入
路径:/sys/bus/usb/driver//new_id
格式:\[InterfaceClass [refVendor refProduct]]
usb 设置配置
usb_set_configuration
遍历当前配置的接口(通过usb_get_configuration从usb设备获取)
1
2
3
4
5intf->dev.bus = &usb_bus_type;
intf->dev.type = &usb_if_device_type;
dev_set_name(&intf->dev, "%d-%s:%d.%d",
dev->bus->busnum, dev->devpath,
configuration, alt->desc.bInterfaceNumber);
遍历当前配置的接口
添加接口:device_add(&intf->dev)
重点:会触发probe
hub初始化过程添加usb接口时(device_add)触发probe,如果接口是hub,则执行hub_probe
hub的匹配表:USB_CLASS_HUB=91
2
3
4
5
6
7
8
9
10
11
12static const struct usb_device_id hub_id_table[] = {
{ .match_flags = USB_DEVICE_ID_MATCH_VENDOR //指定产商的hub
| USB_DEVICE_ID_MATCH_INT_CLASS,
.idVendor = USB_VENDOR_GENESYS_LOGIC,
.bInterfaceClass = USB_CLASS_HUB,
.driver_info = HUB_QUIRK_CHECK_PORT_AUTOSUSPEND},
{ .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS, //设备为hub
.bDeviceClass = USB_CLASS_HUB},
{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, //接口为hub
.bInterfaceClass = USB_CLASS_HUB},
{ }/* Terminating entry */
};
hub_probe
新建1个hub,配置hub(重点)
1
2
3
4
5hub = kzalloc(sizeof(*hub), GFP_KERNEL)
...
INIT_WORK(&hub->events, hub_event);
usb_set_intfdata (intf, hub);
hub_configure(hub, endpoint)
hub_event是重点
配置hub
hub_configure(struct usb_hub hub, struct usb_endpoint_descriptorendpoint)
获取hub的描述
get_hub_descriptor(hdev, hub->descriptor)
获取hub设备的状态
usb_get_status(hdev, USB_RECIP_DEVICE, 0, &hubstatus)
获取hub的状态
hub_hub_status(hub, &hubstatus, &hubchange)
get_hub_status(hub->hdev, &hub->status->hub)
创建端口设备
1
2
3
4
5
6
7
8for (i = 0; i < maxchild; i++) {
ret = usb_hub_create_port_device(hub, i + 1);
if (ret < 0) {
dev_err(hub->intfdev,
"couldn't create port%d device.n", i + 1);
break;
}
}
1
2
3
4
5
6port_dev->dev.groups = port_dev_group;
port_dev->dev.type = &usb_port_device_type;
port_dev->dev.driver = &usb_port_driver;
dev_set_name(&port_dev->dev, "%s-port%d", dev_name(&hub->hdev->dev),
port1);
retval = device_register(&port_dev->dev);
创建的端口在/sys/bus/usb/device/下可见
hub事件处理
hub_event
处理hub下每个端口的事件
1
2
3
4for (i = 1; i <= hdev->maxchild; i++) {
...
port_event(hub, i);
}
port_event
获取端口状态:hub_port_status(hub, port1, &portstatus, &portchange)
端口连接事件发生变化时,执行hub_port_connect_change
hub端口连接事件
hub_port_connect_change->hub_port_connect
端口下有设备,则先移除
1
2
3
4
5if (udev) {
if (hcd->usb_phy && !hdev->parent)
usb_phy_notify_disconnect(hcd->usb_phy, udev->speed);
usb_disconnect(&port_dev->child);
}
创建一个usb设备
udev = usb_alloc_dev(hdev, hdev->bus, port1)
初始化hub port
hub_port_init(hub, udev, port1, i);
获取设备描述:usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE)
添加usb设备
status = usb_new_device(udev);
最后
以上就是跳跃跳跳糖为你收集整理的linux usb host,linux USB host驱动的全部内容,希望文章能够帮你解决linux usb host,linux USB host驱动所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复