为啥写这篇文章
初次接触USB驱动程序,协议本身支持的设备类型非常多,资料也非常多,相关的专业名词也是非常多,为了记录这个过程,特意写一下自己的学习过程,希望也能帮助到初次接触到这部分的人。
USB驱动的分类
USB是主从结构,两个包含USB接口的设备之间进行通信,必然一主一从,从程序角度上来看,主机和从机上都运行着各自的驱动程序,才能使二者之间正常通信。所以USB驱动程序分为主机上的USB驱动程序和设备上的USB驱动程序。这里说的驱动程序针对的都是带操作系统的驱动开发,所以名词上会和其他人保持一致,主机上的驱动开发叫做主机控制器驱动开发(UHC,网上很多说设备驱动开发主要就是指的这个),设备上的驱动开发叫做USB从机控制器驱动(UDC)。下面的描述这些名词都可能会用到,首先要搞清楚,自己到底是要做UHC还是UDC,至于单片机等不带操作系统做主机或者从机的情况(类似U盘 鼠标这类),下面也会讨论到。
对主机而言,驱动程序还分两部分,一部分是作为主机自身USB处理单元和CPU之间的驱动关系,另一部分是对接入的设备进行驱动的支持,第一部分,一般情况下,处理器厂商的usb外设从第三方购买IP,这部分驱动芯片厂商在系统层面已经做好了适配,如果时间允许,后面的文章中也许可以看到对这部分内容的分析;第二部分才是普通的驱动开发者经常遇到的,它是与设备业务相关的那部分驱动的开发,不管是在windows还是在linux上做这部分驱动开发,这方面往往有许多可以参考的例子;接下来讨论的主机设备驱动程序UHC,没有特指的情况下都指的是这部分的开发,并且优先在Linux平台上做讨论。
对从机而言,驱动程序也分两部分,第一部分是主机芯片USB处理单元和CPU之间的驱动关系,另一部分是自身设备业务驱动,和主机驱动类似,前者不是我们所需要关注的,后者是重点关注的,而这部分的驱动我主要在linux平台上进行阐述,相信很少会出现让windows电脑作为从机接入的情况,而在linux上提供了Gadget 驱动框架,从机相关的驱动实现都基于该框架进行阐述。
关于USB驱动的相关疑问
支持USB协议的设备越来越多,直接使用USB协议的设备就很多,比如常见的鼠标、键盘、U盘,USB还可以在其他通信协议中做桥接,比如usb蓝牙接头,usb无线网卡,usb虚拟串口,相关资料也不少,自己在学习过程中也是针对不同的设备类型进行学习和模仿的。但在学习初期也遇到了很多疑问,比如很多教程写着设备驱动程序,如果是做类似鼠标、U盘、网卡这类电子设备的,那么到底别人写的设备驱动程序是不是自己需要的?
当拿着单片机需要实现类似U盘或鼠标的功能的时候,究竟需要了解哪些内容,怎样锁定关键的部分?
如果想实现单片机与电脑之间的自由通信,既不是鼠标键盘,又不是U盘,那么分别需要在单片机和电脑上做些什么呢?这里还有一个问题,很多USB设备是不需要额外写驱动的,那么啥情况需要自己写驱动,啥情况可以用系统自带的驱动的?
需要写驱动的那部分是否又可以使用一些开源的资源库来实现自定义的USB通信呢?
如果是用单片机来作为主机,比如读取U盘,这种情况不管单片机有没有跑系统,都不在这里展开讨论,因为一般单片机这部分功能都提供好了,而RTOS也支持这些。
而单片机作为从机,实现U盘或者鼠标,这里会讨论到的,因为一方面借助这类设备可以方便地结合主机端设备驱动程序进行通信测试,好处就是同时解决不带系统的USB从机端驱动业务程序编写重点和主机端Linux或者windows主机设备驱动程序的编写流程,并展开讨论在windows或者linux上一般的USB通信过程是否需要写驱动的问题,比如是否可以使用HID类或者虚拟串口通信来实现免驱,或者使用第三方库来实现USB协议自由通信,最终自己写这样一个驱动来实现自由的使用usb接口进行通信的过程,下文也将按照示例以及通信效率和资源占用情况分析这几种做法的特点,在产品中应该怎样做,但主机端设备驱动这方面资料比较多,可能链接到其他写的好的文章中去了,免得重复造轮子了。
USB加解密问题,像一些加密狗,加密U盘,这些实现的原理是怎样的呢?以及文件系统和USB驱动之间是怎样的关系?因为我们看到接入U盘就可以看到一个盘符,里面有着不同的文件系统,这些又是怎样实现的呢?
如果想实现像手机那样,接入电脑可以在资源管理器中看到一个U盘,能进行adb调试,能与电脑上的手机管家通信,还可以共享与电脑之间的网络,当手机上接入U盘,手机又可以读取U盘的信息,这一切是怎样实现的呢 ?
而随着USB版本越来越高,USB不止支持了快充,还支持了视频相关的协议,这部分又是怎样的呢?
我在了解USB相关功能的时候,网上这么多设备驱动程序教程,哪一类是自己需要的呢?
一一解疑
如果是做鼠标、键盘、U盘,一般是基于单片机来做的,这类驱动也有两方面,一部分是芯片厂商提供好的相关寄存器的配置,另一部分是自身业务相关的部分,往往厂商已经提供了鼠标或者键盘等HID类设备的实现例子,自己只需要修改一些描述符信息,修改接受和发送函数的业务逻辑,便可以完成与鼠标或键盘类似的功能,如果对带宽要求不高,刚好也不想做主机端驱动,但又要实现单片机与电脑之间的通信,可以使用这类方法,由于这类比较简单,后面看情况补充一篇用stm32实现与windows PC之间实现低速数据通信的办法,主要好处是免驱,兼容性好。
如果是在主机端实现与设备自由通信,除了使用HID类设备,还可以使用USB虚拟串口的方式,但是这类办法都有局限性,串口具有速度不高,开销不小的特点,所以想实现自由的数据通信或者类似开发驱动一个USB网卡的驱动,这些便是主机控制器设备驱动程序了,后面会给出一篇主机端的网卡驱动教程或者一个能与设备端进行自由数据通信的教程,主机端使用Linux,从机使用单片机STM32。
如果对手机上这样的USB接口功能感兴趣,也是我所关注的重点内容。这种后续的讨论将在linux系统上,想实现从机的相关功能,就要关注Gadget 驱动框架,这部分相关的内容比较少,将作为重点进行讨论。后面将通过几个实例,从简单到复杂,首先实现linux从机模拟鼠标,接着实现linux从机作为U盘,继续实现linux从机与主机windows之间的自由通信,完成一个案例实现linux设备屏幕和windows屏幕之间通过USB相互分享的功能。
而USB支持视频相关的协议,也在后面的一个视频转接板中进行描述,将实现Type-c转Hdmi,mipi,并简单介绍USB转I2C触摸驱动相关案例。
结语
这里挖了一些坑,一方面是记录一下前段时间的工作内容,另一方面是希望能与其他USB方面爱好的人一块分享交流,这里写的有点赶时间,后面也会再改改,其他将要补充的内容将连接在本文挖坑的地方。
可以留言一块交流,谢谢。