USB-ethernet Data Transfers

Name

USB-ethernet Data Transfers -- Exchanging ethernet packets with the USB host

Synopsis

#include <cyg/io/usb/usbs_eth.h>

void usbs_eth_start_rx(usbs_eth* usbseth, unsigned char* buffer, void (*)(usbs_eth*, void*, int) complete_fn, void* complete_data);

void usbs_eth_start_tx(usbs_eth* usbseth, unsigned char* buffer, void (*)(usbs_eth*, void*, int) complete_fn, void* complete_data);

Description

The USB-ethernet package provides two main modes of operation. In the first mode it provides a network device driver for use by a TCP/IP stack running inside the USB peripheral. All incoming ethernet packets should be passed up the TCP/IP stack, and only the stack will generate outgoing packets. Apart from initialization and possibly certain control operations, higher-level code will not interact with the USB-ethernet package directly.

In the second mode there is no TCP/IP stack running inside the USB peripheral. For example, a simple USB-ethernet converter has an ethernet chip and a USB port: ethernet packets received by the ethernet chip need to be forwarded to the USB host, and ethernet packets sent by the USB host need to be sent out of the ethernet chip. usbs_eth_start_rx and usbs_eth_start_tx allow for this lower-level access to the USB-ethernet package.

The two modes of operation are mutually exclusive. If the network device driver mode is enabled then application code should communicate at the TCP/IP level, and not by using the lower-level functions. Instead, it is the network device driver that will make use of these functions, and it assumes that it has exclusive access. The package does not perform any locking.

The transmit and receive functions work in much the same way. The first argument identifies the usbs_eth structure that should be used. For the majority of applications this will be usbs_eth0. The second argument specifies the location of the ethernet packet; outgoing for usbs_eth_start_tx and incoming for usbs_eth_start_rx. This buffer should correspond to the protocol:

  1. Outgoing packets can consist of up to 1516 bytes, consisting of a two-byte header specific to USB-ethernet followed by a standard ethernet frame (a header with 6-byte destination address, 6-byte source address and a further two bytes, followed by a payload of up to 1500 bytes). The two-byte USB-ethernet header consists simply of the size of the ethernet frame, i.e. the size of the rest of the packet not including the USB-ethernet header, with the least significant byte first.

  2. For incoming packets the supplied buffer should usually be at least 1516 bytes. There may be special circumstances in which a smaller buffer might be safe; for example, if the host-side device driver is modified to support only smaller packets. Once the packet has been received the buffer will contain a two-byte header specific to USB-ethernet, followed by a normal ethernet frame. The header gives the size of the ethernet frame, excluding the header, with the least significant byte first.

Both usbs_eth_start_tx and usbs_eth_start_rx are asynchronous: the transfer is started and, some time later, a completion function will be invoked. The third and fourth arguments to both usbs_eth_start_tx and usbs_eth_start_rx supply the completion function and an argument to that function respectively. The completion function will be invoked with three arguments: a pointer to the usbs_eth data structure, usually usbs_eth0; the supplied completion data ; and a return code field. A negative value indicates that an error occurred, for example -EPIPE if the connection between USB host and peripheral has been broken, or -EAGAIN if an endpoint has been halted. A positive value indicates the total size of the transfer, which should correspond to the size in the USB-ethernet header plus an additional two bytes for the header itself.

If the data transfer is succesful then the completion function will typically be invoked in DSR context rather than in thread context, although this depends on the implementation of the underlying USB device driver. Therefore the completion function is restricted in what it can do; in particular, it must not make any calls that will or may block such as locking a mutex or allocating memory. The kernel documentation should be consulted for more details of DSR's and interrupt handling generally. Note that if the transfer finishes quickly then the completion function may be invoked before usbs_eth_start_rx or usbs_eth_start_tx returns. This is especially likely to happen if the current thread is descheduled after starting the data transfer but before returning from these functions.

For transmit operations, it is possible for usbs_eth_start_tx to invoke the completion function immediately. If there is no current connection between host and target then the transmit will fail immediately with -EPIPE. In addition the USB-ethernet package will check the destination MAC address and make sure that the ethernet frame really is intended for the host: either it must be for the address specified in the initialization call usbs_eth_init, or it must be a broadcast packet, or the host must have enabled promiscuous mode.