USB 设备驱动之设备接入梳理(二)
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 设备驱动之设备接入梳理(二)相关推荐
- 【Linux开发】linux设备驱动归纳总结(十二):简单的数码相框
linux设备驱动归纳总结(十二):简单的数码相框 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
- 字符设备驱动、平台设备驱动、设备驱动模型、sysfs的比较和关联
参考原文:https://www.kancloud.cn/yueqian_scut/emlinux/106829 对原文笔误地方做了修改.重新排版 目录 字符设备驱动.平台设备驱动.设备驱动模型.sy ...
- Linux设备驱动和设备匹配过程
Linux设备驱动和设备匹配过程 1. 设备驱动匹配简述 2. 重点结构体介绍 2.1 `struct device` 2.2 `struct platform_device` 2.3 `struct ...
- LINUX设备驱动之设备模型一--kobject
http://blog.csdn.net/yangzhu1982/article/details/6186016 Linux设备驱动之设备模型一kobject Eric Fang 2010-01-1 ...
- 【驱动】linux设备驱动·字符设备驱动开发
Preface 前面对linux设备驱动的相应知识点进行了总结,现在进入实践阶段! <linux设备驱动入门篇>:http://infohacker.blog.51cto.com/6751 ...
- linux设备驱动--字符设备模型
linux设备驱动--字符设备模型 最近正在学习设备驱动开发,因此打算写一个系列博客,即是对自己学习的一个总结,也是对自己的一个督促,有不对,不足,需要改正的地方还望大家指出,而且希望结识志同道合的朋 ...
- LINUX设备驱动之设备模型一kobject
LINUX设备驱动之设备模型一kobject -------------------------------------------------------------- 转载请注明出处:http:/ ...
- linux设备驱动归纳总结(十二):简单的数码相框
http://blog.chinaunix.net/uid-25014876-id-116926.html 其实代码很简单,实现lcd驱动,使lcd能够显示图片,当按下按键后切换图片. 先要说明一下几 ...
- Linux设备驱动--块设备(二)之相关结构体
上回最后面介绍了相关数据结构,下面再详细介绍 块设备对象结构 block_device 内核用结构block_device实例代表一个块设备对象,如:整个硬盘或特定分区.如果该结构代表一个分区,则其成 ...
- linux fb设备驱动,linux设备驱动归纳总结(八):1.总线、设备和驱动
linux设备驱动归纳总结(八):1.总线.设备和驱动 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
最新文章
- 如何导入nod32企业版的授权文件.lic,并制作镜像服务器?
- Spring中@Import注解的作用和使用
- dedecms原理及使用
- 【VS开发】PCIe体系结构的组成部件
- IDEA云行项目提示Error: java: OutOfMemoryError
- python数据预处理_Python数据预处理——缺失值、重复值
- 【转载】石油天然气常用单位换算
- C++ std::unordered_map怎么用
- 向量机和感知机的相同和不同点_感知机(perceptron)和支持向量机(svm)是一种东西吗?
如果不是那他们的区别和关系是什么?...
- 添加 centos 右键 terminal
- JAVA编写飞机大战---分析过程及源代码(超详细超完整)
- 数据分析师还是算法工程师|用数据多角度解读如何选择
- 如何写投资项目计划书?
- 杂谈(1)--人生必知的78种经典效应
- c++标准扩展TR1
- YYlabelCopy
- RapidMiner 5.3.015源代码下载并且正确的运行
- C语言100题打卡—第7题
- 橙瓜大数据发掘好书,25个网站小说排行榜,百万人打分
- 交换DataFrame的两列
热门文章
- 右键计算机管理显示目录名称无效,电脑资源管理器的右键上下文菜单打不开的两种解决办法...
- python面向对象案例--买水果
- python pdb 安装_Python调试工具pdb使用详解
- Android加载/处理超大图片神器!SubsamplingScaleImageView(subsampling-scale-image-view)【系列1】
- 御龙在天以前服务器信息,御龙在天所有区的名字,合区前的
- 谷歌眼镜设计规范之UI设计原则
- 求方程的解(简化版)
- 读书笔记——《我们时代的神经症人格》
- 使用Python进行ADSL宽带拨号连接等操作
- 【python练习】打印菱形