02 November 2018
Writing Your Own Gadget
Andrei Emeltchenko
Contents
▪ Introduction
▪ General USB
▪ Using Ethernet over USB
▪ Using 802.15.4 over USB
▪ Other USB usages
▪ Experimental USB features: WebUSB
▪ Debugging without the board
▪ Summary
▪ References
2
Introduction: Problem
▪ Devices around (sensors, switches, etc)
▪ Problem connecting to devices with non standard PC interfaces
○ SPI, I2C, etc
Access
Complex Hardware
3
Introduction: Solution
▪ Use embedded board with special interfaces powered by Zephyr OS
▪ Zephyr board connects to Host via USB
Zephyr gadget
Interface
USB
Complex Hardware
4
Introduction: Zephyr
▪ Open Source RTOS for connected resource constrained devices
https://www.zephyrproject.org/what-is-zephyr/
▪ Hosted by Linux Foundation
▪ Supported more then 100 boards:
https://docs.zephyrproject.org/latest/boards/boards.html
▪ Zephyr Project Documentation https://docs.zephyrproject.org/latest/index.html
▪ License: Apache 2.0
▪ Source:
https://github.com/zephyrproject-rtos/zephyr
5
Hello world in Zephyr
▪ Set up a development system
https://docs.zephyrproject.org/latest/getting_started/getting_started.html#set-up-a-development-system
▪ Set up build environment
$ source zephyr-env.sh
▪ Build hello_world sample for Qemu ▪ Run hello_world in Qemu
$ cd samples/hello_world/ $ make run
$ mkdir build
$ cd build To exit from QEMU enter: 'CTRL+a, x'
# Use cmake to configure a Make-based build [QEMU] CPU: qemu32,+nx,+pae
$ cmake -DBOARD=qemu_x86 ..
# Now run make on the generated build system: ***** Booting Zephyr OS zephyr-v1.13.0 *****
$ make Hello World! qemu_x86
6
USB: General overview
▪ One Host connected to many devices Device Descriptor
▪ Device identifies itself through
Descriptors Endpoint Descriptor 1
▪ Descriptors are binary data ...
describing USB capabilities Endpoint Descriptor N
○ Device Class Interface Descriptor 1
○ Product ID / Vendor ID ...
Interface Descriptor N
○ Configuration, Interfaces,
Endpoints Configuration Descriptor 1
▪ Endpoints are communication
...
channels between Host and Device Configuration Descriptor N
7
Programming USB gadgets: Standard Classes
▪ Basic USB Device Classes supported by Zephyr Device Stack
○ Can be enabled in Zephyr application via menuconfig
8
Programming USB gadgets: Custom Device
Define Device Descriptors Define Endpoints and config data and enable
static const struct dev_common_descriptor { static struct usb_ep_cfg_data ep[] = {
struct usb_device_descriptor device_descriptor; {
struct usb_cfg_descriptor configuration_descr; .ep_cb = bulk_in,
struct usb_device_config { .ep_addr = ENDP_BULK_IN
struct usb_if_descriptor if0; },
struct usb_ep_descriptor if0_in_ep; };
} __packed device_configuration; static struct usb_cfg_data config = {
} __packed desc = { .usb_device_description = (u8_t *)&desc,
.device_descriptor = { .cb_usb_status = status_cb,
.bDeviceClass = CUSTOM_CLASS, .interface = {
.idVendor = sys_cpu_to_le16((u16_t)CONFIG_USB_DEVICE_VID), .vendor_handler = NULL,
.idProduct = sys_cpu_to_le16((u16_t)CONFIG_USB_DEVICE_PID), .class_handler = NULL,
.bcdDevice = sys_cpu_to_le16(BCDDEVICE_RELNUM), .custom_handler = NULL,
}, },
.device_configuration = { .num_endpoints = ARRAY_SIZE(ep),
.if0 = { .endpoint = ep,
.bInterfaceClass = CUSTOM_CLASS, };
.bInterfaceSubClass = WPANUSB_SUBCLASS,
.bInterfaceProtocol = WPANUSB_PROTOCOL,
}, /* Initialize the USB driver with the right configuration */
.if0_in_ep = { ret = usb_set_config(&wpanusb_config);
.bEndpointAddress = ENDP_BULK_IN,
.bmAttributes = USB_DC_EP_BULK, /* Enable USB driver */
... ret = usb_enable(&wpanusb_config);
9
Ethernet over USB: Use case
Browser Zephyr app
Apps: DNS / LLMNR / MDNS / CoAP / MQTT / HTTP http server
Transport Layer: UDP / TCP
Host PC Zephyr gadget
Network Layer: IPv4 / IPv6
Physical Layer: ECM / EEM / RNDIS Ethernet frames
USB
10
Ethernet over USB: Standards
▪ Motivation: Application independent data exchange
▪ Standards:
○ Microsoft Remote NDIS (RNDIS)
○ Communications Device Class (CDC) protocols
■ Ethernet Control Model (ECM)
■ Ethernet Emulation Model (EEM)
■ Network Control Model (NCM)
▪ macOS supports CDC ECM
▪ MS Windows supports RNDIS
▪ Linux support all protocols
11
Ethernet over USB: Enabling in Zephyr
▪ Zephyr supports RNDIS, ECM and EEM
▪ Simple configuration: protocols are implemented in USB Device Stack
○ User only need to select Ethernet over USB checkboxes
12
Ethernet over USB: Zero configuration
● IPv4 address autoconfiguration for Host and Zephyr
IcannIan_00:53:01 Broadcast |
| | |
| Who has 169.254.81.1 | | ARP: Who has 169.254.81.199? Tell 0.0.0.0
|----------------------------->| |
| Gratuitous ARP | | ARP: Gratuitous ARP for 169.254.81.199 (Request)
|----------------------------->| |
● Link Local Multicast Name Resolution (LLMNR)
Host 224.0.0.252 Zephyr |
| | | |
| Standard query A zephyr | | | LLMNR: Standard query A zephyr
|------------------------->| | |
| Standard query resp A zephyr 169.254.9.70 | | LLMNR: Standard query response
|<---------------------------------------------| | A zephyr A 169.254.9.70
● zephyr can now be used as a hostname
13
Ethernet over USB: HTTP server app
Zephyr app + extra configuration Host PC
# USB Device settings
CONFIG_USB=y Ethernet over
CONFIG_USB_DEVICE_STACK=y
USB overlay
# Select USB Configurations config
CONFIG_USB_DEVICE_NETWORK_ECM=y
# Zero Configuration
CONFIG_NET_IPV4_AUTO=y Zero
CONFIG_NET_HOSTNAME_ENABLE=y WEB GUI for Zephyr app
CONFIG_DNS_RESOLVER=y Configuration
CONFIG_LLMNR_RESOLVER=y overlay config
CONFIG_LLMNR_RESPONDER=y
$ cmake ... -DOVERLAY_CONFIG=overlay-netusb.conf
Sample README https://docs.zephyrproject.org/latest/samples/net/http_server/README.html
14
Ethernet over USB: border router app
▪ Border Router connects networks with different routing domains
▪ Zephyr capabilities:
○ Multiple interfaces
○ Routing
USB
Zephyr
border router
radio
some custom radio network
15
Ethernet over USB Drivers: Linux
▪ ECM, EEM, RNDIS protocols are all supported by Linux
16
Ethernet over USB Drivers: Windows
▪ Only MS RNDIS is supported
▪ RNDIS gadget may be recognized as Serial / COM
○ Device Class / Subclass matches usbser.inf
17
OS Drivers for Zephyr USB: OS Descriptors
▪ Microsoft OS Descriptors help to autoconfigure MS Windows driver
○ Implemented for RNDIS at the moment
○ Tested with MS Windows 8.1 / 10
MS Windows Zephyr
Windows INF files Compatible ID Subcompatible ID
OS
INF Descriptors RNDIS 5162001
INF
rndiscmp.inf USB\MS_COMP_RNDIS&MS_SUBCOMP_5162001
Compatibe ID: https://docs.microsoft.com/en-us/windows-hardware/drivers/install/compatible-ids
18
IEEE802.15.4 USB: Use case
Access IEEE802.15.4 network
Zephyr gadget
▪ Only one USB 802.15.4 transceiver is supported
802.15.4
by Linux (atusb)
USB
19
IEEE802.15.4 USB gadget
▪ A board with 802.15.4 radio and USB might be used as a USB adapter
○ Board, radio and USB shall be supported by Zephyr
Board used:
Intel C1000 Eval Kit
● TI CC2520 802.15.4 radio
module connected over SPI
● DW USB controller
Source code: https://github.com/zephyrproject-rtos/zephyr/tree/master/samples/net/wpanusb
20
Low Power Wireless Linux stack
Linux
Applications
IPv6
6LoWPAN
802.15.4 MAC
802.15.4 driver SPI
802.15.4 Hardware
Raspberry Pi + OpenLabs Atmel AT86RF233 radio
21
IEEE802.15.4 USB gadget
Linux Zephyr gadget
Applications
SPI
802.15.4 radio
IPv6
6LoWPAN 802.15.4 driver
802.15.4 MAC wpanusb application
wpanusb driver USB
USB
22
IEEE802.15.4 USB gadget: API
Zephyr 802154 Driver API Linux 802154 SoftMAC API
struct ieee802154_radio_api { struct ieee802154_ops {
... ...
int (*start)(struct device *dev); int (*start)(struct ieee802154_hw *hw);
int (*stop)(struct device *dev); void (*stop)(struct ieee802154_hw *hw);
int (*tx)(struct device *dev, int (*xmit_async)(struct ieee802154_hw *hw,
struct net_pkt *pkt, struct sk_buff *skb);
struct net_buf *frag); int (*set_channel)(struct ieee802154_hw *hw,
int (*set_channel)(struct device *dev, u8 page, u8 channel);
u16_t channel); int (*set_txpower)(struct ieee802154_hw *hw,
int (*set_txpower)(struct device *dev, s16_t dbm); s32 mbm);
... ...
} __packed; };
opcode: SET_CHANNEL setup.bRequest data
USB
parameters: channel, page opcode parameters
23
IEEE802.15.4 USB: Linux driver
▪ SoftMAC driver similar to atusb Linux kernel driver
▪ Protocol defined:
https://github.com/zephyrproject-rtos/zephyr/blob/master/samples/net/wpanusb/
wpan-radio-spec.txt
▪ Vendor specific class - driver loads on specific Product ID / Vendor ID pair
▪ Zephyr has own Vendor ID (0x2FE3)
https://docs.zephyrproject.org/latest/subsystems/usb/usb.html#usb-vendor-and-
product-identifiers
▪ Source code: https://github.com/finikorg/wpanusb
24
IEEE802.15.4 atusb vs wpanusb protocol
atusb wpanusb
▪ Vendor - dependent protocol ▪ Vendor - independent GENERIC
protocol
Linux ieee802154_ops.set_channel
setup.bRequest data data setup.bRequest data data
ATUSB_REG_WRITE SR_CHANNEL channel SET_CHANNEL page channel
25
IEEE802.15.4 USB: Linux driver
#!/bin/sh
usb-devices output for the gadget: PHY=`iwpan phy | grep wpan_phy | cut -d' ' -f2`
CHAN=${1:-20}
T: Bus=01 Lev=03 Prnt=03 Port=01 Cnt=01 Dev#= 23 Spd=12 MxCh= 0 echo 'Using phy' $PHY 'channel' $CHAN
D: Ver= 1.10 Cls=ff(vend.) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 iwpan dev wpan0 set pan_id 0xabcd
P: Vendor=2fe3 ProdID=0101 Rev=00.11 iwpan dev wpan0 set short_addr 0xbeef
C: #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr=100mA iwpan phy $PHY set channel 0 $CHAN
I: If#= 0 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=00 Prot=00 Driver=wpanusb ip link add link wpan0 name lowpan0 type lowpan
ip link set wpan0 up
ip link set lowpan0 up
interfaces needed for IPv6 communication
20: wpan0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 123 qdisc pfifo_fast state UNKNOWN group default qlen 300
link/ieee802.15.4 6e:18:24:17:8c:e4:ef:88 brd ff:ff:ff:ff:ff:ff:ff:ff
21: lowpan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1280 qdisc noqueue state UNKNOWN group default qlen 1000
link/[825] 6e:18:24:17:8c:e4:ef:88 brd ff:ff:ff:ff:ff:ff:ff:ff
inet6 fe80::6c18:2417:8ce4:ef88/64 scope link
valid_lft forever preferred_lft forever
26
Other USB usages
▪ Human Interface Device (HID)
▪ Device Firmware Upgrade (DFU)
▪ Mass storage over USB
▪ Serial Port over USB
▪ 802.15.4 “serial radio” protocol
○ 802.15.4 frames over Serial USB
○ Works with Contiki native border router app
https://github.com/contiki-os/contiki/tree/master/examples/ipv6/native-bor
der-router
▪ Bluetooth USB adapter
○ Bluetooth HCI RAW access is used to send HCI over USB
○ Bluetooth USB Transport Layer Spec. (bluetooth.org)
27
WebUSB: Use case
WebUSB Notification when device is connected WebUSB Device Chooser
28
WebUSB: API & Zephyr support
▪ Simple WebUSB API
// Select configuration #1 for the device
device.selectConfiguration(1)
https://wicg.github.io/webusb/
▪ Works with recent Chrome // Request exclusive control over interface #2
▪ USB Device direct access
device.claimInterface(2)
▪ USB Device announce support by // Waiting for 64 bytes of data from endpoint #3
including special Descriptor device.transferIn(3, 64)
▪ Vendor - Specific Request specified // Send Control Transfer
▪ Zephyr supports WebUSB device.controlTransferOut({
requestType: 'class',
recipient: 'interface',
request: 0x22,
value: 0x01,
index: 0x02})
Zephyr WebUSB app https://github.com/zephyrproject-rtos/zephyr/tree/master/samples/subsys/usb/webusb
29
Debugging Zephyr USB app without a hardware
▪ Zephyr app and kernel run as a native Linux console application
○ native_posix board: https://docs.zephyrproject.org/latest/boards/posix/
▪ Virtual USB controller over USBIP protocol
○ Zephyr is a server which decapsulates USBIP packets into USB requests
handled by Zephyr
○ Linux is a client which uses VHCI driver which encapsulate USB requests
to USBIP packets
30
Virtual USB Controller over USB/IP
Client Server Server
userspace
usbip daemon
Application Zephyr native_posix
listens TCP:3240
Linux console app
TCP:3240
USB Devices Stub Driver USB Device Class
Linux kernel
Drivers
USB Core USB Core USB Device Core
Virtual Host Host Controller Virtual Controller
Controller Driver Driver Driver
VC Adaptation
Host Controller listens TCP:3240
Hardware
USB device
31
Zephyr Virtual USB Controller: Attaching
$ sudo modprobe vhci-hcd Load USB/IP Virtual Host Controller driver
$ lsof -i -P | grep zephyr Run Zephyr app and verify USBIP
zephyr.ex 13633 niko 4u IPv4 32089735 0t0 TCP *:3240 (LISTEN) listening socket
$ usbip list -r localhost List exportable USB devices with usbip list
Exportable USB devices
======================
- 127.0.0.1
1-1: unknown vendor : unknown product (2fe3:0100)
: /sys/devices/pci0000:00/0000:00:01.2/usb1/1-1
: (Defined at Interface level) (00/00/00)
: 0 - Human Interface Device / No Subclass / None(03/00/00)
$ sudo usbip attach -r localhost -b 1-1
Attach exportable device to the Host
$ lsusb -d 2fe3:0100 Verify USB device attached to the Host
Bus 007 Device 013: ID 2fe3:0100
32
Zephyr Virtual USB Controller: Linux logs
vhci_hcd vhci_hcd.0: USB/IP Virtual Host Controller
Loading Virtual Host
vhci_hcd vhci_hcd.0: new USB bus registered, assigned bus number 7
vhci_hcd: created sysfs vhci_hcd.0 Controller driver
usb usb7: New USB device found, idVendor=1d6b, idProduct=0002
usb usb7: New USB device strings: Mfr=3, Product=2, SerialNumber=1
usb usb7: Product: USB/IP Virtual Host Controller
usb usb7: Manufacturer: Linux 4.15.0-31-generic vhci_hcd
usb usb7: SerialNumber: vhci_hcd.0 Attaching exportable
hub 7-0:1.0: USB hub found device over USB/IP
hub 7-0:1.0: 8 ports detected
usb 7-1: New USB device found, idVendor=2fe3, idProduct=0100
usb 7-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 7-1: Product: Zephyr HID sample
usb 7-1: Manufacturer: ZEPHYR
usb 7-1: SerialNumber: 0.01
input: ZEPHYR Zephyr HID sample as
/devices/platform/vhci_hcd.0/usb7/7-1/7-1:1.0/0003:2FE3:0100.004E/input/input89
hid-generic 0003:2FE3:0100.004E: input,hidraw2: USB HID v1.10 Device [ZEPHYR Zephyr HID sample] on
usb-vhci_hcd.0-1/input0
33
Summary
Zephyr gadget
Interface
USB
Complex Hardware
34
References
Zephyr USB
▪ Zephyr OS https://www.zephyrproject.org/ ▪ How to Create and Program USB Devices
▪ Native Posix board ▪ Microsoft OS Descriptors
https://docs.zephyrproject.org/latest/boards/posix/ https://docs.microsoft.com/en-us/windows-hardware/drivers/u
▪ Zephyr HTTP Server app sbcon/microsoft-defined-usb-descriptors
https://docs.zephyrproject.org/latest/samples/net/http_server/ ▪ WebUSB API https://wicg.github.io/webusb/
README.html ▪ WebUSB Privacy and Security
▪ Zephyr wpanusb app https://developers.google.com/web/updates/2016/03/access-
https://github.com/zephyrproject-rtos/zephyr/tree/master/sam usb-devices-on-the-web#privacy_and_security
ples/net/wpanusb
▪ Zephyr webusb app
https://docs.microsoft.com/en-us/windows-hardware/drivers/u Linux
sbcon/microsoft-defined-usb-descriptors ▪ USB/IP project http://usbip.sourceforge.net/
▪ Linux IEEE 802.15.4 implementation
Contiki
▪ Contiki OS http://www.contiki-os.org/
▪ Contiki native border router
https://github.com/contiki-os/contiki/tree/master/examples/ipv
6/native-border-router
35