LInux下使用USB模拟ACM串口设备

这个想法之前就在脑袋里有过,最近公司产品要用到,所以多做了些了解。

1. USB 简介

USB 是 Universal Serial Bus 的缩写,从字面上看,就是通用串行总线的意思。从物理上看,其实就是一对差分线,连接两台设备后,相互间进行数据传输。加上另外两路供电( 5V 和 GND)线,一共是 4 根线。

那么,既然是只有一对差分线,那么该如何决定由谁传给谁呢(如果两边同时在线上建立电平,线路上的电平会是不确定态的,以致无法通信)?这就要说到 USB 传输的一个重要基础:“询问-应答” 机制—— Device(slave) 设备通常是处在等待状态,只有 HOST 侧设备发起询问、请求,它才会在接下来的时间片中使用数据线向 HOST 发送数据。

那么,谁是 HOST,谁是 SLAVE 又是由什么来决定的呢?答案是硬件。也就是说,你 USB 后面的那块驱动芯片如果是 HOST,那么,这个 USB 只能做 HOST 用了。反之,SLAVE 亦然。比如我们经常见到的,PC 上的 USB HOST 连接到 U盘、鼠标、键盘这些 SLAVE 设备。

当然,后来有人觉得这样一个设备只能是 HOST 或者只能是 SLAVE 太死板了,所以又发明了 USB OTG。USB OTG(on-the-go,大意为在使用时切换身份)是在原来 4 根线的基础上,又加了一根线,ID。那块 USB 后面的驱动芯片,就可以根据这根线,来选择自己到底该扮演 HOST 还是 SLAVE 的角色:当这根线悬空时,保持自己为 SLAVE;当这根线接地时,自身身份切换为 HOST。这一功能对接口数量受限的设备来讲,简直就是一大福音!比如手机,现在的 Android 基本都已支持 OTG 功能。对这样的手机,你可以选择用 USB 线将其连接到 PC,这样手机将自己模拟成一个 U 盘,你可以使用 U 盘拷贝手机中数据;或者,你可以直接使用 OTG 转接线,将 U 盘与手机连接,直接用手机来操作 U 盘。

另外,因为使用一对差分线进行数据传输,所以,USB 又采用了基于 HUB 的星形拓扑结构(包括根控制器,最多7 层拓扑,且7层已不具备挂载 HUB 能力,只能是功能设备)。所以,更确切来说,“HOST-SLAVE“ 是在由 HUB 支持的物理链路之上的传输机制。同时,HUB 本身也是一个 USB SLAVE 设备。

2. USB 连接过程概述

下图很好的解释了 USB 的连接过程。需注意,1)如上图的拓扑结构所示,每个网络内只能有一个 HOST。2) HOST 和 SLAVE 之间,可以一对一直连,也可以通过 HUB ,一个 HOST 对应多个 SLAVE。

基本状态包括:设备插入、设备上电、设备复位、设备获得地址、设备配置完成、挂起状态。下面略做解释。

设备插入:HOST 侧(可能是在 HUB 上,也可能是直接在 host controller 上)根据 D+ 和 D- 口的阻抗变化,来判断是否有 device 插入,以及判断插入设备的速度类型。

设备上电:因为 USB 口有供电功能(5V DC,多为 500-1000 mA ),所以,设备又分为 Bus powered 和 self powerd。当然,即使是设备自己供电,我们也认为只有当设备已连接,它才进入powered 状态。设备一旦重新上电,后面的连接操作要重新执行一次。

设备复位:因为只有一对差分线,如果两边同时操作,那线路上的电平将是不确定态,根本无法通信。所以,上电后,USB device(slave)默认为等待状态,不进行任何动作,直到 HOST 发给它一个 Reset 请求。复位完成,意味着低速/全速/高速的物理通路已经建立。

设备获得地址:设备复位成功后,将获得一个由 HOST 分配的地址。分配地址的对话,将在设备的 endpoint0 上完成。

设备配置完成:握手?配置?反正这一阶段完成,意味着设备已经 ready了。

挂起状态:所有 USB Device(slave)在空闲一段时间后,都必须将自己挂起,并保持自己的状态,无论设备已经被分配地址还是没有分配地址。

3. OTG

OTG 增加了一根可以动态配置为 HOST 或者 DEVICE(slave)的数据线,以 micro USB 接头为例,其引脚分配如下:

因为传统的 USB 线缆为 4 根线,所以,要将 OTG 设备接入,需对其进行配置(硬件短接):

  1. 当配置 OTG 设备为 USB Device(slave) 时,将 ID 脚悬空。

  2. 当配置 OTG 设备为 USB HOST时,将 ID 脚接地。

所以,我们这里,需要将OTG脚悬空,来将其配置为 Slave 设备。硬件上面,买来的 OTG 转接线默认把 OTG USB 设备设置为 HOST,他们 ID 脚都是接地的。而我们是需要把 OTG 设备当作 Device(slave)来用,所以,最终选择了将板子上的 ID 线割断,使其悬空。

4. g_serial.ko

当前内核 3.0.8 支持 Gadget Serial 接口,即,如果我们有一个硬件的 USB SLAVE(可以是由 OTG 支持的), 这一驱动可以支持我们在此 USB 通道上实现一个 USB 串口;就像有 PL2303 或者 HM340 硬件支持的 USB 那样。当然,我们的设备是以 USB slave存在的,驱动支持情况下,这个链路看起来就是一个普通的串口连接。其源代码在 /drivers/usb/gadget/serial.c,另外还有文档 Documentation/usb/gadget_serial.txt。可自行阅读。(其实,谷歌的 ADB 工具和这个是差不多的东西,可能甚至只有驱动号不一样。)

具体应用时,我们并不需要做太多修改。。。只需要配置,编译就足够了。我把它编译成了module,所以,需要在文件系统起来之后再做一次 modprobe。

至于 HOST 侧,据说是都不需要驱动的,但是,我在 Windows 上用的时候,还是安装了gadget serial v2.4 的(据说不支持 64 位系统,未验证),UBUNTU 上即插即用。

时间: 2024-10-29 19:10:36

LInux下使用USB模拟ACM串口设备的相关文章

在Linux下使用usb wifi

今天购买了D-Link DWL-G122 usb wifi dongle.之前已经在网上查好了,该款设备可以被Linux支持,同时也找到了几种安装驱动的方法: 使用ndiswrapper直接安装Windows XP版(目前ndiswrapper只支持XP版的)的驱动程序文件(*.inf). 直接从Realtek上下载相应的驱动程序.事先可以在驱动光盘中找到Windows版驱动程序文件的名字,如net8192su.inf.然后在Realtek的官方网站上搜索8192su相应的Linux驱动. 从g

linux下的usb转串口的使用(修改)【转】

环境:Ubuntu 10.10 Server minicom是linux下串口通信的软件,它的使用完全依靠键盘的操作,虽然没有“超级终端”那么易用,但是使用习惯之后读者将会体会到它的高效与便利,下面将讲解minicom的安装和配置. 转自:http://blog.chinaunix.net/uid-25562715-id-1990181.html 一.安装minicom: 使用以下命令:# sudo apt-get install minicom 以下为安装的详细信息:# sudo apt-ge

华为WiFi Pro E5771h-937在linux下使用usb连接

买了一个WiFi Pro E5771h-937无线路由,一直想在linux下使用,官方文档也没有linux下的说明,自己查找资料研究了一下,并测试成功. 在centos7下,直接运行如下modprobe rndis_host命令即可加载 rndis_host.ko和usbnet.ko驱动 然后使用ip a就可以看到usb网卡了 至于路由表,自己可以根据实际情况用route命令进行控制.

Linux下查看USB设备的VID、PID命令

Linux下查看PID命令 cat /proc/bus/usb/devices 或 lsusb 方法一:在/etc/init.d/rcS中添加mount -t usbfs none /proc/bus/usb. 方法二:在shell中输入mount -t usbfs /proc/bus/usb /proc/bus/usb. 前提是在编译内核时选中usb device filesystem. # cat   /proc/bus/usb /device T:  Bus=01 Lev=00 Prnt=

c++ 读取window下的USB输入数据 及 linux下的USB读取

先使用arduino,做一个串口的重复输入,我手头使用的就是mega版. 在arduino自己的ide中做好配置 这里需要配置好,开发板,处理器还有端口. 程序中先要初始化端口,而后要不断打印"Hello world" void setup() { // put your setup code here, to run once: Serial.begin(9600); } void loop() { // put your main code here, to run repeate

linux下php pcntl_fork模拟多线程

开始用php写后台服务一段时间了.也是在这样的驱动下,不断的学习php语法,体验这一原来一直以为神秘且敬而远之的神奇语言的魅力.最初看php多线程的资料是为了提高程序的处理能力,充分发挥linux多任务的优势.不曾想多线程没用成反到是带来了一系列的意外收获.让之后的许多问题迎刃而解,不敢独享特一一道来. 本文所讲的东西是源自php的pcntl_fork函数.因为这个函数依赖操作系统fork的实现,所以本文所讲的东西只适用于linux/unix.ok,那么先看看这个函数的用法吧.php手册上是这么

linux下插入USB设备使用脚本实现自动挂载

某天客户要求说要想在linux OS上插入U盘,然后像和在windows上一样实现自动挂载,在网上没有搜索到有用的信息,有一个软件usbmount,但是试验用不了,有兴趣可以瞧瞧,地址如下 http://usbmount.alioth.debian.org/#what 客户就是客户 于是使用脚本实现这个过程 1. vi mount.sh #!/bin/bash mount_dir=/mnt/usb    #挂载USB设备之后挂载的路径 mount_txt=/etc/mount.txt umoun

Linux下手机USB 显示???

如果你是一个开发人员,而且USB设备很多的话,使用以下方式会很方便: 如果没有51-android.rules文件,在/etc/udev/rules.d/目录下创建51-android.rules;第一步:清空51-android.rules,添加如下一行,一劳永逸(因我需要测试好几种设备,每次都添加一个会很麻烦). 1 SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", MODE="0666" 第二步:

Linux下复位USB设备

有时候USB设备出错,这时我们希望通过软件复位一下USB设备,可以参考下面这段代码: #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <sys/ioctl.h> #include <linux/usbdevice_fs.h> int main(int argc, char **argv) { const char