usb hub 分析(转)

在host controller初始化的时候一定会调用hub_probe进行初始化,至少对root hub初始化
hub_probe(struct usb_interface *intf, const struct usb_device_id *id) (hub.c)
此时struct usb_interface 和struct usb_device的数据已经在hc初始化的过程中得到
    -> hdev = interface_to_usbdev(intf); 
       由struct usb_interface 得到usb_device, 中间通过struct device转换,
    然后:分配struct usb_hub, 并初始化hub->event_list和hub->leds
    -> INIT_DELAYED_WORK(&hub->leds, led_work);初始化led_work工作队列
       以后调用schedule_delayed_work()来唤醒led_work, 暂时不用led
    -> usb_get_intf(intf);
    -> usb_set_intfdata (intf, hub);让struct usb_hub和struct usb_interface关联
    -> hub_configure(hub, endpoint)
        ->get_hub_descriptor(hdev, hub->descriptor,sizeof(*hub->descriptor));
          得到hub->descriptor
            -> usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
                USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
                USB_DT_HUB << 8, 0, da ta, size,
                USB_CTRL_GET_TIMEOUT);
        对tt初始化, struct usb_tt用来匹配低速设备和高速hub.tt与hub相关与OHCI/EHCI无关
        这样一个port既能支持high也能支持full/low
        -> INIT_WORK (&hub->tt.kevent, hub_tt_kevent);
            -> hub_tt_kevent()
        -> usb_set_interface(hdev, 0, 1); high speed hub
        -> usb_get_status(hdev, USB_RECIP_DEVICE, 0, &hubstatus);
            -> usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
                USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, status,
                sizeof(*status), USB_CTRL_GET_TIMEOUT);
        接着:定义每一个port的电流
        -> hub_hub_status(hub, &hubstatus, &hubchange);    
           这个请求是hub自己定义的(spec P425),将当前hub状态保存在hubstatus,已经改变的
            hub状态保存在hubchange里
            -> get_hub_status(hub->hdev, &hub->status->hub);
                ->usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
                             USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
                         da ta, sizeof(*da ta), USB_STS_TIMEOUT);
        -> usb_alloc_urb(0, GFP_KERNEL); 分配urb
            -> usb_init_urb(urb);    初始化urb
        -> usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq,
            hub, endpoint->bInterval);  填充int urb
        -> hub_power_on(hub);
            -> set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER);
                  对每一个port
        -> hub_activate(hub);
            -> usb_submit_urb(hub->urb, GFP_NOIO);
               将之前usb_fill_int_urb()的urb提交
            -> schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
               延迟LED_CYCLE_PERIOD一段时间后,调度hub->leds, 让led一闪一闪亮晶晶
            -> kick_khubd(hub);向&hub_event_list链表挂载event,并唤醒hub_thread()
                -> to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
                   由usb_hub->struct device->usb_interface,增加pm的引用计数
                   hub要使用了,就别让电源管理把它挂起来了
                -> list_add_tail(&hub->event_list, &hub_event_list);
                   如果list_empty(&hub->event_list)即第一次调用,就把当前hub->event_list
                   加入到全局hub_event_list中去
                -> wake_up(&khubd_wait);
                   唤醒休眠的hub_thread(),从wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list));                         继续向下执行,khubd_wait是wait_queue_head_t类型。hub_events()将再次被执行
    -> hub_disconnect (intf);
        -> usb_get_intfdata (intf);
           由usb_interface->struct device->usb_hub 得到usb_hub
        -> list_del_init(&hub->event_list);删除当前hub 的event_list

usb_hub_init(void) hub.c
    ->usb_register(&hub_driver) 注册hub_driver  那末怎莫把hub_driver与hub_device挂接起来呢????
    -> kthread_run(hub_thread, NULL, "khubd"); 创建并唤醒线程hub_thread
    -> usb_deregister(&hub_driver) 注销hub_driver

hub执行线程
hub_thread(void *__unused) hub.c 
    -> hub_events();
        -> list_entry(tmp, struct usb_hub, event_list); 得到那个触发hub_events()的hub (struct usb_hub)
        -> to_usb_interface(hub_dev); 再得到 struct usb_interface
        -> usb_lock_device(hdev); 通过semaphone锁住这个usb_device
        -> hub_pre_reset(intf);      如果设备状态是USB_STATE_NOTATTACHED
        -> usb_autopm_get_interface(intf); 电源管理方面,让这个usb_interface引用计数加1,以防hub自动挂起
            -> usb_autopm_do_interface(intf, 1);
        -> usb_reset_composite_device(hdev, intf); 如果hub出错,把复合设备reset,复合设备就是有多个interface的设备
            -> usb_autoresume_device(udev); 防止在reset过程中自动挂起了
            接着:针对设备中的每个interface,找到其driver (usb_driver)并调用usb_driver->pre_reset(usb_interface)
            -> usb_reset_device(udev);
            接着:针对设备中的每个interface,找到其driver (usb_driver)并调用usb_driver->post_reset(usb_interface)
            -> usb_autosuspend_device(udev);

        接着:轮询该hub的每个端口,查看是否有变化
        -> hub_port_status(hub, i, &portstatus, &portchange);    
           通过发送Get Port Status标准hub请求,得到Status Bits和Status Change Bits
           根据port变化的原因,分别判断处理
            -> get_port_status(hub->hdev, port1, &hub->status->port);
                -> usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
                    USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port1,
                    da ta, sizeof(*da ta), USB_STS_TIMEOUT);
        -> clear_port_feature(hdev, i, USB_PORT_FEAT_C_CONNECTION);     //USB_PORT_STAT_C_CONNECTION
           hub标准命令,清除USB_PORT_FEAT_C_CONNECTION这个feature, 说明已经确认这个feature了
            -> usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),    
                USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port1,
                NULL, 0, 1000);
        -> clear_port_feature(hdev, i, USB_PORT_FEAT_C_ENABLE);        //USB_PORT_STAT_C_ENABLE
        -> clear_port_feature(hdev, i, USB_PORT_FEAT_C_SUSPEND);    //USB_PORT_FEAT_C_SUSPEND
        -> remote_wakeup(hdev->    children[i-1]);
        -> hub_port_disable(hub, i, 1);    
        -> clear_port_feature(hdev, i, USB_PORT_FEAT_C_OVER_CURRENT);    //USB_PORT_STAT_C_OVERCURRENT
        -> hub_power_on(hub); 轮询hub的每一个port并设置port状态
            -> set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER); 
                -> usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
                    USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port1,
                    NULL, 0, 1000);
        -> clear_port_feature(hdev, i, USB_PORT_FEAT_C_RESET);        //USB_PORT_STAT_C_RESET
        -> hub_port_connect_change(hub, i,portstatus, portchange); 一个usb设备插入port,最终会发生的事情
        -> hub_hub_status(hub, &hubstatus, &hubchange)
        -> clear_hub_feature(hdev, C_HUB_LOCAL_POWER);        //HUB_CHANGE_LOCAL_POWER
        -> clear_hub_feature(hdev, C_HUB_OVER_CURRENT);        //HUB_CHANGE_OVERCURRENT
        -> hub_power_on(hub);
        -> usb_enable_root_hub_irq(hdev->bus); 如果是root hub
        -> usb_autopm_enable(intf);
        -> usb_unlock_device(hdev);
    -> wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list));
       只要hub_event_list不为空, 就唤醒。否则休眠,线程不会继续执行。ecos只要用“条件变量”把这个线程阻塞就行了
       当再向下执行时,hub_event_list已经不为空了
Dynamix 保留本作品所有权利. ALL RIGHTS RESERVED by DYNAMIX. 本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本设计是一款符合 USB 3.0 要求的,兼具有5V快速充电特性的一款超高速分线器。本设计从原理,布线,采购,制造均有本人亲自把关,用料考究,稳定性强。本人尊崇开源的思想,希望通过这样一个简单的设计,抛砖引玉,让国内的爱好者们在分享学习,在学习交流。这仅仅是个开始,我会在接下来的业余生活带给大家更多更好的作品。 本设计经过两次迭代实物验证,除厂商不对外开放的OTP功能外完全实现TUSB8041其余各项功能。其功能主要包括: 实现 USB 3.0 集线器功能,向下兼容 USB 2.0 链路; 实现四个USB-A 母座 下行端口和一个USB-B 母座 上行端口以最高近似 5Gbps(SuperSpeed)的速率传输数据; 设备可以通过 5.5 外径 2.5 内径 DC 电源接口供电,供电电压为 9V~14V DC,所需适配器功率不低于 45W *; 在外部电源接口插入后,设备电源将自动从上行 Vbus 端口供电切换至外部独立供电; 设备属性可以通过外部 EEPROM 修改,提供默认配置二进制文件(*.bin); 在默认配置下,上行端口连接时,四个下行端口支持 CDP,DCP 协议最高2A@5V快速充电模式; 在默认配置下,上行端口未连接时,四个下行端口支持 ACP1/2,CDP,DCP 协议最高2A@5V快速充电模式; 下行四个端口采用独立限流开关控制,当任意一个下行端口输出电流超过 2A 时,PC端将会收到下游端口过流通知并可手动复位; 主芯片TUSB8041 pin-to-pin 兼容TUSB8041A,经过验证可以实现 USB 3.1 Gen1 标准。 本设计使用 Altium Designer 绘制原理图文件和 PCB 文件。PCB 经过样品生产后,手工焊接并调试。调试测试电压,电流,时钟频率等参数,并针对限流,过流,警告,快充等特性单独测试。同时,粗略对比高速 SSD 移动硬盘在大文件传输过程直接连接 PC 与经过 HUB 连接 PC 时速度的变化,结果传输速度无明显差别**。 设计根据 PCB 样品生产材料规格,使用 Si9000 计算差分阻抗。在 Layout 过程,使用差分对工具布线,进行等长处理,使用 Shield 工具保护差分线,以获得最好的信号完整性。由于身边没有 TDR 和 VNA 等设备,无法进行详细测试。 在 PCB 文档所有器件均含有 3D 外形,方便二次开发外壳。文件附带一个简易外壳文件***。 本设计核心器件全部使用进口器件。主要芯片均选择德州仪器公司产品。该公司器件资料齐全,对独立开发者非常友好。接插件方面,选择引进较多的通用接插件。评估人员可以在要求高的场合使用进口接插件,在要求低的场合使用国产接插件,这样有利于控制成本。在测试过程,主要使用 TE,Molex,CUI 和富士康的接插件,这几个生产商器件质量较好,寿命高。对于电解电容,采用高速数字电路常用的松下POSCAP等高分子聚合物电容,提高整体电源质量。 本设计采用四层板材,顶层信号,间层地和电源,底层低速信号。极大保证了电源和信号完整性。 本设计端口均有过流保护和静电保护,保证设备安全。 在设计,参考了若干半导体生厂商关于 USB 3.0 的 Reference design ,USB 协会的 USB 3 Spec 还有一些网上版权不明晰的设计。 在本文档,主要包括整个 1.2 版本 PCB project 文件。 其,可以提取出 BOM,Gerber 等制造相关文件。后续所有文档的更新和维护将会在 Github 呈现。 Github文件地址 PCB 文件,含有板层设计文件。请根据板层厚度,挑选加工厂商。如需调整,使用 Si9000 重新计算后,更改差分对规则,对差分对重新 Layout 。 四层板打样,参考费用在200元/10片左右。 针对于高校学生,推荐在 TI.com 申请样片,本设计 TI 芯片均可申请样片****。 本设计包含相当多的冗余器件,请根据实际需求添加。 本设计只考虑到小量样品测试,并未经过产品化测试。其存在很多可制造性问题亟待解决。 本说明未尽事宜,请根据图纸自行揣摩。如有疑惑欢迎在文后跟帖或者在 Github 提问,也可以 Email 联系我 miracle.jin.tong@gmail.com 或 15918107@hdu.edu.cn 。 本设计存在的瑕疵与不足也欢迎批评指正。 *可以参考 TUSB8041 Datasheet 寄存器定义,使用烧录器调整所需功能。在关闭若干快充功能
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值