Linux USB虚拟串口设备

时间:2021-03-26 16:14:38

  Linux内核中usb设备侧驱动程序分成3个层次:UDC驱动程序、Gadget APIGadget驱动程序。UDC驱动程序(USB控制器)直接访问硬件,控制USB设备和主机间的底层通信,向上层提供与硬件相关操作的回调函数。Gadget APIUDC驱动程序回调函数的简单包装,这部分程序内核都已经写好。Gadget驱动程序具体控制USB设备功能的实现,使设备表现出“U盘”、“虚拟串口”等特性。

   简单看个usb 虚拟串口例子

Overview
--------
The gadget serial driver is a Linux USB gadget driver, a USB device
side driver.  It runs on a Linux system that has USB device side
hardware; for example, a PDA, an embedded Linux system, or a PC
with a USB development card.
 
The gadget serial driver talks over USB to either a CDC ACM driver
or a generic USB serial driver running on a host PC.
 
   Host
     --------------------------------------
  | Host-Side   CDC ACM       USB Host   |
  | Operating |   or        | Controller |   USB
  | System    | Generic USB | Driver     |--------
  | (Linux or | Serial      | and        |        |
  | Windows)    Driver        USB Stack  |        |
   --------------------------------------         |
                                                  |
                                                  |
                                                  |
   Gadget                                         |
   --------------------------------------         |
  | Gadget                   USB Periph. |        |
  | Device-Side |  Gadget  | Controller  |        |
  | Linux       |  Serial  | Driver      |--------
  | Operating   |  Driver  | and         |
  | System                   USB Stack   |
   --------------------------------------

On the device-side Linux system, the gadget serial driver looks
like a serial device.
 
On the host-side system, the gadget serial device looks like a
CDC ACM compliant class device or a simple vendor specific device
with bulk in and bulk out endpoints, and it is treated similarly
to other serial devices.
 
The host side driver can potentially be any ACM compliant driver
or any driver that can talk to a device with a simple bulk in/out
interface.  Gadget serial has been tested with the Linux ACM driver,
the Windows usbser.sys ACM driver, and the Linux USB generic serial
driver.
 
With the gadget serial driver and the host side ACM or generic
serial driver running, you should be able to communicate between
the host and the gadget side systems as if they were connected by a
serial cable.
 
The gadget serial driver only provides simple unreliable data
communication.  It does not yet handle flow control or many other
features of normal serial devices
.


内核版本:3.15                    硬件:ATMEL  SAMA5D3            编译环境:ubuntu 12.04


1、配置内核


这里之所以都选择为模块的形式,是为了调试方便,有些模块,比如U盘加载时还需要提供介质,就是说加载模块时还需要参数,否则加载不上

   Device Drivers  ---> 

   [*] USB support  ---> 

 <*>   USB Gadget Support  --->  

 <M>   USB Gadget Drivers                                                                            
                             < >     USB functions configurable through configfs                                             
                           < >     Gadget Zero (DEVELOPMENT)                                                                    
                             < >     Ethernet Gadget (with CDC Ethernet support)                                                
                              < >     Network Control Model (NCM) support                                                         
                             < >     Gadget Filesystem                                                                            
                             < >     Function Filesystem                                                                      
                             < >     Mass Storage Gadget                                                                           
                             < >     USB Gadget Target Fabric Module                                                            
                               <M>     Serial Gadget (with CDC ACM and CDC OBEX support)                                          
                               < >     Printer Gadget      

保存退出,编译内核。在drivers/usb/gadget目录下会生成以下驱动文件

-rw-rw-r-- 1 a_tu a_tu  9710  3月  5 15:14 ./g_serial.ko
-rw-rw-r-- 1 a_tu a_tu 49319  3月  5 15:14 ./libcomposite.ko
-rw-rw-r-- 1 a_tu a_tu 11473  3月  5 15:14 ./usb_f_acm.ko
-rw-rw-r-- 1 a_tu a_tu  9485  3月  5 15:14 ./usb_f_obex.ko
-rw-rw-r-- 1 a_tu a_tu  8011  3月  5 15:14 ./usb_f_serial.ko
-rw-rw-r-- 1 a_tu a_tu 15970  3月  5 15:14 ./u_serial.ko


2、操作开发板


把编译好的内核烧入开发板,加载生成的驱动文件,注意加载顺序,否则会出现错误。

insmod  u_serial.ko
insmod  libcomposite.ko
insmod   usb_f_serial.ko
insmod  usb_f_obex.ko
insmod  usb_f_acm.ko
insmod  g_serial.ko

出现内核信息如下:

[   27.310000] --------file=composite.c-------usb_composite_probe------1830
[   27.320000] ------------402
[   27.320000] -----usb_gadget_probe_driver------411
[   27.330000] -------udc_bind_to_driver-----342
[   27.330000] g_serial gadget: Gadget Serial v2.4
[   27.340000] g_serial gadget: g_serial ready

[   18.960000] g_serial gadget: high-speed config #2: CDC ACM config

说明加载成功。

此时你打开设备管理器会发现多了一个串口设备,

ELMO GMAS(COM10)

Linux USB虚拟串口设备

Win7操作系统可以自动加载基于udc标准的serial驱动。

对于WinXP操作系统,要使用ACM串口,需要WindowsXP机器上有gserial.inf和usbser.sys这两个文件,其中gserial.inf的配置如下:

[Version] 
  Signature='$Windows NT$' 
  Class=Ports 
  ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} 
  Provider=%LINUX% 
  DriverVer=08/17/2004,0.0.2.0 
  ; Copyright (C) 2004 Al Borchers (alborchers@steinerpoint.com) 

  [Manufacturer] 
  %LINUX%=GSerialDeviceList 

  [GSerialDeviceList] 
  %GSERIAL%=GSerialInstall, USB\VID_0525&PID_A4A7 

  [DestinationDirs] 
  DefaultDestDir=10,System32\Drivers 

  [GSerialInstall] 
  CopyFiles=GSerialCopyFiles 
  AddReg=GSerialAddReg 

  [GSerialCopyFiles] 
  usbser.sys 

  [GSerialAddReg] 
  HKR,,DevLoader,,*ntkern 
  HKR,,NTMPDriver,,usbser.sys 
  HKR,,EnumPropPages32,,'MsPorts.dll,SerialPortPropPageProvider' 

  [GSerialInstall.Services] 
  AddService = usbser,0x0002,GSerialService 

  [GSerialService] 
  DisplayName = %GSERIAL_DISPLAY_NAME% 
  ServiceType = 1 ; SERVICE_KERNEL_DRIVER 
  StartType = 3 ; SERVICE_DEMAND_START 
  ErrorControl = 1 ; SERVICE_ERROR_NORMAL 
  ServiceBinary = %10%\System32\Drivers\usbser.sys 
  LoadOrderGroup = Base 

  [Strings] 
  LINUX = 'Linux' 
  GSERIAL = 'Gadget Serial' 
  GSERIAL_DISPLAY_NAME = 'USB Gadget Serial Driver'

安装成功后,在设备管理器中可以看到 “Gadget Serial (COM11) '这个端口。


开发板的/dev/下会出现/dev/ttyGS0这个设备。当然如果你怕这个设备重名,可以更改这个设备节点。操作如下:

cat /proc/devices

Character devices:
  1 mem
  2 pty
  3 ttyp
  4 /dev/vc/0
  4 tty
  4 ttyS
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
  7 vcs
 10 misc
 13 input
 90 mtd
128 ptm
136 pts
153 spi
251 ttyGS

mknod /dev/usb_serial c 254 0

以后可以直接按照串口通讯的方式打开该节点 /dev/usb_serial ,进行数据读写操作。



3、通信测试


开发板上执行命令  cat /dev/usb_serial(当然你也可以编写程序,打开设备读写),这里只是简单的测试设备通信是否正常 ,pc机上打开串口调试助手,打开com10,通过字符串输入框发送数据。此时发现开发板没有收到数据,而串口助手却收到自己发送的数据。这让我很是纳闷,折腾了2天,终于睡醒了。

又测试了另一通路:开发板给pc发。echo 12345 > /dev/usb_serial 

这是完全正常的,通过串口助手收到的数据来看。每次收到的数据都有换行现象,会不会是数据没有从缓冲区中刷出来?我就换了数据格式,发送简单文件

111111111111111111
222222222222222222
222222222222222222
444444444444444444

此时开发板收到数据

# cat /dev/usb_serial 
111111111111111111
222222222222222222
222222222222222222
444444444444444444

原来真的是 "\n" 在作怪!!!,如果你的文件只有一行,且没有换行。那么你的开发板是收不到数据的,这些数据并没有丢失,而是存储在串口的缓冲区中,直到遇到 "\n",才会把数据一股脑发出来。

至此测试完毕。

本人水平有限,文章仅代表个人观点,如有错误,请指正!!!