OTG Functions

Introduction

This chapter covers the support provided by the USB library for the USB OTG controller. The USB library provides a simplified interface that allows the application to configure how often OTG sessions are requested and a callback method to notify the application when any mode switch has occurred. Since the OTG portion of the USB library must handle both device and host mode operation it requires some setup for both device and host modes. This puts some requirements on the order of initialization of the stacks in order to insure proper operation.

The USB library currently only supports OTG session request protocol(SRP) and does not support host negotiation protocol(HNP).

File Structure

Filename

Description

usblib.h

The header file containing OTG mode and other function prototypes and data types offered by the USB library.

usbmode.c

The source code for the USB OTG functions are in this file.

OTG Controller Driver

The USB library OTG functions provide a higher level interface to the USB controller’s OTG hardware register interface. The hardware register interface is the lowest level of the interface and it interacts directly with the DriverLib USB APIs. The OTG functions provide the ability to detect which end of the USB cable was connected (A side or B side) as well as the presence of a device or host being connected. The OTG portion of the USB library requires initialization of the USB library in a certain order to safely bring up the the controller in OTG mode. This is because the stack requires both host and device mode operation. Once the USB library stack is initialized for OTG mode operation, the application will manage OTG notifications via a mode callback function that is called any time the USB mode changes.

Initialization

The application using the USB library in OTG mode must perform not only the initialization for the OTG functionality but also configure the host and device mode library functions as well. For host mode this includes registering the supported host classes, configuring the power pins, and calling any application level initialization functions that are required. For device mode, only the application level initialization is required as the OTG initialization will complete all other initialization required by the USB device library.

To properly configure host mode, the application must first configure and enable the host power pins for USBEPEN and USBPFLT. These are configured using in the library the USBHCDPowerConfigInit(). The actual physical pins must also be enabled and configured by the application using SysCtlPeripheralEnable() followed by GPIOPinTypeUSBDigital(). These pins are located on different physical pins on devices and thus must be configured by the application. The remaining USB pins are handled by the library and do not require any configuration.

Once the pins are configured, the USB library must be put into OTG mode in order to properly handle incoming requests. The very first call after pin configuration should be to call USBStackModeSet() to register a callback function for OTG events as well as put the library into OTG mode. Next any calls needed to initialize the application level interface for device and host mode need to be called. For device this would be functions like USBDHIDMouseInit() for a HID mouse or it could be USBDCDInit() for a non-library provided device class. For host mode the the drivers must be registered with a call to USBHCDRegisterDrivers() and if a USB library provided class is used then it’s application initialization interface must be called as well. For example in the case of supporting a USB mouse, the USBHMouseOpen() should be called to initialize the USB libraries HID mouse functionality. The last function that should be called by the application to initialize the USB OTG library is to call USBOTGModeInit() in order to finalize the initialization and enable the controller to start functioning in OTG mode. The USBOTGModeInit() also sets the polling rate for determining the mode of the controller as well as provide the memory that is required by the USB library host stack. Once this call is complete the application should be ready to receive any callbacks from the function provided to the USBStackModeSet() and any other device or host specific calls.

Mode Detection

The detection of which end of the cable that the USB controller is on and the current mode is done automatically in the library. The callback function passed in to USBStackModeSet() provides information on mode changes to allow the application to respond. Initially the USB library will start in idle state and remain in that state until a new mode is detected. The rate at which the mode is checked is passed into the USBOTGModeInit() function or can be set by the USBOTGPollRate() function once the OTG library code has been initialized. If USBOTGPollRate() is called with a polling rate of zero then polling for mode will stop until the rate is changed to a non-zero value. In a full OTG system, the polling rate is not required, but it will set how often the USB library issues session request on B side of the USB cable and how often it will look for devices if on the A side of the cable. Regardless of the mode that is detected the application should periodically call the USBOTGMain() function to allow the polling to function as well as call the USB library’s main function once host mode is determined. The USBOTGMain() takes the number of elapsed milliseconds since the last call to USBOTGMain() in order to provide the USB OTG library functions with some basic timing information.

When the USB library detects that it is on the B side of the cable and has been powered, then the library will call back with the mode set to eUSBModeDevice. If the USB controller is connected to a non-OTG host then the library will simply detect device mode and start operating as a USB device. All other device handling will work exactly as it does for normal device operation. When the USB cable is disconnected the USB library will return to the idle state and inform the application by calling the mode callback function with the mode set to eUSBModeNone.

The USB library detects that is is on the A side of the cable via a session request from the B side or detecting that the A side is connected to a cable due to the polling check. The USB library will then power the USB bus, call the mode callback function with the mode set to eUSBModeHost, and then begin enumerating the device. If a non-OTG device was connected the USB library will simply enumerate the device and function exactly as if the USB controller was in normal host mode.

Once the USB controller is unplugged from the host or detects that a device has been removed in host mode, the session will end and polling will resume. In both cases the USB library will call the callback function with the mode set to eUSBModeNone to inform the application that the USB library has returned to and idle state and is neither a host or device. Once the USB controller mode has been determined, no other USB library OTG API functions need to be called.

Interrupt Handling

All interrupt handling is done by the USB library USB0OTGModeIntHandler() function which is the interrupt handler for all USB interrupts in OTG mode. This function must be registered as the interrupt handler for the USB controller. To simplify handling both modes of operation, the OTG interrupt handler will take care of routing interrupts to the correct handler in USB library based on the current mode of operation. The application should be ready to receive any calls from other parts of the USB library based on the current mode of operation that was returned by the mode callback function. Since most callbacks are done in interrupt context they should be treated like interrupt handlers and should defer any real processing of events to occur outside the interrupt context. The callbacks are used to notify the applications of events that occur due to OTG negotiations or during normal operation.

OTG Programming Examples

The USB library provides an example OTG application that can act as a mouse device or can support being a host to a mouse device. This application uses the USB HID mouse device support as well as the USB HID mouse host support that is provided with the USB library. To accomplish this the application must initialize the host stack to support a mouse device and initialize the device stack to operate as a mouse device. The application should always call USBStackModeSet() in order to set the mode of the stack to OTG and in order to receive callbacks for any mode changes.

USBStackModeSet(0, eUSBModeOTG, ModeCallback);

OTG Host Mode Initialization

The USB OTG library requires the application to initialize the host stack almost identically as is done for normal host mode. The only difference for the USB OTG configuration is that USBHCDInit() is not called by the application and is handled by the call to USBOTGModeInit(). As with normal host mode, the application first registers the supported device drivers with a call to USBHCDRegisterDrivers(). If the top level driver for a device requires any initialization it should be called as well. Then the application should configure the USB power pins EPEN and FAULT to allow the OTG stack to be able to power the device and detect fault conditions if required. At this point the host mode drivers and stack are ready for normal operation. Unlike normal host mode the application must periodically call USBOTGMain() instead of USBHCDMain() to allow non-interrupt based library code to run.

//
// Register the host class drivers.
//
USBHCDRegisterDrivers(0, g_ppHostClassDrivers, g_ulNumHostClassDrivers);

//
// Configure the power pins for host mode.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
GPIOPinTypeUSBDigital(GPIO_PORTH_BASE, GPIO_PIN_3 | GPIO_PIN_4);

//
// Initialize the power configuration. This sets the power enable signal
// to be active high and does not enable the power fault.
//
USBHCDPowerConfigInit(0, USBHCD_VBUS_AUTO_HIGH);

//
// This is the top level call to initialize a mouse driver.
//
USBHMouseOpen(MouseCallback, g_pucBuffer, MOUSE_MEMORY_SIZE);

OTG Device Mode Initialization

The USB OTG library requires the application to initialize the device stack identically to how it is done for normal device mode. This includes calling USBDCDInit() for custom classes or a specific USB library provided device initialization function like USBDHIDMouseInit() in the example below. Once this is done the device mode stack is ready for normal operation in OTG mode.

//
// This is the call to initialize the mouse device stack.
//
USBDHIDMouseInit(0, (tUSBDHIDMouseDevice *)&g_sMouseDevice);

OTG Mode Initialization

The only remaining initialization required after configuring the device and host stacks is to enable OTG mode with a call to USBOTGModeInit(). This function takes a parameter to specify the polling intervall for the OTG detection and also two other parameters that are the same as the ones passed to USBHCDInit() as it will pass the memory buffer provided in these two parameters directly to USBHCDInit(). Once this function returns the OTG stack will be operational and ready for new devices.

//
// Pass in the host stack buffer to the OTG stack.
//
USBOTGModeInit(0, g_pHCDPool, HCD_MEMORY_SIZE);

Application Interface

Once all the host, device and OTG initialization is complete, the USB library is ready to start normal operation. For device mode this simply means that the next time the device is connected to a host the application will receive a callback via the function provided with the USBStackModeSet() API. This will inform the application that a device has been detected. Because the USB bus is not be powered in idle mode, detection of host mode requires polling or actual session request signaling from a device in order to detect that host mode should be enabled. In the case where the USB controller is connected to the A side of the cable(default Host mode) this will check the cable and inform the application via the mode callback if a device is present. In the case where the USB controller is connected to the B side of the cable and an OTG device is on the A side, this call will request that the A side power the USB bus and enumerate the device. If nothing is present then the application will receive a callback indicating eUSBModeNone as the current mode was not able to be detected. The application will be informed of a device being disconnected or being disconnected as a device by receiving a callback that the USB library has returned to eUSBModeNone and possibly also from the USB library device or host library functions as well.