Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pkg/tinyusb: add tinyUSB netdev driver #18903

Merged
merged 8 commits into from
Feb 3, 2023

Conversation

gschorcht
Copy link
Contributor

@gschorcht gschorcht commented Nov 14, 2022

Contribution description

This PR adds the tinyUSB netdev driver.

The tinyUSB netdev driver is part of the tinyUSB package and is enabled by module tinyusb_netdev. It is available for boards that provide the tinyusb_device feature.

Please note Since the tinyUSB package is distinct from (and incompatible with) the USB stack provided around USBUS in RIOT (see USB), the tinyUSB netdev driver cannot be used together with with any USBUS device class.

The tinyUSB netdev driver uses Ethernet over USB and supports the following protocols:

  • CDC ECM (Ethernet Control Model)
  • CDC NCM (Network Control Model)
  • RNDIS (Microsoft Remote NDIS)

While Linux and macOS support all these protocols, Microsoft Windows only supports the RNDIS protocol and since Windows version 11 also the CDC NCM protocol. macOS supports the RNDIS protocol since version 10.15 (Catalina).

Which protocol is used is selected by the corresponding pseudomodules tinyusb_class_net_cdc_ecm, tinyusb_class_net_cdc_ncm and tinyusb_class_net_rndis.

The CDC ECM protocol (tinyusb_class_net_cdc_ecm) and the RNDIS protocol (tinyusb_class_net_rndis) can be used simultaneously to support all operating systems, for example :

USEMODULE='tinyusb_netdev tinyusb_class_net_rndis tinyusb_class_net_cdc_ecm' \
BOARD=... make -C ... flash

In this case, the CDC ECM protocol is the default protocol and the RNDIS protocol the alternative protocol defined as second device configuration. The CDC NCM protocol cannot be used together with the CDC ECM or the RNDIS protocol.

This PR includes PR #18983 for now to be compilable.

Comparison with USBUS CDC ECM (nucleo-f767zi board):

   text	   data	    bss	    dec	    hex	filename
  65916	    596	  18728	  85240	  14cf8	tests_pkg_tinyusb_netdev.elf
   text	   data	    bss	    dec	    hex	filename
  63120	    544	  15444	  79108	  13504	tests_usbus_cdc_ecm.elf

Testing procedure

Use a board that is supported by tinyUSB. Compile and flash the test application for each protocol:

  1. RNDIS
    BOARD=... make -j8 -C tests/pkg_tinyusb_netdev flash
    
  2. CDC ECM
    CLASS=tinyusb_class_net_cdc_ecm BOARD=... make -j8 -C tests/pkg_tinyusb_netdev flash
    
  3. CDC NCM
    CLASS=tinyusb_class_net_cdc_ncm BOARD=... make -j8 -C tests/pkg_tinyusb_netdev flash
    

For each test, a network interface should be added on the host. Use command ifconfig on USB device and on the host and check that both have a link local address. In syslog there should be an output like the following:

Nov 13 18:14:46 gunny8 kernel: [4611465.480025] usb 1-2.2: new full-speed USB device number 28 using xhci_hcd
Nov 13 18:14:47 gunny8 kernel: [4611465.581641] usb 1-2.2: New USB device found, idVendor=1209, idProduct=7d01, bcdDevice= 1.00
Nov 13 18:14:47 gunny8 kernel: [4611465.581646] usb 1-2.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Nov 13 18:14:47 gunny8 kernel: [4611465.581650] usb 1-2.2: Product: nucleo-f767zi
Nov 13 18:14:47 gunny8 kernel: [4611465.581653] usb 1-2.2: Manufacturer: RIOT-os.org
Nov 13 18:14:47 gunny8 kernel: [4611465.581654] usb 1-2.2: SerialNumber: 6591620BCB270283
Nov 13 18:14:47 gunny8 vmnetBridge: RTM_NEWLINK: name:usb0 index:508 flags:0x00001002
Nov 13 18:14:47 gunny8 vmnet-natd: RTM_NEWLINK: name:usb0 index:508 flags:0x00001002
Nov 13 18:14:47 gunny8 NetworkManager[24229]: <info>  [1668359687.1066] manager: (usb0): new Ethernet device (/org/freedesktop/NetworkManager/Devices/528)
Nov 13 18:14:47 gunny8 kernel: [4611465.594604] rndis_host 1-2.2:1.0 usb0: register 'rndis_host' at usb-0000:00:14.0-2.2, RNDIS device, fa:db:7c:1b:58:80
Nov 13 18:14:47 gunny8 mtp-probe: checking bus 1, device 28: "/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.2"
Nov 13 18:14:47 gunny8 mtp-probe: bus: 1, device: 28 was not an MTP device
Nov 13 18:14:47 gunny8 systemd-udevd[17796]: link_config: autonegotiation is unset or enabled, the speed and duplex are not writable.
Nov 13 18:14:47 gunny8 vmnet-natd: RTM_NEWLINK: name:usb0 index:508 flags:0x00001002
Nov 13 18:14:47 gunny8 kernel: [4611465.643852] rndis_host 1-2.2:1.0 enp0s20f0u2u2: renamed from usb0
Nov 13 18:14:47 gunny8 vmnetBridge: RTM_NEWLINK: name:usb0 index:508 flags:0x00001002
Nov 13 18:14:47 gunny8 vmnet-natd: RTM_NEWLINK: name:enp0s20f0u2u2 index:508 flags:0x00001002
Nov 13 18:14:47 gunny8 vmnetBridge: RTM_NEWLINK: name:enp0s20f0u2u2 index:508 flags:0x00001002
Nov 13 18:14:47 gunny8 NetworkManager[24229]: <info>  [1668359687.1833] device (usb0): interface index 508 renamed iface from 'usb0' to 'enp0s20f0u2u2'
Nov 13 18:14:47 gunny8 upowerd[2845]: unhandled action 'bind' on /sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.2/1-2.2:1.1
Nov 13 18:14:47 gunny8 NetworkManager[24229]: <info>  [1668359687.2037] device (enp0s20f0u2u2): state change: unmanaged -> unavailable (reason 'managed', sys-iface-state: 'external')
Nov 13 18:14:47 gunny8 vmnet-natd: RTM_NEWLINK: name:enp0s20f0u2u2 index:508 flags:0x00011043
Nov 13 18:14:47 gunny8 vmnetBridge: RTM_NEWLINK: name:enp0s20f0u2u2 index:508 flags:0x00011043
Nov 13 18:14:47 gunny8 vmnetBridge: Adding interface enp0s20f0u2u2 index:508
Nov 13 18:14:47 gunny8 NetworkManager[24229]: <info>  [1668359687.2075] device (enp0s20f0u2u2): carrier: link connected
Nov 13 18:14:47 gunny8 upowerd[2845]: unhandled action 'bind' on /sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.2/1-2.2:1.0
Nov 13 18:14:47 gunny8 NetworkManager[24229]: <info>  [1668359687.2129] settings: (enp0s20f0u2u2): created default wired connection 'Kabelgebundene Verbindung 2'
Nov 13 18:14:47 gunny8 NetworkManager[24229]: <warn>  [1668359687.2142] device (enp0s20f0u2u2): connectivity: "/proc/sys/net/ipv4/conf/enp0s20f0u2u2/rp_filter" is set to "1". This might break connectivity checking for IPv4 on this device
Nov 13 18:14:47 gunny8 NetworkManager[24229]: <info>  [1668359687.2151] device (enp0s20f0u2u2): state change: unavailable -> disconnected (reason 'none', sys-iface-state: 'managed')
Nov 13 18:14:47 gunny8 vmnetBridge: RTM_NEWLINK: name:enp0s20f0u2u2 index:508 flags:0x00011043
Nov 13 18:14:47 gunny8 vmnet-natd: RTM_NEWLINK: name:enp0s20f0u2u2 index:508 flags:0x00011043
Nov 13 18:14:47 gunny8 upowerd[2845]: unhandled action 'bind' on /sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.2
Nov 13 18:14:47 gunny8 systemd-udevd[17796]: link_config: autonegotiation is unset or enabled, the speed and duplex are not writable.
Nov 13 18:14:47 gunny8 NetworkManager[24229]: <info>  [1668359687.2403] policy: auto-activating connection 'Kabelgebundene Verbindung 2' (0b1ae45e-c76e-3efb-a2cd-138ca2b2a59c)
Nov 13 18:14:47 gunny8 NetworkManager[24229]: <info>  [1668359687.2414] device (enp0s20f0u2u2): Activation: starting connection 'Kabelgebundene Verbindung 2' (0b1ae45e-c76e-3efb-a2cd-138ca2b2a59c)
Nov 13 18:14:47 gunny8 NetworkManager[24229]: <info>  [1668359687.2419] device (enp0s20f0u2u2): state change: disconnected -> prepare (reason 'none', sys-iface-state: 'managed')
Nov 13 18:14:47 gunny8 NetworkManager[24229]: <info>  [1668359687.2429] device (enp0s20f0u2u2): state change: prepare -> config (reason 'none', sys-iface-state: 'managed')
Nov 13 18:14:47 gunny8 NetworkManager[24229]: <info>  [1668359687.2440] device (enp0s20f0u2u2): state change: config -> ip-config (reason 'none', sys-iface-state: 'managed')
Nov 13 18:14:47 gunny8 NetworkManager[24229]: <info>  [1668359687.2445] dhcp4 (enp0s20f0u2u2): activation: beginning transaction (timeout in 45 seconds)
Nov 13 18:14:47 gunny8 vmnetBridge: RTM_NEWLINK: name:enp0s20f0u2u2 index:508 flags:0x00011043
Nov 13 18:14:47 gunny8 vmnet-natd: RTM_NEWLINK: name:enp0s20f0u2u2 index:508 flags:0x00011043
Nov 13 18:14:47 gunny8 avahi-daemon[1464]: Joining mDNS multicast group on interface enp0s20f0u2u2.IPv6 with address fe80::dba4:adb8:9ffe:d93e.
Nov 13 18:14:47 gunny8 avahi-daemon[1464]: New relevant interface enp0s20f0u2u2.IPv6 for mDNS.
Nov 13 18:14:47 gunny8 avahi-daemon[1464]: Registering new address record for fe80::dba4:adb8:9ffe:d93e on enp0s20f0u2u2.*.
Nov 13 18:14:47 gunny8 kernel: [4611465.895046] userif-1: sent link down event.
Nov 13 18:14:47 gunny8 kernel: [4611465.895052] userif-1: sent link up event.

Ping from and to the host.

Issues/PRs references

Depends on PR #18983

@github-actions github-actions bot added Area: doc Area: Documentation Area: drivers Area: Device drivers Area: Kconfig Area: Kconfig integration Area: network Area: Networking Area: pkg Area: External package ports Area: sys Area: System Area: tests Area: tests and testing framework labels Nov 14, 2022
@gschorcht gschorcht added Type: new feature The issue requests / The PR implemements a new feature for RIOT CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Nov 14, 2022
@riot-ci
Copy link

riot-ci commented Nov 14, 2022

Murdock results

✔️ PASSED

ee8dcfe tests: add pkg_tinyusb_netdev for tinyUSB netdec

Success Failures Total Runtime
6811 0 6811 09m:58s

Artifacts

@gschorcht gschorcht requested a review from benpicco November 14, 2022 08:30
@gschorcht gschorcht force-pushed the pkg/tinyusb_netdev branch 5 times, most recently from 1b84d5d to ef78c85 Compare November 15, 2022 07:38
@aabadie aabadie added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Nov 15, 2022
@benpicco
Copy link
Contributor

Needs a rebase now, I'll try to give this a look soon.

@dylad
Copy link
Member

dylad commented Jan 19, 2023

I just tested it on stm32f429i-disco, samr21-xpro and same54-xpro.
A RNDIS interface is mounted and I was able to ping both side for all boards.
I didn't have time yet to look the code in details.

@dylad
Copy link
Member

dylad commented Jan 24, 2023

Feels free to rebase.

I've noticed a weird artifact in lsusb for RNDIS only (see UNRECOGNIZED):

lsusb -v -d 1209:                                           

Bus 001 Device 014: ID 1209:7d01 Generic same54-xpro
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.00
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x1209 Generic
  idProduct          0x7d01 
  bcdDevice            1.00
  iManufacturer           1 RIOT-os.org
  iProduct                2 same54-xpro
  iSerial                 3 A7420FE06DB2CD46
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x004b
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              100mA
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         0
      bInterfaceCount         2
      bFunctionClass        224 Wireless
      bFunctionSubClass       1 Radio Frequency
      bFunctionProtocol       3 RNDIS
      iFunction               0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass       224 Wireless
      bInterfaceSubClass      1 Radio Frequency
      bInterfaceProtocol      3 RNDIS
      iInterface              4 
      ** UNRECOGNIZED:  05 24 00 10 01
      ** UNRECOGNIZED:  05 24 01 00 01
      ** UNRECOGNIZED:  04 24 02 00
      ** UNRECOGNIZED:  05 24 06 00 01
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval               1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 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     0x0040  1x 64 bytes
        bInterval               0

@dylad
Copy link
Member

dylad commented Jan 24, 2023

In addition, USEMODULE='tinyusb_class_net_cdc_ncm' BOARD=same54-xpro make -C tests/pkg_tinyusb_netdev flash -j16
won't compile.

@gschorcht
Copy link
Contributor Author

>       ** UNRECOGNIZED:  05 24 00 10 01
>       ** UNRECOGNIZED:  05 24 01 00 01
>       ** UNRECOGNIZED:  04 24 02 00
>       ** UNRECOGNIZED:  05 24 06 00 01

These bytes are part of the interface descriptor as generated by the tinyUSB RNDIS Descriptor Template macro:

  /* CDC-ACM Header */\
  5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\
  /* CDC Call Management */\
  5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\
  /* ACM */\
  4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 0,\
  /* CDC Union */\
  5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\

Either the macro is incorrect or the descriptor is not decoded correctly by the Linux kernel driver. I would tend to the latter. But either way, I'm afraid there's not much we can do to fix it.

@gschorcht
Copy link
Contributor Author

I have rebased the PR to resolve the conflicts. I have also provided some small fixes.

@dylad
Copy link
Member

dylad commented Feb 1, 2023

I'll re-test tonight.

@dylad
Copy link
Member

dylad commented Feb 1, 2023

Please squash.

@dylad
Copy link
Member

dylad commented Feb 1, 2023

Either the macro is incorrect or the descriptor is not decoded correctly by the Linux kernel driver.

Looks like TinyUSB changes the class/subclass/protocol trio because of Windows (probably for compatibility reason ?)

#if 0
/* Windows XP */
#define TUD_RNDIS_ITF_CLASS    TUSB_CLASS_CDC
#define TUD_RNDIS_ITF_SUBCLASS CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL
#define TUD_RNDIS_ITF_PROTOCOL 0xFF /* CDC_COMM_PROTOCOL_MICROSOFT_RNDIS */
#else
/* Windows 7+ */
#define TUD_RNDIS_ITF_CLASS    TUSB_CLASS_WIRELESS_CONTROLLER
#define TUD_RNDIS_ITF_SUBCLASS 0x01
#define TUD_RNDIS_ITF_PROTOCOL 0x03
#endif

Linux is happy with Windows XP value but not with the default value. I guess there is nothing we can do on our side for this.

@gschorcht
Copy link
Contributor Author

gschorcht commented Feb 1, 2023

Linux is happy with Windows XP value but not with the default value. I guess there is nothing we can do on our side for this.

RNDIS is primarily intended for use under Windows so I think we can accept the problem in Linux.

@dylad
Copy link
Member

dylad commented Feb 2, 2023

RNDIS is primarily intended for use under Windows so I think we can accept the problem in Linux.

I guess so. I'll give it a try on a Windows laptop tonight.
If we're all good, let's merge it tonight.

@dylad
Copy link
Member

dylad commented Feb 2, 2023

@gschorcht
Were you able to test RNDIS on a Windows host on your side ?
The only windows laptop I have, has a picky USB...
Just want to make sure that's my laptop fault.

@gschorcht
Copy link
Contributor Author

Were you able to test RNDIS on a Windows host on your side ?

I don't have any native Windows system. I tested it with my VirtualBox Windows 10. It seems to work.

main(): This is RIOT! (Version: 2023.04-devel-240-gee8dc-pkg/tinyusb_netdev)
Test application for the tinyUSB net device interface

This test pulls in parts of the GNRC network stack, use the
provided shell commands (i.e. ifconfig, ping) to interact with
the tinyUSB based network interface.

Starting the shell now...
> ifconfig
Iface  5  HWaddr: A6:89:4E:EC:81:6C 
          L2-PDU:1500  MTU:1500  HL:64  RTR  
          RTR_ADV  
          Source address length: 6
          Link type: wired
          inet6 addr: fe80::a489:4eff:feec:816c  scope: link  VAL
          inet6 group: ff02::2
          inet6 group: ff02::1
          inet6 group: ff02::1:ffec:816c

esp32s3-devkit_rndis_02

esp32s3-devkit_rndis_01

Copy link
Member

@dylad dylad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK.

@dylad
Copy link
Member

dylad commented Feb 3, 2023

bors merge

@bors
Copy link
Contributor

bors bot commented Feb 3, 2023

Build succeeded:

@bors bors bot merged commit 0fb6a09 into RIOT-OS:master Feb 3, 2023
@gschorcht
Copy link
Contributor Author

Thanks for reviewing and testing.

@gschorcht gschorcht deleted the pkg/tinyusb_netdev branch February 3, 2023 21:07
@MrKevinWeiss MrKevinWeiss added this to the Release 2023.04 milestone Apr 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: doc Area: Documentation Area: drivers Area: Device drivers Area: Kconfig Area: Kconfig integration Area: network Area: Networking Area: pkg Area: External package ports Area: sys Area: System Area: tests Area: tests and testing framework CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Type: new feature The issue requests / The PR implemements a new feature for RIOT
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants