2017-01-05 16:48:07 mapeng892020 阅读数 7231

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

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 的角色。后面我们单独介绍。

另外,因为使用一对差分线进行数据传输,所以,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. 一般的实现结构

前面我们讨论了硬件部分,同时,作为通讯接口,不可能不需要系统及软件层面的协作。先给出一张比较常见的 USB 通讯模型图,然后我们再做解释:

对于整个 USB 通讯过程,我们可以粗略的将其分为“总线层”、“功能层”和“设备层”三个层次。这三个层次的划分,主要是为了问题的集中解决。其中:

  a. 总线层负责解决“点到点”的问题,主要是保障上一层可以和相邻的端点“对话”,一般还会提供硬件 buffer 公上层使用;

  b. 设备层才有了设备的概念,HOST 通过 Device(Slave)的 Endpoint0 对其进行配置,准备好数据管道给上一层使用;

  c. 功能层在是 Device(Slave)功能的具体实现,才能看到一个个“鲜活”的设备,才是我们看得到的 U盘、鼠标这些设备。

以某安装 Linux 的 PC 为例,作为 HOST,其中这三部分工作分别由控制器(如 EHCI 、UHCI 、OHCI),USB CORE (对前面控制器的内核支持、设备管理功能等)和 USB 上层驱动(usbmouse、usbkbd、usb-storge)。

我们要实现的 USB 串口,就是属于 USB 上层驱动部分的实现。只不过,我们是通过类似于这里 HOST 的结构,实现了一个 Device(Slave)。

 

5. g_serial.ko

当前内核 3.0.8 支持 Gadget Serial 接口。也就是说,如果我们有一个硬件的 USB SLAVE(可以是由 OTG 支持的), 这一驱动可以支持我们实现一个软件的 USB 串口;就像由 PL2303 或者 HM340 硬件实现的 USB Serial 一样。 只有 HOST 控制器是不行的。不管是对 HOST 侧的PC,还是我们添加 Gadget Serial 驱动支持的 PC,这条链路看起来都只是一个普通的串口连接。其源代码在 /drivers/usb/gadget/serial.c,另外还有文档 Documentation/usb/gadget_serial.txt。可自行阅读。(其实,谷歌的 ADB 工具和这个是差不多的东西,可能甚至只有驱动号不一样。)

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

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

——————无论在哪里做什么,只要坚持服务、创新、创造价值,其他的东西自然都会来的。


说明:本文转载自:http://www.cnblogs.com/pied/p/4549614.html

2018-07-19 17:20:18 insanegtp 阅读数 527

网上找的高人帖子: https://community.cypress.com/thread/14010?start=0&tstart=0

关键的yidu一段话:,

I managed to access the serial port in Linux:

- change product id in usb descriptor to 0xF139 :        < 0x39,0xF1,                      /* Product ID */ >

- use modprobe to bind the usbserial driver to the device <sudo modprobe usbserial vendor=0x04B4 product=0xF139

- the device appears now as /dev/ttyUSB0

按照这个操作,有时候会虚出两个串口,有时候会出一个。。。。很神奇

还要cypress的cyusb_linux其他VID,PID 不识别问题,

https://community.cypress.com/docs/DOC-10863

Question: How do you make a device with a custom vendor identification (VID) number / product identification (PID) number visible on the cyusb_linux GUI?

Answer:

By default, the cyusb_linux GUI (Control Center equivalent for Linux) only shows devices with a Cypress® VID (0x04B4) and PIDs contained in the /etc/cyusb.conf file.

If you are using a Cypress VID (0x04B4) and any PID that is not present in the /etc/cyusb.conf file, you will have to add the VID (0x04B4) and the PID to the end of the /etc/cyusb.conf file. You will need root permissions to do this. If the cyusb_linux GUI is already open, close it and start it again. The device will now appear in the cyusb_linux GUI.

If you are using a non-Cypress VID, follow the steps below. For this example, the VID is 0x04FF and the PID is 0xFF.

  1.   Add the VID and PID in /etc/cyusb.conf as shown in Figure 1. You will need root permissions.  

       Figure 1. FX3™ Custom VID-PID Added to cyusb.conf File

     

       FX3 custom

  2.   For a non-Cypress VID, you will need to make changes in the /etc/udev/rules.d/88-cyusb.rules file as well. You will need root permissions. Copy lines four and five of the 88-cyusb.rules file and paste it back into the file with ATTR{idVendor}==”04b4” changed to ATTR{idVendor}==””, as shown in Figure 2.  

       Figure 2. ATTR{idVendor}==”04ff” Added in the 88-cyusb.rules File

     

       rules file

  3.   Close and restart the cyusb_linux GUI. The device with a custom VID/PID will now appear in the GUI as shown in Figure 3.  

       Figure 3. Device with VID=0x04ff and PID=0x00ff Now Appears in the cyusb_linux GUI

     

       linux GUI

  4. 还有个奇葩坑,就是如果VID设成cypress的0x04b4,PID只有为0x0008时,才能虚拟出ttyACM0,但cyusb_linux无设备,采用上述方法,会出现设备列表,但ttyACM0会消失,必须用modprobe强制生成一个ttyUSB0。如果换为其他PID则ttyACM0消失,设备列表 出现。如果VID和PID设为非0x04b4,则ttyACM0会出现,再采用上述方法,自定义设备也会出现在设备列表中。这个奇葩坑害了我大概一周的时间!!!!

2017-04-18 14:19:20 pyf09 阅读数 7078

以下内容参考

http://blog.csdn.net/xhoufei2010/article/details/43966889


一、硬件平台:TI AM335X 芯片


二、软件平台:Ubuntu 10.04


三、USB CDC ACM 驱动简介

        USB的CDC类是USB通信设备类 (Communication Device Class)的简称。CDC类是USB组织定义的一类专门给各种通信设备(电信通信设备和中速网络通信设备)使用的USB子类。

        Linux 内核本省自带USB CDC ACM类驱动模块功能,用户可以采用内核下的图形化编译工具menconfig 添加该驱动至内核模块。

        步骤一:进入到自己下载的内核目录,运行命令 make menuconfig,出现如图1所示的 menu 菜单主界面。

                                         

                                                                                                           图1  menuconfig菜单主界面


    步骤二:在图1中,选择“Device Driver”选项,通过“Select”确定,进入到设备驱动界面,如图2所示。

                           

                                                    图2 设备驱动界面


    步骤三:在图2所示的设备驱动界面中,选择“USB support”选项,选择“Select”选项,确定后进入图3所示的USB驱动界面。

                           

                                                     图3 USB驱动界面

    步骤四:选择“USB Modem(CDC ACM support)”选项,该选项左端的“<>”中,默认为空,按下“空格键”可以切换选择项,选择为“*”号。

    对于尖括号里面的选项,如果为空,表示没有选择;

    如果为“*”,表示对应的选项编译到内核里;

    如果为“M”,表示对应的选项编译成模块。

        

    步骤五:USB设置完成之后,选择图3中的“Exit”选项,依次退出。退出之后,将会进入图2选项,继续选择“Exit”。然后进入图1界面,继续选择“Exit”。此时,将会出现确定是否保存修改界面,如图4所示。选择“Yes”选项即可。

                           

                                         图4 是否保存配置界面


    步骤六:重新编译内核,此时会将USB CDC ACM驱动添加至驱动程序中。

0

2015-02-27 13:45:26 xhoufei2010 阅读数 16163

一、硬件平台:TI AM335X 芯片


二、软件平台:Ubuntu 10.04


三、USB CDC ACM 驱动简介

        USB的CDC类是USB通信设备类 (Communication Device Class)的简称。CDC类是USB组织定义的一类专门给各种通信设备(电信通信设备和中速网络通信设备)使用的USB子类。

        Linux 内核本省自带USB CDC ACM类驱动模块功能,用户可以采用内核下的图形化编译工具menconfig 添加该驱动至内核模块。

        步骤一:进入到自己下载的内核目录,运行命令 make menuconfig,出现如图1所示的 menu 菜单主界面。

                                         

                                                                                                           图1  menuconfig菜单主界面


    步骤二:在图1中,选择“Device Driver”选项,通过“Select”确定,进入到设备驱动界面,如图2所示。

                           

                                                    图2 设备驱动界面


    步骤三:在图2所示的设备驱动界面中,选择“USB support”选项,选择“Select”选项,确定后进入图3所示的USB驱动界面。

                           

                                                     图3 USB驱动界面

    步骤四:选择“USB Modem(CDC ACM support)”选项,该选项左端的“<>”中,默认为空,按下“空格键”可以切换选择项,选择为“*”号。

    对于尖括号里面的选项,如果为空,表示没有选择;

    如果为“*”,表示对应的选项编译到内核里;

    如果为“M”,表示对应的选项编译成模块。

        

    步骤五:USB设置完成之后,选择图3中的“Exit”选项,依次退出。退出之后,将会进入图2选项,继续选择“Exit”。然后进入图1界面,继续选择“Exit”。此时,将会出现确定是否保存修改界面,如图4所示。选择“Yes”选项即可。

                           

                                         图4 是否保存配置界面


    步骤六:重新编译内核,此时会将USB CDC ACM驱动添加至驱动程序中。

2016-11-16 21:30:07 zqixiao_09 阅读数 7060

Module_init中会注册tty_driver,tty_device会在acm usb_driver的probe中注册。

每个ACM设备都由2个Interface组成,第一个interface有一个interrupt endpoint主要负责控制,第二个interface主要负责数据传输,有2个endpoint,有可能是两个int,也有可能是2个bulk。他们都是成对出现的。

比如:

这个是第一个interface,其中CDC Union中,bMasterInterface就是设备的第0interface,它就是ACM中的第一个interface,作为主interface,它所对应的从interface的号是1,也就是负责数据传输的那个interface。他们两个是成对出现的。

    Interface Descriptor:

      bLength                 9

      bDescriptorType         4

      bInterfaceNumber        0

      bAlternateSetting       0

      bNumEndpoints           1

      bInterfaceClass         2 Communications

      bInterfaceSubClass      2 Abstract (modem)

      bInterfaceProtocol      1 AT-commands (v.25ter)

      iInterface              4 CDC Communication Interface

      CDC Header:

        bcdCDC               1.10

      CDC Union:

        bMasterInterface        0

        bSlaveInterface         1

      CDC Call Management:

        bmCapabilities       0x00

        bDataInterface          1

      CDC ACM:

        bmCapabilities       0x07

          sends break

          line coding and serial state

          get/set/clear comm features

      Endpoint Descriptor:

        bLength                 7

        bDescriptorType         5

        bEndpointAddress     0x81  EP 1 IN

        bmAttributes            3

          Transfer Type            Interrupt

          Synch Type               None

          Usage Type               Data

        wMaxPacketSize     0x0040  1x 64 bytes

        bInterval               4

第二个

    Interface Descriptor:

      bLength                 9

      bDescriptorType         4

      bInterfaceNumber        1

      bAlternateSetting       0

      bNumEndpoints           2

      bInterfaceClass        10 CDC Data

      bInterfaceSubClass      0 Unused

      bInterfaceProtocol      0

      iInterface              5 CDC Data Interface

      Endpoint Descriptor:

        bLength                 7

        bDescriptorType         5

        bEndpointAddress     0x82  EP 2 IN

        bmAttributes            2

          Transfer Type            Bulk

          Synch Type               None

          Usage Type               Data

        wMaxPacketSize     0x0200  1x 512 bytes

        bInterval               0

      Endpoint Descriptor:

        bLength                 7

        bDescriptorType         5

        bEndpointAddress     0x02  EP 2 OUT

        bmAttributes            2

          Transfer Type            Bulk

          Synch Type               None

          Usage Type               Data

        wMaxPacketSize     0x0200  1x 512 bytes

        bInterval               0

    Interface Association:

      bLength                 8

      bDescriptorType        11

      bFirstInterface         2

      bInterfaceCount         2

      bFunctionClass          2 Communications

      bFunctionSubClass       2 Abstract (modem)

      bFunctionProtocol       1 AT-commands (v.25ter)

      iFunction               0

在第一个interaface被匹配后,它对应的probe函数中,会找到它所对应的slave interface,并用

usb_driver_claim_interface(&acm_driver, data_interface, acm);来对其声明,让这两个interface device匹配同一个usb_driver。

虽然在module_init中注册了tty_driver,但是此时它是不工作的,在probe的结尾会调用

tty_register_device(acm_tty_driver, minor, &control_interface->dev); 

这句话是注册tty_driver所对应的tty_device,此时他们俩会匹配,并创建相应的字符设备。这个时候user space才可以对其进行访问!

其中在probe中,会有三个ep

Epcontrol

Epread

Epwrite

其中control是interrupt ep,在tty_open的时候会注册到系统中,监听control event.

Epread对应一个urb,也是在tty_open时被submit,每次接收到数据后,urb的callback了都会调用tty_flip_buffer_push将数据提交给tty子系统的flip buffer中。

Epwrite则是在tty_write中调用。

acm_tty_throttle会在最后一次read urb处理的callback中进行判断是否继续提交,因为tty子系统的flip buffer已经满了,直到acm_tty_unthrottle中会再次提交read urb。

 

acm_tty_break_ctl是用来发送break信号的,RS232规定,收到break信号后,要output一段时间的logic zero。

 

acm_tty_tiocmset和acm_tty_tiocmget主要是来设置和查询当前的CS232的硬件信号的支持。比如RTS信号

 

而acm_tty_set_termios主要就是设置什么奇偶校验,波特率等串口传输特性。