USB提供了一套自顶向下的识别方法,从hub_event出发,检查是否真的有端口发生了改变,如果坐实是port被触发了,则进入port_event。

port_event()

先去获取hub的状态

if (hub_port_status(hub, port1, &portstatus, &portchange) < 0)return;

最终也是调用get_port_stats()函数去获得想要的状态,hub也是一类usb设备,

static int get_port_status(struct usb_device *hdev, int port1,void *data, u16 value, u16 length)
{int i, status = -ETIMEDOUT;for (i = 0; i < USB_STS_RETRIES &&(status == -ETIMEDOUT || status == -EPIPE); i++) {status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, value,port1, data, length, USB_STS_TIMEOUT);}return status;
}

根据spec对于port状态的请求

状态字段的定于

驱动也有相同的宏定义:

/** wPortChange bit field* See USB 2.0 spec Table 11-22 and USB 2.0 LPM ECN Table-4.10* Bits 0 to 5 shown, bits 6 to 15 are reserved*/
#define USB_PORT_STAT_C_CONNECTION  0x0001
#define USB_PORT_STAT_C_ENABLE      0x0002
#define USB_PORT_STAT_C_SUSPEND     0x0004
#define USB_PORT_STAT_C_OVERCURRENT 0x0008
#define USB_PORT_STAT_C_RESET       0x0010
#define USB_PORT_STAT_C_L1          0x0020
/*
122   * wPortStatus bit field
123   * See USB 2.0 spec Table 11-21
124   */
125  #define USB_PORT_STAT_CONNECTION   0x0001
126  #define USB_PORT_STAT_ENABLE       0x0002
127  #define USB_PORT_STAT_SUSPEND      0x0004
128  #define USB_PORT_STAT_OVERCURRENT  0x0008
129  #define USB_PORT_STAT_RESET        0x0010
130  #define USB_PORT_STAT_L1       0x0020
131  /* bits 6 to 7 are reserved */
132  #define USB_PORT_STAT_POWER        0x0100
133  #define USB_PORT_STAT_LOW_SPEED        0x0200
134  #define USB_PORT_STAT_HIGH_SPEED        0x0400
135  #define USB_PORT_STAT_TEST              0x0800
136  #define USB_PORT_STAT_INDICATOR         0x1000

然后引发了一串 if 判断...

 if (portchange & USB_PORT_STAT_C_CONNECTION) {               //有新设备接入?usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION);connect_change = 1;}if (portchange & USB_PORT_STAT_C_ENABLE) {              //hub上port是否使能?if (!connect_change)dev_dbg(&port_dev->dev, "enable change, status %08x\n",portstatus);usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE);/** EM interference sometimes causes badly shielded USB devices* to be shutdown by the hub, this hack enables them again.* Works at least with mouse driver.*/if (!(portstatus & USB_PORT_STAT_ENABLE)&& !connect_change && udev) {dev_err(&port_dev->dev, "disabled by hub (EMI?), re-enabling...\n");connect_change = 1;}}if (portchange & USB_PORT_STAT_C_OVERCURRENT) {   //过电流?u16 status = 0, unused;dev_dbg(&port_dev->dev, "over-current change\n");usb_clear_port_feature(hdev, port1,USB_PORT_FEAT_C_OVER_CURRENT);msleep(100);    /* Cool down */hub_power_on(hub, true);hub_port_status(hub, port1, &status, &unused);if (status & USB_PORT_STAT_OVERCURRENT)dev_err(&port_dev->dev, "over-current condition\n");}if (portchange & USB_PORT_STAT_C_RESET) {  //重启?dev_dbg(&port_dev->dev, "reset change\n");usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_RESET);}if ((portchange & USB_PORT_STAT_C_BH_RESET)     //以下是usb3.0相关的状态&& hub_is_superspeed(hdev)) {dev_dbg(&port_dev->dev, "warm reset change\n");usb_clear_port_feature(hdev, port1,USB_PORT_FEAT_C_BH_PORT_RESET);}if (portchange & USB_PORT_STAT_C_LINK_STATE) {dev_dbg(&port_dev->dev, "link state change\n");usb_clear_port_feature(hdev, port1,USB_PORT_FEAT_C_PORT_LINK_STATE);}if (portchange & USB_PORT_STAT_C_CONFIG_ERROR) {dev_warn(&port_dev->dev, "config error\n");usb_clear_port_feature(hdev, port1,USB_PORT_FEAT_C_PORT_CONFIG_ERROR);}

connect_change 标志,用来标志着是不是真的有端口改变了。如果真的改变了,需要处理调用hub_port_connect_change()函数。

if (connect_change)hub_port_connect_change(hub, port1, portstatus, portchange);

总结一下,在那些情况下会使得 connect_change 标志位 为1?

答:1. 端口对应的hub->change_bits 被置1

2.有设备接入的时候

3. 远程唤醒hub端口

port_event() 函数都干了些啥?

答:判定hub的port发生了什么(设备接入、唤醒...),做出相应的响应。

hub_port_connect_change()

函数原型:

/* Handle physical or logical connection change events.* This routine is called when:*   a port connection-change occurs;*   a port enable-change occurs (often caused by EMI);* usb_reset_and_verify_device() encounters changed descriptors (as from*      a firmware download)* caller already locked the hub*/
static void hub_port_connect_change(struct usb_hub *hub, int port1,u16 portstatus, u16 portchange)__must_hold(&port_dev->status_lock)

功能:响应物理层或者逻辑层的port改变

适用于: 端口连接情况发生改变;端口使能情况发生改变等

若hub有指示灯,则开始工作

if (hub->has_indicators) {set_port_led(hub, port1, HUB_LED_AUTO);hub->indicator[port1-1] = INDICATOR_AUTO;}

如支持otg功能,设置标志位

#ifdef   CONFIG_USB_OTG/* during HNP, don't repeat the debounce */if (hub->hdev->bus->is_b_host)portchange &= ~(USB_PORT_STAT_C_CONNECTION |USB_PORT_STAT_C_ENABLE);
#endif

检查端口设备是不是已连接需要被唤醒

 if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&udev->state != USB_STATE_NOTATTACHED) {if (portstatus & USB_PORT_STAT_ENABLE) {status = 0;       /* Nothing to do */
#ifdef CONFIG_PM} else if (udev->state == USB_STATE_SUSPENDED &&udev->persist_enabled) {/* For a suspended device, treat this as a* remote wakeup event.*/usb_unlock_port(port_dev);status = usb_remote_wakeup(udev);usb_lock_port(port_dev);
#endif} else {/* Don't resuscitate */;}}clear_bit(port1, hub->change_bits);/* successfully revalidated the connection */if (status == 0)return;

如果之前没有不是只需要唤醒,就进入连接处理

 usb_unlock_port(port_dev);hub_port_connect(hub, port1, portstatus, portchange);usb_lock_port(port_dev);

hub_port_connect 函数接着处理连接相关事务。

USB 设备驱动之设备接入梳理(二)相关推荐

  1. 【Linux开发】linux设备驱动归纳总结(十二):简单的数码相框

    linux设备驱动归纳总结(十二):简单的数码相框 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  2. 字符设备驱动、平台设备驱动、设备驱动模型、sysfs的比较和关联

    参考原文:https://www.kancloud.cn/yueqian_scut/emlinux/106829 对原文笔误地方做了修改.重新排版 目录 字符设备驱动.平台设备驱动.设备驱动模型.sy ...

  3. Linux设备驱动和设备匹配过程

    Linux设备驱动和设备匹配过程 1. 设备驱动匹配简述 2. 重点结构体介绍 2.1 `struct device` 2.2 `struct platform_device` 2.3 `struct ...

  4. LINUX设备驱动之设备模型一--kobject

    http://blog.csdn.net/yangzhu1982/article/details/6186016 Linux设备驱动之设备模型一kobject Eric Fang  2010-01-1 ...

  5. 【驱动】linux设备驱动·字符设备驱动开发

    Preface 前面对linux设备驱动的相应知识点进行了总结,现在进入实践阶段! <linux设备驱动入门篇>:http://infohacker.blog.51cto.com/6751 ...

  6. linux设备驱动--字符设备模型

    linux设备驱动--字符设备模型 最近正在学习设备驱动开发,因此打算写一个系列博客,即是对自己学习的一个总结,也是对自己的一个督促,有不对,不足,需要改正的地方还望大家指出,而且希望结识志同道合的朋 ...

  7. LINUX设备驱动之设备模型一kobject

    LINUX设备驱动之设备模型一kobject -------------------------------------------------------------- 转载请注明出处:http:/ ...

  8. linux设备驱动归纳总结(十二):简单的数码相框

    http://blog.chinaunix.net/uid-25014876-id-116926.html 其实代码很简单,实现lcd驱动,使lcd能够显示图片,当按下按键后切换图片. 先要说明一下几 ...

  9. Linux设备驱动--块设备(二)之相关结构体

    上回最后面介绍了相关数据结构,下面再详细介绍 块设备对象结构 block_device 内核用结构block_device实例代表一个块设备对象,如:整个硬盘或特定分区.如果该结构代表一个分区,则其成 ...

  10. linux fb设备驱动,linux设备驱动归纳总结(八):1.总线、设备和驱动

    linux设备驱动归纳总结(八):1.总线.设备和驱动 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

最新文章

  1. 如何导入nod32企业版的授权文件.lic,并制作镜像服务器?
  2. Spring中@Import注解的作用和使用
  3. dedecms原理及使用
  4. 【VS开发】PCIe体系结构的组成部件
  5. IDEA云行项目提示Error: java: OutOfMemoryError
  6. python数据预处理_Python数据预处理——缺失值、重复值
  7. 【转载】石油天然气常用单位换算
  8. C++ std::unordered_map怎么用
  9. 向量机和感知机的相同和不同点_感知机(perceptron)和支持向量机(svm)是一种东西吗? 如果不是那他们的区别和关系是什么?...
  10. 添加 centos 右键 terminal
  11. JAVA编写飞机大战---分析过程及源代码(超详细超完整)
  12. 数据分析师还是算法工程师|用数据多角度解读如何选择
  13. 如何写投资项目计划书?
  14. 杂谈(1)--人生必知的78种经典效应
  15. c++标准扩展TR1
  16. YYlabelCopy
  17. RapidMiner 5.3.015源代码下载并且正确的运行
  18. C语言100题打卡—第7题
  19. 橙瓜大数据发掘好书,25个网站小说排行榜,百万人打分
  20. 交换DataFrame的两列

热门文章

  1. 右键计算机管理显示目录名称无效,电脑资源管理器的右键上下文菜单打不开的两种解决办法...
  2. python面向对象案例--买水果
  3. python pdb 安装_Python调试工具pdb使用详解
  4. Android加载/处理超大图片神器!SubsamplingScaleImageView(subsampling-scale-image-view)【系列1】
  5. 御龙在天以前服务器信息,御龙在天所有区的名字,合区前的
  6. 谷歌眼镜设计规范之UI设计原则
  7. 求方程的解(简化版)
  8. 读书笔记——《我们时代的神经症人格》
  9. 使用Python进行ADSL宽带拨号连接等操作
  10. 【python练习】打印菱形