http://www.myexception.cn/linux-unix/1853061.html
Linux内核中usb设备侧驱动程序分成3个层次:UDC驱动程序、Gadget API和Gadget驱动程序。UDC驱动程序(USB控制器)直接访问硬件,控制USB设备和主机间的底层通信,向上层提供与硬件相关操作的回调函数。Gadget API是UDC驱动程序回调函数的简单包装,这部分程序内核都已经写好。Gadget驱动程序具体控制USB设备功能的实现,使设备表现出“U盘”、“虚拟串口”等特性。
简单看个usb 虚拟串口例子
内核版本: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 use_acm=0
出现内核信息如下:
[ 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)
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”,才会把数据一股脑发出来。
至此测试完毕。