USBX supports the OTG functionalities of USB when an OTG compliant USB controller is available in the hardware design.
USBX supports OTG in the core USB stack. But for OTG to function, it requires a specific USB controller. USBX OTG controller functions can be found in the usbx_otg directory. The current USBX version only supports the NXP LPC3131 with full OTG capabilities.
The regular controller driver functions (host or device) can still be found in the standard USBX usbx_device_controllers and usbx_host_controllers but the usbx_otg directory contains the specific OTG functions associated with the USB controller.
There are four categories of functions for an OTG controller in addition to the usual host/device functions.
-
VBUS specific functions
-
Start and Stop of the controller
-
USB role manager
-
Interrupt handlers
VBUS functions
Each controller needs to have a VBUS manager to change the state of VBUS based on power management requirements. Usually this function only performs turning on or off VBUS
Start and Stop the controller
Unlike a regular USB implementation, OTG requires the host and/or the device stack to be activated and deactivated when the role changes.
USB role Manager
The USB role manager receives commands to change the state of the USB. There are several states that need transitions to and from those given in the table below.
| State | Value | Description |
|---|---|---|
UX_OTG_IDLE |
0 |
The device is Idle. Not connected to anything |
UX_OTG_IDLE_TO_HOST |
1 |
Device is connected with type A connector |
UX_OTG_IDLE_TO_SLAVE |
2 |
Device is connected with type B connector |
UX_OTG_HOST_TO_IDLE |
3 |
Host device got disconnected |
UX_OTG_HOST_TO_SLAVE |
4 |
Role swap from Host to Slave |
UX_OTG_SLAVE_TO_IDLE |
5 |
Slave device is disconnected |
UX_OTG_SLAVE_TO_HOST |
6 |
Role swap from Slave to Host |
Interrupt handlers
Both host and device controller drivers for OTG needs different interrupt handlers to monitor signals beyond traditional USB interrupts, in particular signals due to SRP and VBUS.
How to initialize a USB OTG controller. We use the NXP LPC3131 as an example here.
/* Initialize the LPC3131 OTG controller. */
status = ux_otg_lpc3131_initialize(0x19000000, lpc3131_vbus_function,
tx_demo_change_mode_callback);
In this example, we initialize the LPC3131 in OTG mode by passing a VBUS function and a callback for mode change (from host to slave or vice versa).
The callback function should simply record the new mode and wake up a pending thread to act up the new state.
void tx_demo_change_mode_callback(ULONG mode)
{
/* Simply save the otg mode. */
otg_mode = mode;
/* Wake up the thread that is waiting. */
ux_utility_semaphore_put(&mode_change_semaphore);
}
The mode value that is passed can have the following values.
-
UX_OTG_MODE_IDLE
-
UX_OTG_MODE_SLAVE
-
UX_OTG_MODE_HOST
The application can always check what the device is by looking at the variable.
ux_system_otg ->ux_system_otg_device_type
Its values can be one of the following.
-
UX_OTG_DEVICE_A
-
UX_OTG_DEVICE_B
-
UX_OTG_DEVICE_IDLE
A USB OTG host device can always ask for a role swap by issuing the command.
/* Ask the stack to perform a HNP swap with the device. We relinquish the host role to A device. */
ux_host_stack_role_swap(storage ->ux_host_class_storage_device);
For a slave device, there is no command to issue but the slave device can set a state to change the role, which will be picked up by the host when it issues a GET_STATUS and the swap will then be initiated.
/* We are a B device, ask for role swap. The next GET_STATUS from the host will get the status change and do the HNP. */
ux_system_otg ->ux_system_otg_slave_role_swap_flag =
UX_OTG_HOST_REQUEST_FLAG;