USB热拔插事件

news/2024/10/31 5:26:45/

前言

USBUniversal Serial Bus通用串行总线的缩写,是一个外部总线标准,用于规范主机与外围设备的连接以及通讯,目前使用较多的版本有USB1.1USB2.0USB3.0等。USB接口常用在诸如USB串行设备驱动(3G/4G上网卡、蓝牙设备、串口设备)USB大容量磁盘驱动(U盘、移动硬盘)、USB主机控制器驱动(嵌入式otgdwc_otg)、USB键盘鼠标等,这一些的USB功能支持可以通过内核配置来实现,内核会管理这些USB设备的信息(lsusb 命令可以查看USB设备的情况)。上层应用开发则可以通过监听内核socket来获取设备的热拔插信息,进而利用此信息来确定相关的挂载操作或者其他的一些上层应用的业务逻辑。

USB驱动框图

为了加深对USB的理解,我们且看看USB2.0 Host逻辑框图,以达到对USB设备与主机对接接口及协议有一个比较全面的理解。可以看出最右边的PHY0PHY1是用来实现与外部设备进行物理连接的,然后通过serial interfaceUSB控制单元相连接,USB控制单元里面又分为EHCI Host ControllerOHCI Host Controller以实现USB2.0USB1.1的兼容,EHCI Host ControllerOHCI Host Controller则通过AHB BUS(在PC机则是PCI总线)总线与MemoryCPU相连。整个过程看起来并不是十分复杂,但是实际应用中有大量的控制寄存器需要配置来实现与不同的外围设备进行相连,但是这一切的繁杂工作内核已经帮我们实现了。

USB热拔插

热插拔(hot-pluggingHot Swap)即带电插拔,它的诞生提高了系统与外围设备的交互能力。那么我们如何获取USB的热拔插事件呢,这里可以通过与内核建立socket连接,然后对socket进行监听来获取USB拔插信息,接着对监听的信息进行处理,对于大容量存储设备则决定设备的挂载目录(mount /dev/sdb /usb)或者设备卸载(umount -l /USB)、对于诸如3G/4G等上网卡设备,则可以通过监听拔插信息来决定拨号上网或者接听电话等。下面通过例子说明如何通过内核socket获取设备热拔插信息的。

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <stddef.h>
#include <sys/mount.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <mntent.h>static int CreateHotPlugSock(void)
{struct sockaddr_nl snl;const int buffersize = 16*1024;int retval = 0;memset(&snl,0x00,sizeof(struct sockaddr_nl));snl.nl_family = AF_NETLINK;snl.nl_pid = getpid();snl.nl_groups = 1;int hotplug_sock = socket(PF_NETLINK,SOCK_DGRAM,NETLINK_KOBJECT_UEVENT);if(hotplug_sock == 1){printf("error get socket:%s",strerror(errno));return -1;}setsockopt(hotplug_sock, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize, sizeof(buffersize));retval = bind(hotplug_sock,(struct sockaddr *)&snl,sizeof(struct sockaddr_nl));if(0 > retval){printf("bind failed:%s",strerror(errno));close(hotplug_sock);hotplug_sock = -1;return -1;}return hotplug_sock;
}int main(int argc, char* argv[])
{int sockfd;int sum,size;char buf[1024] = {0};char *str;sockfd = CreateHotPlugSock();while(1){sum = 0;memset(buf, 0, sizeof(buf));size = recv(sockfd, buf, sizeof(buf), 0);//	fprintf(stderr,"size=%d, buf=[%s], strlen(buf)=%d\n", size, buf, strlen(buf));while(sum < size){str = buf + sum;sum += strlen(str);buf[sum] = '\n';}buf[sum] = 0;//输出热拔插socket监听的信息fprintf(stderr,"buf=[%s]\n\n", buf);usleep(100*1000);}	
}

下面是样例代码socket监听鼠标设备拔插的部分打印信息

总结

正如linux下一切都是文件的哲学理念一样,现在的外围设备则一切以USB为标准看齐,在应用程序开发过程中,经常需要对这些USB外围设备的热拔插事件进行监听处理来实现上层软件的业务逻辑,内核socket很好解决了这个问题,通过它可以很方便地与这些USB热拔插设备交互。原创不易,转载请说明出处。

文章参考:

https://www.cnblogs.com/oracleloyal/p/5333276.html

https://blog.csdn.net/gladyoucame/article/details/8768731


http://www.ppmy.cn/news/483432.html

相关文章

[热拔插] 轻量级Winform插件式框架

写在前面的话 对于大神&#xff0c;Winform这种“古董玩具”&#xff0c;实在没太多“技术性”可言了&#xff0c;然而『好用才是王道』&#xff0c;本文不以技术为卖点&#xff0c;纯属经验之谈&#xff0c;欢迎交流拍砖 朴素版UI 开发初衷 由于本人所在公司不定时需要开发各种…

[嵌入式linux]PCIe 热拔插(rescan)

linux下可通过/sys/bus/pci/devices/0000\:[bus number]\:[device number].[function number]/ 目录下的节点进行热拔插操作。 板子上电前PCIe插槽有一块NVME的固态硬盘 [ 0.198515] pci 0000:00:00.0: [16c3:abcd] type 01 class 0x060400 [ 0.199284] pci 0000:01:00…

几个SQL的高级写法

一、ORDER BY FLELD() 自定义排序逻辑 MySql 中的排序 ORDER BY 除了可以用 ASC 和 DESC&#xff0c;还可以通过 ORDER BY FIELD(str,str1,...) 自定义字符串/数字来实现排序。这里用 order_diy 表举例&#xff0c;结构以及表数据展示&#xff1a; ORDER BY FIELD(str,str1,..…

关于微信小程序生成海报一个简单的办法

废话不多说&#xff0c;直接入题&#xff0c;先上GITHUB地址&#xff0c;这个组件很好用&#xff0c;有图形生成工具&#xff0c;你不用再自己写代码一个个元素对齐了&#xff0c;是不是很爽。 GITHUB&#xff1a;https://github.com/Kujiale-Mobile/Painter 生成painter代码…

TC8:SOMEIPSRV_OPTIONS_12-15

SOMEIPSRV_OPTIONS_12: Reserved field of the IPv4 Multicast Option 目的 IPv4 Multicast Option的Reserved字段应静态设置为0x00 这里指的是第二个Reserved字段 测试步骤 DUT CONFIGURE:启动具有下列信息的服务Service ID:SERVICE-ID-1Instance数量:1Tester:客户端-1发…

Jconsole 开启远程连接遇到的一些坑

最近在学习 JVM&#xff0c;其中涉及到性能、内存等指标分析需要使用工具分享&#xff0c;Java 提供了几个可视化工具来监控和管理 Java 应用&#xff0c;比如 Jconsole、JVisual、JMC&#xff0c;他们以图形化的界面实时的监控程序各种性能指标以及内存、CPU 的使用情况。 Jco…

Prometheus配置通过file_sd_configs中每个目标的module标签信息重置每个目标的metrics_path

配置方式如下: scrape_configs: - job_name: file_sd file_sd_configs:- files: - targets.jsonrelabel_configs:- source_labels: [__address__]regex: (http://)([^:])target_label: __address__ replacement: http://${2}- source_labels: [__port__] regex: (\d)target_la…

Davinci安装失败

Davinci安装失败 在安装Davinci的时候&#xff0c;遇到报错Failed to install DaVinci Resolve Panels. Continues with others components? 更新最新显卡驱动没有解决问题&#xff0c;后来想到可能是我把TMP&#xff0c;TEMP文件夹放到ramdisk&#xff0c;导致空间不够。在把…