USB设备热插拔流程解析

设备热插拔

i2c,spi都是主机驱动初始化的时候,就会根据设备树来添加设备

pci的话,主机初始化的时候,会通过总线去遍历枚举card设备

sdio的话,主机驱动初始化的时候,会去枚举卡;插卡可能会触发主机中断,然后中断处理程序又去扫描枚举卡;也可能通过cd脚注册中断,来判断卡的在位情况

mdio的话,根据设备树,去枚举和创建phy设备,会给phy创建一个状态机,每秒去读phy口的网线连接状态

sim卡,有一个cd脚,注册一个中断,根据高低电平,判断是否插卡,拔卡

所以,对于能热插拔的设备,要么通过中断,要么通过轮询(定时器,延时队列等),去判断设备的插拔情况

注册主机

usb主机一般都是通过__usb_create_hcd和usb_add_hcd来注册一个usb主机

static int fsl_ehci_drv_probe(struct platform_device *pdev)
{....hcd = __usb_create_hcd(&fsl_ehci_hc_driver, pdev->dev.parent,&pdev->dev, dev_name(&pdev->dev), NULL);....retval = usb_add_hcd(hcd, irq, IRQF_SHARED);....
}

__usb_create_hcd的流程如下

__usb_create_hcdrh_timer_funcusb_hcd_poll_rh_statususb_hcd_giveback_urburb->complete (urb);

usb_add_hcd的流程如下

usb_add_hcdusb_hcd_request_irqsrequest_irq(irqnum, &usb_hcd_irq, irqflags, hcd->irq_descr, hcd);hcd->driver->irqehci_irqusb_hcd_poll_rh_statususb_hcd_giveback_urburb->complete (urb);

usb_hcd_poll_rh_status函数中,调用主机控制器的hub_status_data函数获取端口状态。如果端口的状态有变化,那么length > 0,把获取到的端口状态的数组拷贝到urb->transfer_buffer中,就是前面的hub->buffer中,同时调用usb_hcd_giveback_urb函数

void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
{struct urb	*urb;int		length;int		status;unsigned long	flags;char		buffer[6];	/* Any root hubs with > 31 ports? */if (unlikely(!hcd->rh_pollable))return;if (!hcd->uses_new_polling && !hcd->status_urb)return;length = hcd->driver->hub_status_data(hcd, buffer);if (length > 0) {/* try to complete the status urb */spin_lock_irqsave(&hcd_root_hub_lock, flags);urb = hcd->status_urb;if (urb) {clear_bit(HCD_FLAG_POLL_PENDING, &hcd->flags);hcd->status_urb = NULL;if (urb->transfer_buffer_length >= length) {status = 0;} else {status = -EOVERFLOW;length = urb->transfer_buffer_length;}urb->actual_length = length;memcpy(urb->transfer_buffer, buffer, length);usb_hcd_unlink_urb_from_ep(hcd, urb);usb_hcd_giveback_urb(hcd, urb, status);} else {length = 0;set_bit(HCD_FLAG_POLL_PENDING, &hcd->flags);}spin_unlock_irqrestore(&hcd_root_hub_lock, flags);}/* The USB 2.0 spec says 256 ms.  This is close enough and won't* exceed that limit if HZ is 100. The math is more clunky than* maybe expected, this is to make sure that all timers for USB devices* fire at the same time to give the CPU a break in between */if (hcd->uses_new_polling ? HCD_POLL_RH(hcd) :(length == 0 && hcd->status_urb != NULL))mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4));
}

usb_hcd_giveback_urb函数中调用urb->complete (urb),而urb->complete = hub_irq;hub_irq会执行一次检查port状态的work;有设备插入就会去初始化port,注册新的usb设备

hub_probeINIT_WORK(&hub->events, hub_event);hub_configureusb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq, hub, endpoint->bInterval);urb->complete = hub_irq;

初始化HUB

在系统初始化的时候在usb_init函数中调用usb_hub_init函数,就进入了hub的初始化。

int usb_hub_init(void)
{if (usb_register(&hub_driver) < 0) {printk(KERN_ERR "%s: can't register hub driver\n",usbcore_name);return -1;}/** The workqueue needs to be freezable to avoid interfering with* USB-PERSIST port handover. Otherwise it might see that a full-speed* device was gone before the EHCI controller had handed its port* over to the companion full-speed controller.*/hub_wq = alloc_workqueue("usb_hub_wq", WQ_FREEZABLE, 0);if (hub_wq)return 0;/* Fall through if kernel_thread failed */usb_deregister(&hub_driver);pr_err("%s: can't allocate workqueue for usb hub\n", usbcore_name);return -1;
}

在usb_hub_init函数中完成了注册hub驱动,然后创建一个工作队列hub_wq,每当有设备连接到USB接口时;根据上面----USB主机在中断后半段会回调complete函数(hub_irq)

static void hub_irq(struct urb *urb)
{struct usb_hub *hub = urb->context;int status = urb->status;unsigned i;unsigned long bits;switch (status) {case -ENOENT:		/* synchronous unlink */case -ECONNRESET:	/* async unlink */case -ESHUTDOWN:	/* hardware going away */return;default:		/* presumably an error *//* Cause a hub reset after 10 consecutive errors */dev_dbg(hub->intfdev, "transfer --> %d\n", status);if ((++hub->nerrors < 10) || hub->error)goto resubmit;hub->error = status;/* FALL THROUGH *//* let hub_wq handle things */case 0:			/* we got data:  port status changed */bits = 0;for (i = 0; i < urb->actual_length; ++i)bits |= ((unsigned long) ((*hub->buffer)[i]))<< (i*8);hub->event_bits[0] = bits;break;}hub->nerrors = 0;/* Something happened, let hub_wq figure it out */kick_hub_wq(hub);resubmit:hub_resubmit_irq_urb(hub);
}

在该函数中利用kick_hub_wq;来执行一次work;work的工作内容为hub->events;

static void kick_hub_wq(struct usb_hub *hub)
{struct usb_interface *intf;if (hub->disconnected || work_pending(&hub->events))return;/** Suppress autosuspend until the event is proceed.** Be careful and make sure that the symmetric operation is* always called. We are here only when there is no pending* work for this hub. Therefore put the interface either when* the new work is called or when it is canceled.*/intf = to_usb_interface(hub->intfdev);usb_autopm_get_interface_no_resume(intf);kref_get(&hub->kref);if (queue_work(hub_wq, &hub->events))return;/* the work has already been scheduled */usb_autopm_put_interface_async(intf);kref_put(&hub->kref, hub_release);
}

hub->events去发现设备,初始化设备

INIT_WORK(&hub->events, hub_event);hub_eventport_eventhub_port_connect_changeusb_alloc_devhub_port_initusb_new_device

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/817738.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

物业满意度调查如何开展?

物业管理行业的服务水平对于提升居民生活质量、维护社区安全和保障房产价值起着重要作用&#xff0c;近年来受地产关联方房屋交付影响&#xff0c;以及疫情后物业投入减少&#xff0c;物业企业对社区环境、设施和公共区域的维护减弱&#xff0c;2023年的降幅尤其明显&#xff0…

Java基础(变量)

什么是变量&#xff1f; 变量&#xff1a;在程序的执行过程中&#xff0c;其值有可能发生改变的量&#xff08;数据&#xff09; 变量的使用场景 当某个数据经常发生改变时&#xff0c;我们也可以用变量储存。当数据变化时&#xff0c;只要修改变量里面记录的值即可。 变量…

加州大学戴维斯分校最新Nature Ecology Evolution(IF=19)!入侵植物在成为生态威胁之前可能会休眠几十年甚至几百年

根据加利福尼亚大学戴维斯分校领导的一项新研究&#xff0c;入侵植物在被引入环境后可能会休眠几十年甚至几百年&#xff0c;然后才会迅速扩展并造成生态破坏&#xff08;非常意外和可怕&#xff09;。这项发表在《Nature Ecology & Evolution》上的研究调查了全球九个地区…

掌握JMeter HTTP 请求头:简单易懂

在深入研究 JMeter 的过程中&#xff0c;任何涉及性能测试或接口验证的专业人员都会认识到&#xff0c;合理配置HTTP请求头部信息是实现精确测试的关键步骤之一。不同情景下&#xff0c;如数据提交形式的不同&#xff08;例如 JSON、XML 等&#xff09;&#xff0c;或是需要通过…

【react】零基础教学写一个最简单的网站和装饰思路

你想要把你的数据放在网络上&#xff0c;给别人分享&#xff0c;难道就是直接闹脑中想一想就能做了么&#xff1f; 并不是&#xff0c;我们看到有五花八门的网站。 这些网站都是非常的好看&#xff0c;玲琅满目的商品让你想要去下单购买。 一个复杂的商城是很复杂&#xff0c; …

英语技术会议常用语

个人整理。 自我介绍&#xff1a; Hello everyone, Im [Your Name], and Im excited to be here today. I work as [Your Position] at [Your Company/Organization], where I focus on [Brief Description of Your Role or Expertise]. Im looking forward to our discussion…

YoloV8改进策略:Block改进|轻量级的Mamba打造优秀的YoloV8|即插即用,简单易懂|附Block结构图|检测、分割、关键点均适用(独家原创)

摘要 无Mamba不狂欢,今天给大家带来一个基于轻量级Mamba的改进。模块简单易懂,即插即用! 带领大家去征服更高的领域。 论文:《LightM-UNet:Mamba 辅助的轻量级 UNet 用于医学图像分割》 https://arxiv.org/pdf/2403.05246.pdf UNet及其变体在医学图像分割中得到了广泛…

uniapp开发 如何获取IP地址?

一、需求 使用uniapp开发小程序时&#xff0c;需要调取【记录日活动统计】的接口&#xff0c;而这个接口需要传递一个ip给后台&#xff0c; 那么前端如何获取ip呢&#xff1f;下面代码里可以实现 二、代码实现 1.在项目的manifest.json中配置一下网络权限&#xff1a; &quo…

Python离线语音识别高准确率方案分析及代码实现

背景: 随着信息技术的飞速发展和人工智能的广泛应用,语音识别技术已成为现代通信和人机交互领域的重要组成部分。离线语音识别技术,作为语音识别的一个分支,因其无需实时连接网络、保护用户隐私等特性,在特定场景中发挥着越来越重要的作用。 离线语音识别技术主要指的是…

IDEA pom.xml显示灰色并被划线

在使用 IDEA 进行开发的过程中&#xff0c;有时候会遇到 pom.xml 显示灰色并被划线的情况&#xff0c;如下图&#xff1a; 这一般是因为该文件被 Maven 忽略导致的&#xff0c;可以进行如下操作恢复&#xff1a; 设置保存后&#xff0c;可以看到 pom.xml 恢复了正常&#xff1a…

python-pytorch 利用word2vec实现lstm模型预测中文文本输出0.1.00

python-pytorch 利用word2vec实现lstm模型预测中文文本输出0.1.00 前言源数据导入包加载数据分析后写入新文件word2vec训练词向量保存word2vec训练词模型保存word2vec词向量加载保存word2vec的模型将分词好的句子依次导入数组中获取word2index、word2index获取word2index、inde…

Java进阶篇——线程通信

0.前言 推荐新手先阅读基础篇 http://t.csdnimg.cn/Xrq8a 1.前提条件 线程同步是线程通信的前提 线程同步常用方法&#xff1a;sychronized关键字&#xff0c;Lock接口 2.两种线程通信方式 2.1定义 Monitor——同步监视器&#xff0c;对象可以是任何类型&#xff0c;因此定义…

深入探讨VIVE OpenXR:为Unity开发者的全面指南

随着虚拟现实&#xff08;VR&#xff09;和增强现实&#xff08;AR&#xff09;技术的迅速发展&#xff0c;开发者们对于能够简化和优化沉浸式应用开发的工具需求日益增长。HTC Vive 作为行业内的领先品牌&#xff0c;其最新推出的 VIVE OpenXR 插件为Unity开发者提供了一个强大…

PowerShell 安装、升级、禁止升级检查

文章目录 下载安装Zip安装Msi安装 升级禁止升级检查 下载 Powershell安装指南&#xff0c;提供了多种安装路径&#xff0c;推荐zip方式&#xff0c;简单快捷。 因从官网下载msi或者zip非常慢&#xff0c;推荐从某个开源镜像站下载powershell的安装包&#xff0c;msi或者zip&am…

明日周刊-第6期

最近一周杭州的天气起起伏伏&#xff0c;下雨就凉&#xff0c;不下雨就热。但是夏天的感觉确实是越来越浓烈了&#xff0c;又是一年夏&#xff0c;在这个夏天大家都有什么新的计划呢。 文章目录 一周热点资源分享言论歌曲推荐 一周热点 一、我国自主研发科技壮举震惊全球航天界…

swagger文档无法访问

1. 报错异常 Unable to render this definition The provided definition does not specify a valid version field. Please indicate a valid Swagger or OpenAPI version field. Supported version fields are swagger: "2.0" and those that match openapi: 3.0…

Web前端 JavaScript笔记4

1、元素内容 属性名称说明元素名.innerText输出一个字符串&#xff0c;设置或返回元素中的内容&#xff0c;不识别html标签元素名.innerHTML输出一个字符串&#xff0c;设置或返回元素中的内容&#xff0c;识别html标签元素名.textContent设置或返回指定节点的文本内容&#x…

2023年图灵奖揭晓,你怎么看?

2023年图灵奖揭晓&#xff0c;你怎么看&#xff1f; 2023年图灵奖&#xff0c;最近刚刚颁给普林斯顿数学教授 Avi Wigderson&#xff01;作为理论计算机科学领域的领军人物&#xff0c;他对于理解计算中的随机性和伪随机性的作用&#xff0c;作出了开创性贡献。 提醒&#xff…

LeetCode hot100-27

21. 合并两个有序链表将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 这题虽然也做出来了&#xff0c;但是做得不好&#xff0c;用了额外的新节点去组成新的链表。其实直接改变原有链表的指向就行了&#xff0c;不用开那么多…

贝叶斯公式中的先验概率、后验概率、似然概率

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和技术。关…