EMAC OE USB Gadget Connections
Many of EMAC's ARM based products provide the capability of using them as USB devices via a USB cable. The USB connection can be used for communication or USB device emulation. This can be especially useful in situations when Ethernet or serial connection is not readily available. For instance, field updates can be performed on a device without interrupting possibly critical Ethernet or serial communications.
The Linux USB Gadget API was developed to make it easier to provide such USB device services. This page covers the process of establishing a connection using the Gadget Ethernet and Serial drivers. More information regarding the USB Gadget drivers for Linux can be found at the Linux USB Project.
USB Gadget Ethernet
The USB Gadget Ethernet driver allows a device to enumerate and communicate as an Ethernet device over the USB link. On the host system, this requires the usbnet driver for a Linux system or the RNDIS driver for Windows hosts.
Device-side Configuration
To establish a connection, first create an entry in the /etc/network/interfaces
file on the device system for the usb0 interface. An example of this configuration is shown below. Note that in almost all circumstances you will need to use a different subnetwork for the USB Ethernet link than what is used for the LAN connection on either the host or device system in order to prevent conflicts.
allow-hotplug usb0 iface usb0 inet static address 192.168.0.2 netmask 255.255.255.0 gateway 192.168.0.1
Host-side Configuration
After the device is configured for a Gadget Ethernet connection it is necessary to configure the host to allow the connection. The configuration will vary depending on the host operating system and flavor. The IP address of the host should be set to the value used for the gateway setting on the device (192.168.0.1 using the example above). An example configuration for a system that uses the /etc/network/interfaces
networking configuration is shown below.
allow-hotplug usb0 iface usb0 inet static address 192.168.0.1 netmask 255.255.255.0 gateway 192.168.0.1
When configured properly the host will present an interface similar to other network interfaces.
Initializing the Connection
Once the configuration is finished and the host and device systems are connected via a USB cable, load the gadget Ethernet driver on the device with the following command:
root@emac-oe:~# modprobe g_ether
After loading the driver, ifconfig
should show an entry for the usb0 interface. Depending on the configuration, you may need to run ifup usb0
to configure the device.
To determine if the device is registered properly you can use ifconfig
as shown below.
root@emac-oe:~# ifconfig usb0 usb0 Link encap:Ethernet HWaddr F2:D5:0C:DC:B4:FB inet addr:192.168.0.2 Bcast:192.168.10.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
The host system will most likely automatically detect and load the appropriate drivers. If this does not occur, verify that the usbnet
driver is installed and loaded on a Linux distribution. See the Microsoft RNDIS driver documentation for more information on configuring this driver for Windows hosts.
Testing the Network Connection
Use the ping
command to test that the connection sends and receives packets correctly. Once this has been verified, you should be able to use any network service to transfer data between the two systems.
Here is an example output from pinging the target from a host system via the USB Ethernet connection:
developer@ldc:~$ ping 192.168.0.2 PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data. 64 bytes from 192.168.0.2: icmp_req=1 ttl=64 time=0.458 ms 64 bytes from 192.168.0.2: icmp_req=2 ttl=64 time=0.464 ms 64 bytes from 192.168.0.2: icmp_req=3 ttl=64 time=0.460 ms 64 bytes from 192.168.0.2: icmp_req=4 ttl=64 time=0.535 ms 64 bytes from 192.168.0.2: icmp_req=5 ttl=64 time=0.376 ms ^C --- 192.168.0.2 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 3997ms rtt min/avg/max/mdev = 0.376/0.458/0.535/0.055 ms
USB Gadget Serial
The USB Gadget Serial driver can be used to emulate a serial port over a USB cable. This can be a useful method for getting serial access to the target machine from a system that does not have a serial port or when there is no spare serial port on the target system to utilize for access. Note that there is limited support for using the USB gadget serial device as a console for accessing the bootloader on most systems, so a hardware serial console is generally required for development.
Device-side Configuration
Serial device connections between the target board and host utilize the g_serial
driver. This allows for data transfer using the standard serial programming API and existing serial terminal applications. Several parameters may be passed to the g_serial
module, as seen in the modinfo listing below:
root@emac-oe:~# modinfo g_serial filename: /lib/modules/2.6.28/kernel/drivers/usb/gadget/g_serial.ko license: GPL author: David Brownell author: Al Borchers description: Gadget Serial v2.4 license: GPL author: Felipe Balbi depends: at91_udc vermagic: 2.6.28 preempt mod_unload ARMv5 parm: idVendor:USB Vendor ID (ushort) parm: idProduct:USB Product ID (ushort) parm: bcdDevice:USB Device version (BCD) (ushort) parm: iManufacturer:USB Manufacturer string (charp) parm: iProduct:USB Product string (charp) parm: iSerialNumber:SerialNumber string (charp) parm: use_acm:Use CDC ACM, default=yes (bool) parm: use_obex:Use CDC OBEX, default=no (bool) parm: n_ports:number of ports to create, default=1 (uint)
In most cases, the default settings will be acceptable and the driver may be loaded using the following command:
root@emac-oe:~# modprobe g_serial
After loading the module, connect a USB cable between the device port and the host machine. Once connected, dmesg
should indicate that the connection was detected and associated with g_serial
.
Host-side Configuration
The host can be running a variety of environments including Linux, Windows, or any other system with a driver implementing the CDC ACM class. This section covers the basic configuration of a Linux host; see the Documentation/usb/gadget_serial.txt file in the Linux kernel source for your target board for detailed information on how to configure both Linux and Windows hosts.
On a Linux PC, the lsusb
command or contents of the /proc/bus/usb/devices
file should indicate that the device is connected and show the vendor and product ID used by the device. On some Linux distributions, a window may be displayed notifying you that it has detected a USB serial connection. If this occurs, you can skip forward to the Testing the Connection section. Otherwise, you will need to register and attach the device.
Registering and Attaching to the Device
To enable serial communication over the USB cable, the cdc_acm
or usbserial
drivers can be registered and associated to the device.
Some distributions, such as Ubuntu, require no configuration on the host side. Test to see if it came up automatically, and only follow these extra steps if required. |
CDC ACM
If the Linux host system is configured to use the ACM driver and the g_serial
driver on the device is loaded in ACM mode (the default), the host system should automatically load the cdc_acm
driver, connect to the device, and create the required device node (/dev/ttyACM0
unless other ACM devices are registered on the system). The partial dmesg output below illustrates this connection being detected and created:
developer@emac-ldc:~# dmesg | tail usb 2-1.3: New USB device found, idVendor=0525, idProduct=a4a7 usb 2-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0 usb 2-1.3: Product: Gadget Serial v2.4 usb 2-1.3: Manufacturer: Linux 2.6.28 with at91_udc usb 2-1.3: configuration #2 chosen from 1 choice cdc_acm 2-1.3:2.0: This device cannot do calls on its own. It is not a modem. cdc_acm 2-1.3:2.0: ttyACM0: USB ACM device
Generic USB Serial
In order to use the generic USB serial driver, the target device should be configured to use the generic serial configuration rather than ACM mode. This can be done by passing use_acm=0
as an option when the g_serial
driver is loaded.
You must explicitly specify the device that the usbserial
driver will be associated with using a pair of ID numbers. In this example, the vendor ID for the device is 0x0525 and the product ID is 0xA4A6. These IDs may vary depending on the device. Use the contents of /proc/bus/usb/devices
to verify the correct ID values and pass these to the usbserial
driver as shown in the example below:
developer@emac-ldc:~# sudo modprobe usbserial vendor=0x0525 product=0xA4A6
The kernel messages should indicate that the driver has been associated correctly and that the USB serial device node has been created (usually this will be /dev/ttyUSB0
). See the listing below for example dmesg
output.
developer@emac-ldc:~# sudo dmesg | tail usb 4-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 usb 4-2: Product: Gadget Serial usb 4-2: Manufacturer: Linux 2.6.25 with at91_udc usb 4-2: SerialNumber: 0 usbcore: registered new interface driver usbserial drivers/usb/serial/usb-serial.c: USB Serial support registered for generic usbserial_generic 4-2:1.0: generic converter detected usb 4-2: generic converter now attached to ttyUSB0 usbcore: registered new interface driver usbserial_generic drivers/usb/serial/usb-serial.c: USB Serial Driver core
Testing the Connection
To test the USB serial interface, use a standard terminal application such as minicom. The microcom application on the EMAC OE system can be used for the target board interface. The device on the Linux PC will be named /dev/ttyACM0
if using the CDC ACM interface, or /dev/ttyUSB0
if using the generic USB serial driver (assuming that this is the only USB serial device connected); the device node on the target system will be /dev/ttyGS0
.
root@emac-oe:~# microcom -s 115200 /dev/ttyGS0 .... developer@emac-ldc:~$ minicom -s
Login Terminal
It is possible to add a login terminal on the USB gadget serial device. Although the getty
can be started manually, typically this would be done through an entry in the /etc/inittab
file. Follow the steps below to configure the system to start a login console on the USB serial gadget connection automatically on boot.
- First, configure the system to load the
g_serial
module automatically on system boot. This can be done using the following command assuming that the root filesystem has been mounted read/write:root@emac-oe:~# echo "g_serial" >> /etc/modules
- Edit
/etc/inittab
to add an entry for the requiredgetty
on the/dev/ttyGS0
device. The following line is an example of this configuration:S1:2345:respawn:/sbin/getty 115200 ttyGS0
- Reboot the board and verify that you can log in to the system through the USB device interface.
For a detailed explanation regarding the syntax for the line which starts the getty , please see this page. This page can be useful for configuring custom applications to run on a serial port, as well. |
Below is an example /etc/inittab with the entry for ttyGS0:
# /etc/inittab: init(8) configuration.
# $Id: inittab,v 1.91 2002/01/25 13:35:21 miquels Exp $
# The default runlevel.
id:5:initdefault:
# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS
# What to do in single-user mode.
~~:S:wait:/sbin/sulogin
# /etc/init.d executes the S and K scripts upon change
# of runlevel.
#
# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevels 2-5 are multi-user.
# Runlevel 6 is reboot.
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
z6:6:respawn:/sbin/sulogin
S:2345:respawn:/sbin/getty 115200 ttyS3
S1:2345:respawn:/sbin/getty 115200 ttyGS0
Other USB Gadget Connections
Several other USB gadget drivers are available, including MIDI, printer, and file storage. See the Linux USB Project and the kernel source for your target device for more information.