RK3399 TypeC配置USB以太网

一、Linux USB驱动总体结构

USB主机、设备与Gadget驱动之Linux USB驱动层次

1.主机侧与设备侧USB驱动

在Linux系统中,提供主机侧和设备侧视角的USB驱动框架,从主机侧看到的USB主机控制器和设备驱动,以及从设备侧看到的设备控制器和Gadget驱动。

  • 主机侧角度
    • 主机侧USB驱动程序包括主机控制器驱动(Host Controller)和设备驱动两类,USB主机控制器驱动程序控制插入其中的USB设备,USB设备驱动程序控制该设备如何作为从设备与主机通信。
    • 驱动分层
      • USB设备驱动层(插入主机上的U盘、鼠标、USB转串口等设备驱动)
      • USB核心层:负责USB驱动管理和协议处理
        • 通过定义一些数据结构、宏和功能函数,向上为设备驱动提供编程接口,向下为USB主机控制器驱动提供编程接口;
        • 维护整个系统的USB设备信息;
        • 完成设备热插拔控制、总线数据传输控制等。
      • USB主机控制器驱动
      • USB主机控制器硬件
  • 设备侧角度
    • 设备侧USB驱动程序包含设备控制器(Device Controller)驱动和Gadget Function驱动两类。
    • 驱动分层
      • USB设备控制器硬件
      • USB设备控制器驱动程序
        • 直接访问硬件,控制USB设备和主机间的底层通信,向上层提供与硬件相关操作的回调函数。
      • Gadget Function API
        • UDC驱动程序回调函数的简单包装。
        • 把下层的UDC驱动程序和上层的Gadget Function驱动程序隔离开,使得在Linux系统中编写USB设备侧驱动程序时能够把功能的实现和底层通信分离。
      • Gadget(小巧机械装置) Function驱动程序。
        • 控制USB设备功能的实现,使设备表现出“网络连接”、“打印机”或“USBMass Storage”等特性。
image

2.USB设备组织结构

在USB设备组织结构中,从上到下分为设备(device)、配置(config)、接口(interface)和端点(endpoint)四个层次

image
  • 设备

    • 代表一个可以实现插入操作的USB设备

    • 设备描述符

      • USB设备用描述符报告他们的属性,一个描述符是一个已定义格式的数据结构体。每个描述符以一个表示描述符长度的字节和一个表示描述符类型的字节开始。
      • USB描述符信息存储在USB设备中,在枚举过程中,USB主机会向USB设备发送GetDescriptor请求,USB设备在收到这个请求之后,会将USB描述符信息返回给USB主机,USB主机分析返回来的数据,判断出该设备是哪一种USB设备,建立相应的数据链接通道。
    • 标准USB设备类

      Base Class Descriptor Usage Description
      00h Device Use class information in the Interface Descriptors种类信息定义在接口描述符中
      01h Interface Audio音频设备
      02h Both Communications&CDC通信设备
      03h Interface HID(Human Interface Device)人机接口设备
      05h Interface Physical物理设备
      06h Interface Image图像设备
      07h Interface Printer打印机
      08h Interface Mass Storage 大容量存储
      09h Device Hub集线器
      0Ah Interface CDC-Data通信设备
      0Bh Interface Smart Card智能卡
      0Dh Interface Content Security内容安全设备
      0Eh Interface Video视频设备
      0Fh Interface Personal Healthcare个人健康设备
      10h Interface Audio/Video Devices声音/视频设备
      11h Device Billboard Device Class广播牌设备
      12h Interface USB Type-C Bridge Class
      DCh Both Diagnostic Device
      E0h Interface Wireless Controller
      EFh Both Miscellaneous
      FEh Interface Application Specific
  • 配置

    • 在Linux系统中,一个USB设备可以使用多个配置,并且可在各个配置之间进行转换,以改变设备的不同状态。
  • 接口

    • 接口由多个端点组成,一个USB接口代表一个基本的功能,每个USB驱动控制一个接口,一个功能复杂的USB设备可以具有多个接口,设备接口是端点的汇集。
    • 一个配置中的所有接口可以同时有效,并可被不同的驱动程序连接。
  • 端点

    • USB通信的最基本形式是通过端点来实现,一个USB端点只能向一个方向传输数据(从主机到设备或者从设备到主机),可以将端点看作是一个单向的管道。
    • 主机只能通过端点与设备进行通信,以使用设备的功能。在USB系统中每一个端点都有唯一的地址,这是由设备地址和端点号给出的。
    • 在Linux系统中,一个USB端点有4种不同的类型,分别对应着4种不同的数据传送方式。
      • 控制CONTROL: 控制端点被用来控制对USB设备的不同部分进行访问。通常用作配置设备、获取设备信息、发送命令到设备或获取设备状态报告,这些端点通常较小。每个USB设备都有一个控制端点称为“端点0”,被USB核心用来在插入时配置设备。USB协议保证总有足够的带宽留给控制端点传送数据到设备。
      • 中断INTERRUPT:每当USB主机向设备请求数据时,中断端点以固定的速率传送少量的数据。这是为USB键盘和鼠标的主要的数据传送方法,并且还用以传送数据到USB设备的方式来控制设备,此时不用来传送大量数据。USB协议保证总有足够的带宽留给中断端点传送数据到设备。
      • 批量BULK:表示批量端点用以传送大量数据,这些端点常比中断端点大得多。USB协议不保证传输在特定时间范围内完成,如果总线上没有足够的空间来发送整个BULK包,则被分为多个包进行传输。这些端点普遍用于打印机、USB Mass Storage和USB网络设备上。
      • 等时ISOCHRONOUS: 此类型端点也能批量传送大量数据,但是这个数据不被保证能 送达。这些端点用在可以处理数据丢失的设备中,并且更多依赖于保持持续的数据流。如音频和视频设备等。

3.USB设备枚举

在Linux系统中,USB设备枚举的基本步骤如下

  • step 1 将设备插入主机,主机检测到设备,复位设备。

    • 当主机向USB设备控制器发送一个包时,USB设备控制器就会产生相应的中断处理
  • step 2 主机向设备控制端点发送Get_Descriptor,以了解设备默认管道的大小。

  • step 3 主机指定一个地址,发送Set_Address标准请求设置设备的地址。

  • step 4 主机使用新的地址,再次发送Get_Descriptor以获得各种描述符。

  • step 5 主机加载一个USB设备驱动。

  • step 6 USB设备驱动再发送Set_Confuration标准设备请求配置设备。

二、Linux-USB Gadget 简介

在USB_Gadget驱动系统中,Gadget功能驱动层位于整个驱动软件结构的最上层,功能是实现USB设备的功能。此层通常与Linux内核的其他层有密切的联系。

Gadget 框架提出了一套标准 API, 在底层USB 设备控制器驱动实现这一套 API, 不同的 UDC需要不同的驱动。

1.Linux USB Gadget 支持的设备驱动

可以在Linux内核menuconfig中的设备驱动程序→USB支持→USB Gadget支持菜单下找到(在kernel/drivers/usb/gadget路径下)

  • g_zero(CONFIG_USB_ZERO)- 类似于 dummy hcd, 该驱动用于测试 udc 驱动。它会帮助您通过 USB-IF 测试。
  • g_audio(CONFIG_USB_AUDIO)
  • g_etherCONFIG_USB_ETH)-实现“通信设备类”(CDC)以太网设备,以创建“ USB到以太网”网络连接。
  • g_ncmCONFIG_USB_G_NCM)-实现USB CDC NCM子类标准。NCM是用于以太网封装的高级协议,它允许将多个以太网帧分组为一个USB传输。
  • g_mass_storageCONFIG_USB_MASS_STORAGE)-充当USB Mass Storage磁盘驱动程序。其存储库可以使用指定为模块参数或sysfs选项的常规文件或块设备。
  • g_serialCONFIG_USB_G_SERIAL)-充当ACM串行设备以创建“ USB到串行”连接,可用于与MS-Windows主机或Linux-USB“ cdc-acm”驱动程序互操作。
  • g_midi(CONFIG_USB_MIDI_GADGET)-充当具有一个MIDI输入和一个MIDI输出的USB音频设备。
  • g_printer(CONFIG_USB_G_PRINTER)-在USB主机和驱动打印引擎的用户空间程序之间传递数据。
  • g_cdcCONFIG_USB_CDC_COMPOSITE)-在一种配置中提供两种功能:CDC以太网(ECM)链接和CDC ACM(串行端口)链接
  • g_acm_ms(CONFIG_USB_G_ACM_MS)-在一种配置中提供两种功能:USB大容量存储设备和CDC ACM(串行端口)链接
  • g_multiCONFIG_USB_G_MULTI)-多功能复合小工具,可以提供以太网(RNDIS和/或CDC),大容量存储和ACM串行链接接口
  • g_hidCONFIG_USB_G_HID)-人机接口设备(HID)小工具,可为诸如键盘,鼠标,触摸屏之类的事物提供通用接口
  • g_webcam-网络摄像头设备

三、RK3399 TypeC配置USB以太网

基于Firefly-AIO-RK3399C开发板,将设备TypeC接口作为设备模式,然后模拟成USB-CDC-ECM设备(虚拟网卡)。主机通过 USB 连接设备并通过设备访问互联网。

1.修改内核配置

进入内核配置菜单后依次选择:Device Drivers -> USB Support -> USB Gadget Support

USB Gadget Driver 设置成编译进内核,然后可以在下边找到 Ethernet Gadget (with CDC Ethernet support) 选项,同样选择编译进内核,同时要选择上 RNDIS support

<*>   USB Gadget Drivers
<*>     USB functions configurable through configfs
<*>     Ethernet Gadget (with CDC Ethernet support)
[*]       RNDIS support (NEW)

2.修改DTS文件

firefly_rk3399开发板type-c口默认使用的OTG控制器,OTG线与常用的type-c数据线并不相同,普通的type-c充电线CC管脚通过56K电阻上拉到vbus,而OTG数据线通常是通过5.1K电阻下拉到地,因此主板电路,在插入OTG线时,将CC管脚的电平通过MOS管和三极管到ID管脚检测为0V,而插入普通充电线时,ID管脚检测大于1.8V即可,因此,若想用普通充电线做USB-adb使用,可采取将type-c控制器转为普通usb2.0 OTG方式。

$ git diff arch/arm64/boot/dts/rockchip/rk3399-firefly-aioc.dts
--- a/arch/arm64/boot/dts/rockchip/rk3399-firefly-aioc.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-firefly-aioc.dts
@@ -160,6 +160,38 @@
        regulator-max-microvolt = <900000>;
 };
 
+&u2phy0 {
+       status = "okay";
+       /delete-property/ extcon;
+       vbus-supply = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>; /* Vbus GPIO配置 */
+};
+
+&usbdrd3_0 {
+       status = "okay";
+       // extcon = <&fusb0>;
+       extcon = <&u2phy0>;
+};
+
+&usbdrd_dwc3_0 {
+       status = "okay";
+       dr_mode = "peripheral";
+       maximum-speed = "high-speed"; 
+       phys = <&u2phy0_otg>; /* phys 属性只引用USB2 PHY节点 */
+       phy-names = "usb2-phy";
+};
+
+&cdn_dp {
+       status = "disabled";
+};
+
+&tcphy0 {
+       status = "disabled";
+};
+
+&fusb0 {
+       status = "disabled";
+};
+

3.测试USB虚拟网卡

1)设备侧

重新编译并烧录固件后,会在usb0网卡设备

$ ls /sys/class/net/
dummy0  eth0  lo  usb0  wlan0

$ udevadm info -p /sys/class/net/usb0
P: /devices/platform/usb0/fe800000.dwc3/gadget/net/usb0
E: DEVPATH=/devices/platform/usb0/fe800000.dwc3/gadget/net/usb0
E: DEVTYPE=gadget
E: ID_MM_CANDIDATE=1
E: ID_NET_DRIVER=g_ether
E: ID_NET_LINK_FILE=/lib/systemd/network/99-default.link
E: ID_PATH=platform-fe800000.dwc3
E: ID_PATH_TAG=platform-fe800000_dwc3
E: IFINDEX=4
E: INTERFACE=usb0
E: NM_UNMANAGED=1
E: SUBSYSTEM=net
E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/usb0
E: TAGS=:systemd:
E: USEC_INITIALIZED=4860606

# usb 插入主机
$ dmesg | tail -n 10
[  331.356762] phy phy-ff770000.syscon:usb2-phy@e450.1: charger = USB_SDP_CHARGER
[  331.357431] rockchip-dwc3 usb0: USB peripheral connected
[  331.746362] g_ether gadget: high-speed config #2: RNDIS

配置usb0 IP 地址

$ sudo ifconfig usb0 192.168.3.10

$ ifconfig usb0
usb0      Link encap:Ethernet  HWaddr 7e:71:82:2b:92:97  
          inet addr:192.168.3.10  Bcast:192.168.3.255  Mask:255.255.255.0
          inet6 addr: fe80::7c71:82ff:fe2b:9297/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:27 errors:27 dropped:0 overruns:0 frame:27
          TX packets:31 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:5413 (5.4 KB)  TX bytes:5532 (5.5 KB)

2)主机侧

# usb 插入主机,主机出现Linux-USB Ethernet/RNDIS Gadget设备
$ lsusb
...
Bus 001 Device 095: ID 0525:a4a2 Netchip Technology, Inc. Linux-USB Ethernet/RNDIS Gadget
...

$ dmesg |tail -n 10
[7170774.297349] usb 1-12: new high-speed USB device number 95 using xhci_hcd
[7170774.447158] usb 1-12: New USB device found, idVendor=0525, idProduct=a4a2
[7170774.447161] usb 1-12: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[7170774.447163] usb 1-12: Product: RNDIS/Ethernet Gadget
[7170774.447165] usb 1-12: Manufacturer: Linux 4.4.179-gc26d2e0-dirty with dwc3-gadget
[7170774.448216] cdc_subset: probe of 1-12:2.0 failed with error -22
[7170774.450133] rndis_host 1-12:2.0 usb0: register 'rndis_host' at usb-0000:00:14.0-12, RNDIS device, e6:ee:a1:6e:54:bb
[7170774.472140] rndis_host 1-12:2.0 enp0s20f0u12c2: renamed from usb0
[7170774.494267] IPv6: ADDRCONF(NETDEV_UP): enp0s20f0u12c2: link is not ready

$ ls /sys/class/net/
br-887ae21410ef  br-b31ab6e197a8  docker0  eno1  enp0s20f0u12c2  lo  vboxnet0  veth6432db0
    # 出现usb网卡设备usb0,被系统udev重命名为enp0s20f0u12c2

# 配置usb网卡ip,需要与设备侧同一网段,此时二者可以ping通
$ sudo ifconfig enp0s20f0u12c2 192.168.3.11

4.设备端安装DHCP服务

设备端搭建搭建DHCP-Server

如果设备端没有安装dhcp服务,主机插入usb后,生成的虚拟网卡无法动态获取IP,这会导致主机DHCP请求失败而定期清除手动配置的IP地址,影响通信。

# 安装isc-dhcp-server
$ sudo apt update
$ sudo apt install isc-dhcp-server

# 指定网卡
$ sudo vim /etc/default/isc-dhcp-server
INTERFACES="usb0"
    
# 修改配置文件
$ sudo vim /etc/dhcp/dhcpd.conf
ddns-update-style interim;
ignore client-updates;
#authoritative;
allow booting;
allow bootp;
allow unknown-clients;

subnet 192.168.3.0 netmask 255.255.255.0 {
    range 192.168.3.11 192.168.3.250;  # dhcp客户端可以获取的ip范围(非绑定的)
    default-lease-time 6000;                 #为客户机获取网络参数的默认租约时间
    max-lease-time 72000;                    #为客户机获取网络参数之后的最大租约时
    option subnet-mask 255.255.255.0;        #子网掩码
    option routers 192.168.3.1;           #路由
    option domain-name-servers 114.114.114.114; #域名服务器
}

# 测试配置文件
$ sudo dhcpd -d
Server starting service.
DHCPDISCOVER from ba:0a:89:46:0d:82 via usb0
DHCPOFFER on 192.168.3.36 to ba:0a:89:46:0d:82 (jiangxing) via usb0
DHCPREQUEST for 192.168.3.36 (192.168.3.10) from ba:0a:89:46:0d:82 (jiangxing) via usb0
DHCPACK on 192.168.3.36 to ba:0a:89:46:0d:82 (jiangxing) via usb0
    # 自动给主机端分配ip

# 启动 isc-dhcp-server.service服务
sudo systemctl restart isc-dhcp-server.service

# 开机自启动
sudo systemctl enable isc-dhcp-server.service

四、参考

USB On-The-Go(OTG)

Class definitions for Communication Devices 1.2

CDC Subclass Specification for Ethernet Emulation Model Devices 1.0

The GNU/Linux "usbnet" Driver Framework

Linux-USB Gadget API Framework

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容