diff options
| author | Yuval Adam <yuv.adm@gmail.com> | 2014-03-16 14:41:11 +0200 |
|---|---|---|
| committer | Yuval Adam <yuv.adm@gmail.com> | 2014-03-16 14:41:11 +0200 |
| commit | 990090a4cc9070837d31e66b58d40f0c3d038741 (patch) | |
| tree | cf1b905082c364e9b223e0c5058566103138dae5 /usblib/usbmode.c | |
| parent | 7f4da522479c0f00126219f0c23b804c3a93d7a6 (diff) | |
Add usblib and utils
Diffstat (limited to 'usblib/usbmode.c')
| -rw-r--r-- | usblib/usbmode.c | 1180 |
1 files changed, 1180 insertions, 0 deletions
diff --git a/usblib/usbmode.c b/usblib/usbmode.c new file mode 100644 index 0000000..3d95c11 --- /dev/null +++ b/usblib/usbmode.c @@ -0,0 +1,1180 @@ +//*****************************************************************************
+//
+// usbmode.c - Functions related to dual mode USB device/host operation.
+//
+// Copyright (c) 2008-2014 Texas Instruments Incorporated. All rights reserved.
+// Software License Agreement
+//
+// Texas Instruments (TI) is supplying this software for use solely and
+// exclusively on TI's microcontroller products. The software is owned by
+// TI and/or its suppliers, and is protected under applicable copyright
+// laws. You may not combine this software with "viral" open-source
+// software in order to form a larger program.
+//
+// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
+// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
+// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
+// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+// DAMAGES, FOR ANY REASON WHATSOEVER.
+//
+// This is part of revision 2.1.0.12573 of the Tiva USB Library.
+//
+//*****************************************************************************
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "inc/hw_ints.h"
+#include "inc/hw_memmap.h"
+#include "inc/hw_types.h"
+#include "inc/hw_sysctl.h"
+#include "inc/hw_usb.h"
+#include "driverlib/debug.h"
+#include "driverlib/interrupt.h"
+#include "driverlib/rom.h"
+#include "driverlib/rom_map.h"
+#include "driverlib/sysctl.h"
+#include "driverlib/usb.h"
+#include "driverlib/rtos_bindings.h"
+#include "usblib/usblib.h"
+#include "usblib/usblibpriv.h"
+#include "usblib/device/usbdevice.h"
+#include "usblib/host/usbhost.h"
+#include "usblib/host/usbhostpriv.h"
+#include "usblib/usblibpriv.h"
+
+//*****************************************************************************
+//
+//! \addtogroup general_usblib_api
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// The following label defines interrupts that we will always pass to the host
+// interrupt handler even if we are in dual mode and not yet sure of which
+// mode we are operating in.
+//
+//*****************************************************************************
+#define USB_HOST_INTS (USB_INTCTRL_VBUS_ERR)
+
+//*****************************************************************************
+//
+// Global variable indicating which mode of operation the application has
+// requested.
+//
+//*****************************************************************************
+volatile tUSBMode g_iUSBMode = eUSBModeNone;
+
+//*****************************************************************************
+//
+// The default and the current polling rate for the USB OTG library.
+//
+//*****************************************************************************
+volatile uint32_t g_ui32PollRate;
+
+//*****************************************************************************
+//
+// The current time remaining in milliseconds before checking the cable
+// connection.
+//
+//*****************************************************************************
+volatile uint32_t g_ui32WaitTicks = 0;
+
+//*****************************************************************************
+//
+// This enum holds the various states that we can be in while performing
+// USB mode checking. This involves use of the OTG session request to poll
+// the USB ID pin to determine whether a device or a host is connected.
+//
+//*****************************************************************************
+typedef enum
+{
+ //
+ // No checking is currently pending.
+ //
+ eUSBOTGModeIdle,
+
+ //
+ // Waiting on ID mode detection.
+ //
+ eUSBOTGModeWaitID,
+
+ //
+ // Waiting for next poll interval.
+ //
+ eUSBOTGModeWait,
+
+ //
+ // Now in B-side wait for connect.
+ //
+ eUSBOTGModeBWaitCon,
+
+ //
+ // Now in A-side device mode.
+ //
+ eUSBOTGModeBDevice,
+
+ //
+ // Now in A-side host mode.
+ //
+ eUSBOTGModeAHost,
+}
+tUSBOTGState;
+
+volatile tUSBOTGState g_eOTGModeState;
+
+//*****************************************************************************
+//
+// Global variable indicating whether we are currently operating in host or
+// device mode if the user has requested Dual mode operation.
+//
+//*****************************************************************************
+static volatile tUSBMode g_iDualMode = eUSBModeNone;
+
+static void USBOTGRemovePower(uint32_t ui32Index);
+
+//*****************************************************************************
+//
+// Global variable holding a pointer to the callback function which will be
+// called when the USB mode changes between device and host.
+//
+//*****************************************************************************
+static tUSBModeCallback g_pfnUSBModeCallback;
+
+//*****************************************************************************
+//
+// This function is used to handle switching between host, device and
+// unconfigured modes.
+//
+// \param iUSBMode is one of eUSBModeHost, eUSBModeDevice, or eUSBModeNone.
+//
+// Based on the current state held in g_iDualMode variable this function will
+// handle the transition of the mode of operation in OTG mode and calling
+// the callback function if it is present.
+//
+// \return None.
+//
+//*****************************************************************************
+static void
+USBOTGSetMode(tUSBMode iUSBMode)
+{
+ if((g_iDualMode != iUSBMode) || (g_iDualMode == eUSBModeNone))
+ {
+ //
+ // If going from host mode to unconfigured mode then remove power.
+ //
+ if((g_iDualMode == eUSBModeHost) && (iUSBMode == eUSBModeNone))
+ {
+ //
+ // Take the steps to remove power in the of host mode OTG.
+ //
+ USBOTGRemovePower(0);
+ }
+
+ //
+ // If going from device mode to unconfigured mode then end the current
+ // session.
+ //
+ if((g_iDualMode == eUSBModeDevice) && (iUSBMode == eUSBModeNone))
+ {
+ //
+ // End the current session.
+ //
+ USBOTGSessionRequest(USB0_BASE, false);
+ }
+
+ //
+ // Reset the delay whenever returning to eUSBModeNone.
+ //
+ if(iUSBMode == eUSBModeNone)
+ {
+ g_ui32WaitTicks = g_ui32PollRate;
+ }
+
+ //
+ // Do we have a mode change callback installed?
+ //
+ if((g_pfnUSBModeCallback) && (g_iDualMode != iUSBMode))
+ {
+ //
+ // Inform the callback of the new operating mode.
+ //
+ g_pfnUSBModeCallback(0, iUSBMode);
+ }
+
+ //
+ // Save the new mode.
+ //
+ g_iDualMode = iUSBMode;
+ }
+}
+
+//*****************************************************************************
+//
+//! Allows dual mode application to switch between USB device and host modes
+//! and provides a method to force the controller into the desired mode.
+//!
+//! \param ui32Index specifies the USB controller whose mode of operation is to
+//! be set. This parameter must be set to 0.
+//! \param iUSBMode indicates the mode that the application wishes to operate
+//! in. Valid values are \b eUSBModeDevice to operate as a USB device and
+//! \b eUSBModeHost to operate as a USB host.
+//! \param pfnCallback is a pointer to a function which the USB library will
+//! call each time the mode is changed to indicate the new operating mode. In
+//! cases where \e iUSBMode is set to either \b eUSBModeDevice or
+//! \b eUSBModeHost, the callback will be made immediately to allow the
+//! application to perform any host or device specific initialization.
+//!
+//! This function allows a USB application that can operate in host
+//! or device mode to indicate to the USB stack the mode that it wishes to
+//! use. The caller is responsible for cleaning up the interface and removing
+//! itself from the bus prior to making this call and reconfiguring afterwards.
+//! The \e pfnCallback function can be a NULL(0) value to indicate that no
+//! notification is required.
+//!
+//! For successful dual mode mode operation, an application must register
+//! USB0DualModeIntHandler() as the interrupt handler for the USB0 interrupt.
+//! This handler is responsible for steering interrupts to the device or host
+//! stack depending upon the chosen mode. Devices which do not require dual
+//! mode capability should register either \e USB0DeviceIntHandler() or
+//! \e USB0HostIntHandler() instead. Registering \e USB0DualModeIntHandler()
+//! for a single mode application will result in an application binary larger
+//! than required since library functions for both USB operating modes will be
+//! included even though only one mode is required.
+//!
+//! Single mode applications (those offering exclusively USB device or USB
+//! host functionality) are only required to call this function if they need to
+//! force the mode of the controller to Host or Device mode. This is usually
+//! in the event that the application needs to reused the USBVBUS and/or USBID
+//! pins as GPIOs.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+USBStackModeSet(uint32_t ui32Index, tUSBMode iUSBMode,
+ tUSBModeCallback pfnCallback)
+{
+ //
+ // Check the arguments.
+ //
+ ASSERT(ui32Index == 0);
+
+ //
+ // Remember the mode so that we can steer the interrupts appropriately.
+ //
+ g_iUSBMode = iUSBMode;
+
+ //
+ // Remember the callback pointer.
+ //
+ g_pfnUSBModeCallback = pfnCallback;
+
+ //
+ // If we are being asked to be either a host or device, we will not be
+ // trying to auto-detect the mode so make the callback immediately.
+ //
+ if((iUSBMode == eUSBModeDevice) || (iUSBMode == eUSBModeHost))
+ {
+ //
+ // Make sure that a callback was provided.
+ //
+ if(g_pfnUSBModeCallback)
+ {
+ g_pfnUSBModeCallback(0, iUSBMode);
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! Steers USB interrupts from controller to the correct handler in the USB
+//! stack.
+//!
+//! This interrupt handler is used in applications which require to operate
+//! in both host and device mode. It steers the USB hardware interrupt to the
+//! correct handler in the USB stack depending upon the current operating mode
+//! of the application, USB device or host.
+//!
+//! For successful dual mode operation, an application must register
+//! USB0DualModeIntHandler() in the CPU vector table as the interrupt handler
+//! for the USB0 interrupt. This handler is responsible for steering
+//! interrupts to the device or host stack depending upon the chosen mode.
+//!
+//! \note Devices which do not require dual mode capability should register
+//! either USB0DeviceIntHandler() or USB0HostIntHandler() instead. Registering
+//! USB0DualModeIntHandler() for a single mode application will result in an
+//! application binary larger than required since library functions for both
+//! USB operating modes will be included even though only one mode is actually
+//! required.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+USB0DualModeIntHandler(void)
+{
+ uint32_t ui32Status;
+
+ //
+ // Read the USB interrupt status.
+ //
+ ui32Status = USBIntStatusControl(USB0_BASE);
+
+ //
+ // Pass through the subset of interrupts that we always want
+ // the host stack to see regardless of whether or not we
+ // are actually in host mode at this point.
+ //
+ if(ui32Status & USB_HOST_INTS)
+ {
+ //
+ // Call the host's interrupt handler.
+ //
+ USBHostIntHandlerInternal(0, ui32Status & USB_HOST_INTS);
+
+ //
+ // We have already processed these interrupts so clear them
+ // from the status.
+ //
+ ui32Status &= ~USB_HOST_INTS;
+ }
+
+ //
+ // Steer the interrupt to the appropriate handler within the stack
+ // depending upon our current operating mode. Note that we need to pass
+ // the ui32Status parameter since the USB interrupt register is
+ // clear-on-read.
+ //
+ switch(g_iUSBMode)
+ {
+ case eUSBModeNone:
+ {
+ //
+ // No mode is set yet so we have no idea what to do. Just ignore
+ // the interrupt.
+ //
+ break;
+ }
+
+ //
+ // Operating in pure host mode.
+ //
+ case eUSBModeHost:
+ {
+ //
+ // Call the host interrupt handler if there is anything still to
+ // process.
+ //
+ USBHostIntHandlerInternal(0, ui32Status);
+
+ break;
+ }
+
+ //
+ // Operating in pure device mode.
+ //
+ case eUSBModeDevice:
+ {
+ //
+ // Call the device interrupt handler.
+ //
+ USBDeviceIntHandlerInternal(0, ui32Status);
+
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group general_usblib_api.
+//! @}
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+//! \addtogroup dualmode_api
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+//! Initializes the USB controller for dual mode operation.
+//!
+//! \param ui32Index specifies the USB controller that is to be initialized for
+//! dual mode operation. This parameter must be set to 0.
+//!
+//! This function initializes the USB controller hardware into a state
+//! suitable for dual mode operation. Applications may use this function to
+//! ensure that the controller is in a neutral state and able to receive
+//! appropriate interrupts before host or device mode is chosen using a call
+//! to USBStackModeSet().
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+USBDualModeInit(uint32_t ui32Index)
+{
+ //
+ // We only support a single USB controller.
+ //
+ ASSERT(ui32Index == 0);
+
+ //
+ // Configure the End point 0.
+ //
+ USBHostEndpointConfig(USB0_BASE, USB_EP_0, 64, 0, 0,
+ (USB_EP_MODE_CTRL | USB_EP_SPEED_FULL |
+ USB_EP_HOST_OUT));
+
+ //
+ // Enable USB Interrupts.
+ //
+ MAP_USBIntEnableControl(USB0_BASE, USB_INTCTRL_RESET |
+ USB_INTCTRL_DISCONNECT |
+ USB_INTCTRL_SESSION |
+ USB_INTCTRL_BABBLE |
+ USB_INTCTRL_CONNECT |
+ USB_INTCTRL_RESUME |
+ USB_INTCTRL_SUSPEND |
+ USB_INTCTRL_VBUS_ERR);
+
+ //
+ // Enable all endpoint interrupts.
+ //
+ MAP_USBIntEnableEndpoint(USB0_BASE, USB_INTEP_ALL);
+
+ //
+ // Initialize the USB tick module.
+ //
+ InternalUSBTickInit();
+
+ //
+ // Enable the USB interrupt.
+ //
+ OS_INT_ENABLE(g_psDCDInst[0].ui32IntNum);
+ //
+ // Turn on session request to enable ID pin checking.
+ //
+ USBOTGSessionRequest(USB0_BASE, true);
+
+ //
+ // Initialize the power configuration.
+ //
+ USBHostPwrConfig(USB0_BASE, USBHCDPowerConfigGet(ui32Index));
+
+ //
+ // If power enable is automatic then then USBHostPwrEnable() has to be
+ // called to allow the USB controller to control the power enable pin.
+ //
+ if(USBHCDPowerAutomatic(ui32Index))
+ {
+ //
+ // This will not turn on power but instead will allow the USB
+ // controller to turn on power when needed.
+ //
+ USBHostPwrEnable(USB0_BASE);
+ }
+}
+
+//*****************************************************************************
+//
+//! Returns the USB controller to the default mode when in dual mode operation.
+//!
+//! \param ui32Index specifies the USB controller whose dual mode operation is
+//! to be ended. This parameter must be set to 0.
+//!
+//! Applications using both host and device modes may call this function to
+//! disable interrupts in preparation for shutdown or a change of operating
+//! mode.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+USBDualModeTerm(uint32_t ui32Index)
+{
+ //
+ // We only support a single USB controller.
+ //
+ ASSERT(ui32Index == 0);
+
+ //
+ // Disable the USB interrupt.
+ //
+ OS_INT_DISABLE(g_psDCDInst[0].ui32IntNum);
+
+ MAP_USBIntDisableControl(USB0_BASE, USB_INTCTRL_ALL);
+
+ MAP_USBIntDisableEndpoint(USB0_BASE, USB_INTEP_ALL);
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group dualmode_api.
+//! @}
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+//! \addtogroup usblib_otg
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+//! Returns the USB controller to and inactive state when in OTG mode
+//! operation.
+//!
+//! \param ui32Index specifies the USB controller to end OTG mode operations.
+//!
+//! Applications using OTG mode may call this function to disable interrupts
+//! in preparation for shutdown or a change of operating mode.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+USBOTGModeTerm(uint32_t ui32Index)
+{
+ //
+ // We only support a single USB controller.
+ //
+ ASSERT(ui32Index == 0);
+
+ //
+ // Disable the USB interrupt.
+ //
+ OS_INT_DISABLE(g_psDCDInst[0].ui32IntNum);
+
+ //
+ // Disable all control interrupts.
+ //
+ MAP_USBIntDisableControl(USB0_BASE, USB_INTCTRL_ALL);
+
+ //
+ // Disable all endpoint interrupts.
+ //
+ MAP_USBIntDisableEndpoint(USB0_BASE, USB_INTEP_ALL);
+
+ //
+ // Set the mode to none if it is not already.
+ //
+ USBOTGSetMode(eUSBModeNone);
+}
+
+//*****************************************************************************
+//
+//! Initializes the USB controller for OTG mode operation.
+//!
+//! \param ui32Index specifies the USB controller that is to be initialized for
+//! OTG mode operation.
+//! \param ui32PollingRate is the rate in milliseconds to poll the controller
+//! for changes in mode.
+//! \param pvPool is a pointer to the data to use as a memory pool for this
+//! controller.
+//! \param ui32PoolSize is the size in bytes of the buffer passed in as
+//! \e pvPool.
+//!
+//! This function initializes the USB controller hardware into a state
+//! suitable for OTG mode operation. Applications must use this function to
+//! ensure that the controller is in a neutral state and able to receive
+//! appropriate interrupts before host or device mode is chosen by OTG
+//! negotiation. The \e ui32PollingRate parameter is used to set the rate at
+//! which the USB library will poll the controller to determine the mode. This
+//! has the most effect on how quickly the USB library will detect changes when
+//! going to host mode. The parameters \e pvPool and \e ui32PoolSize are
+//! passed on to the USB host library functions to provide memory for the USB
+//! library when it is acting as a host. Any device and host initialization
+//! should have been called before calling this function to prevent the USB
+//! library from attempting to run in device or host mode before the USB
+//! library is fully configured.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+USBOTGModeInit(uint32_t ui32Index, uint32_t ui32PollingRate,
+ void *pvPool, uint32_t ui32PoolSize)
+{
+ //
+ // We only support a single USB controller.
+ //
+ ASSERT(ui32Index == 0);
+
+ //
+ // This should never be called if not in OTG mode.
+ //
+ ASSERT(g_iUSBMode == eUSBModeOTG);
+
+ //
+ // Force OTG mode in all cases since anything else is invalid, but a DEBUG
+ // build will still ASSERT above if this value is incorrect.
+ //
+ g_iUSBMode = eUSBModeOTG;
+
+ //
+ // Remember that we have not yet determined whether we are device or
+ // host.
+ //
+ g_iDualMode = eUSBModeNone;
+
+ //
+ // Set the default polling rate.
+ //
+ g_ui32PollRate = ui32PollingRate;
+
+ //
+ // Enable the USB controller.
+ //
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);
+
+ //
+ // Turn on USB Phy clock.
+ //
+ MAP_SysCtlUSBPLLEnable();
+
+ //
+ // Initialize the host controller stack.
+ //
+ USBHCDInit(ui32Index, pvPool, ui32PoolSize);
+
+ //
+ // Configure the End point 0.
+ //
+ USBHostEndpointConfig(USB0_BASE, USB_EP_0, 64, 0, 0,
+ (USB_EP_MODE_CTRL | USB_EP_SPEED_FULL |
+ USB_EP_HOST_OUT));
+
+ //
+ // Enable control interrupts.
+ //
+ MAP_USBIntEnableControl(USB0_BASE, USB_INTCTRL_RESET |
+ USB_INTCTRL_DISCONNECT |
+ USB_INTCTRL_SESSION |
+ USB_INTCTRL_BABBLE |
+ USB_INTCTRL_CONNECT |
+ USB_INTCTRL_RESUME |
+ USB_INTCTRL_SUSPEND |
+ USB_INTCTRL_VBUS_ERR |
+ USB_INTCTRL_MODE_DETECT |
+ USB_INTCTRL_SOF);
+
+ //
+ // Make sure the mode OTG mode and not forced device or host.
+ //
+ USBOTGMode(USB0_BASE);
+
+ //
+ // Enable all endpoint interrupts.
+ //
+ MAP_USBIntEnableEndpoint(USB0_BASE, USB_INTEP_ALL);
+
+ //
+ // Initialize the power configuration.
+ //
+ USBHCDPowerConfigSet(ui32Index, USBHCDPowerConfigGet(ui32Index));
+
+ //
+ // If power enable is automatic then then USBHostPwrEnable() has to be
+ // called to allow the USB controller to control the power enable pin.
+ //
+ if(USBHCDPowerAutomatic(ui32Index))
+ {
+ //
+ // This will not turn on power but instead will allow the USB
+ // controller to turn on power when needed.
+ //
+ USBHostPwrEnable(USB0_BASE);
+ }
+
+ //
+ // Enable the USB interrupt.
+ //
+ if(CLASS_IS_TM4C129)
+ {
+ OS_INT_ENABLE(INT_USB0_TM4C129);
+ }
+ else
+ {
+ OS_INT_ENABLE(INT_USB0_TM4C123);
+ }
+}
+
+//*****************************************************************************
+//
+// This function handles the steps required to remove power in OTG mode.
+//
+// \param ui32Index specifies which USB controller should remove power.
+//
+// This function will perform the steps required to remove power from the USB
+// bus as required by the OTG specification. This call will first issue a
+// bus suspend followed by clearing the current session and then removing
+// power.
+//
+// \return None.
+//
+//*****************************************************************************
+static void
+USBOTGRemovePower(uint32_t ui32Index)
+{
+ tEventInfo sEvent;
+
+ //
+ // Do suspend signaling.
+ //
+ USBHostSuspend(USB0_BASE);
+
+ //
+ // End the session in either device or host mode.
+ //
+ USBOTGSessionRequest(USB0_BASE, false);
+
+ //
+ // Check if the controller is automatically applying power or not.
+ //
+ if(USBHCDPowerAutomatic(ui32Index) == 0)
+ {
+ //
+ // Call the registered event driver to allow it to disable power.
+ //
+ sEvent.ui32Event = USB_EVENT_POWER_DISABLE;
+ sEvent.ui32Instance = 0;
+ InternalUSBHCDSendEvent(0, &sEvent, USBHCD_EVFLAG_PWRDIS);
+ }
+}
+
+//*****************************************************************************
+//
+//! This call sets the USB OTG controllers poll rate when checking for the mode
+//! of the controller.
+//!
+//! \param ui32Index specifies which USB controller to set the polling rate.
+//! \param ui32PollRate is the rate in milliseconds to poll for changes in the
+//! controller mode.
+//!
+//! This function is called to set the USB OTG libraries polling rate when
+//! checking the status of the cable. The \e ui32PollRate value used sets the
+//! rate in milliseconds that the USB OTG library will poll the cable to see
+//! if the controller should enter host mode. This value has no effect on
+//! device detection rate as the controller will detect being connected to a
+//! host controller automatically. The \e ui32PollRate can be set to 0 to
+//! disable polling. The USB OTG library can still function with the polling
+//! rate set to zero, however it will fail to detect host mode properly when no
+//! device is present at the end of the USB OTG B side of the cable.
+//!
+//! \note This function should only be called on devices that support OTG
+//! functionality.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+USBOTGPollRate(uint32_t ui32Index, uint32_t ui32PollRate)
+{
+ //
+ // Save the timeout.
+ //
+ g_ui32PollRate = ui32PollRate;
+}
+
+//*****************************************************************************
+//
+//! Handles OTG mode changes and also steers other USB interrupts from
+//! the controller to the correct handler in the USB stack.
+//!
+//! This interrupt handler is used in applications which require to operate
+//! in both host and device mode using OTG. When in host or device mode, it
+//! steers the USB hardware interrupt to the correct handler in the USB stack
+//! depending upon the current operating mode. It also handles other OTG
+//! related interrupt events.
+//!
+//! For successful OTG mode operation, an application must register
+//! USB0OTGModeIntHandler() in the CPU vector table as the interrupt handler
+//! for the USB0 interrupt.
+//!
+//! \note This interrupt handler should only be used on controllers that
+//! support OTG functionality.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+USB0OTGModeIntHandler(void)
+{
+ uint32_t ui32Status;
+ tEventInfo sEvent;
+
+ //
+ // Read the USB interrupt status.
+ //
+ ui32Status = USBIntStatusControl(USB0_BASE);
+
+ //
+ // Check if this was an mode detect interrupt and under manual power
+ // control.
+ //
+ if((ui32Status & USB_INTCTRL_MODE_DETECT) &&
+ (USBHCDPowerAutomatic(0) == 0))
+ {
+ uint32_t ui32Mode;
+
+ ui32Mode = USBModeGet(USB0_BASE);
+
+ switch(ui32Mode)
+ {
+ //
+ // Device is on the A side of the cable and power needs to be
+ // applied.
+ //
+ case USB_OTG_MODE_ASIDE_NPWR:
+ case USB_OTG_MODE_ASIDE_SESS:
+ case USB_OTG_MODE_ASIDE_AVAL:
+ {
+ //
+ // Since power is not automatically enabled, call the
+ // registered event handler to allow the application to turn
+ // on power.
+ //
+ sEvent.ui32Event = USB_EVENT_POWER_ENABLE;
+ sEvent.ui32Instance = 0;
+ InternalUSBHCDSendEvent(0, &sEvent, USBHCD_EVFLAG_PWREN);
+
+ break;
+ }
+
+ //
+ // Device is on the B side of the cable and powered.
+ //
+ case USB_OTG_MODE_BSIDE_DEV:
+ {
+ //
+ // Now in device mode on the B side of the cable and will wait
+ // for a connect before becoming a device.
+ //
+ g_eOTGModeState = eUSBOTGModeBWaitCon;
+
+ break;
+ }
+
+ //
+ // Any other mode detect indicates eUSBModeNone.
+ //
+ default:
+ {
+ //
+ // Just inform the application that the mode was not device
+ // or host.
+ //
+ USBOTGSetMode(eUSBModeNone);
+
+ break;
+ }
+ }
+ }
+
+ //
+ // If there was a VBUS error then the power should be shut off and the
+ // system is reset to waiting for detection again.
+ //
+ if(ui32Status & USB_INTCTRL_VBUS_ERR)
+ {
+ //
+ // Just inform the application that the mode was not device
+ // or host.
+ //
+ USBOTGSetMode(eUSBModeNone);
+
+ //
+ // Return to idle mode.
+ //
+ g_eOTGModeState = eUSBOTGModeWait;
+ }
+
+ //
+ // If there is a disconnect interrupt and the controller was on the B side
+ // cable as a device then go back to the IDLE state.
+ //
+ if((ui32Status & USB_INTCTRL_DISCONNECT) &&
+ (g_eOTGModeState == eUSBOTGModeBDevice))
+ {
+ //
+ // No longer a device so switch to unconfigured mode.
+ //
+ USBOTGSetMode(eUSBModeNone);
+
+ //
+ // Return to idle mode.
+ //
+ g_eOTGModeState = eUSBOTGModeWait;
+
+ return;
+ }
+
+ //
+ // Handle receiving a reset.
+ //
+ if((ui32Status & USB_INTCTRL_RESET)&&
+ (g_eOTGModeState != eUSBOTGModeBDevice))
+ {
+ //
+ // Getting a reset interrupt when not already a b side device indicates
+ // that a host is resetting the device and the controller should
+ // move to device mode.
+ //
+ g_eOTGModeState = eUSBOTGModeBDevice;
+
+ //
+ // Save the new mode.
+ //
+ USBOTGSetMode(eUSBModeDevice);
+ }
+
+ //
+ // If there is a connect interrupt while the library is waiting for
+ // one then move to full host mode state.
+ //
+ if(ui32Status & USB_INTCTRL_CONNECT)
+ {
+ //
+ // Move to A side host state.
+ //
+ g_eOTGModeState = eUSBOTGModeAHost;
+
+ //
+ // Inform the application that controller is in host mode.
+ //
+ USBOTGSetMode(eUSBModeHost);
+ }
+
+ //
+ // Call the correct device or host interrupt handler based on the current
+ // mode of operation.
+ //
+ switch(g_eOTGModeState)
+ {
+ case eUSBOTGModeAHost:
+ {
+ //
+ // Call the host interrupt handler if there is anything still to
+ // process.
+ //
+ USBHostIntHandlerInternal(0, ui32Status);
+
+ break;
+ }
+
+ //
+ // Operating in pure device mode.
+ //
+ case eUSBOTGModeBDevice:
+ {
+ //
+ // Call the device interrupt handler.
+ //
+ USBDeviceIntHandlerInternal(0, ui32Status);
+
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// This function is called by the USB host stack code to indicated that it
+// has completed handing the device disconnection.
+//
+// \param ui32Index specifies the USB controller that has completed disconnect.
+//
+// This internal library function is used when the hsot controller has
+// completed any deferred handling when it has detected a device has been
+// disconnected. The functions main purpose is to return the OTG controller to
+// a state that allows for resuming normal OTG cable detection and negotiation.
+//
+// \note This function should not be called outside the library.
+//
+//*****************************************************************************
+void
+OTGDeviceDisconnect(uint32_t ui32Index)
+{
+ //
+ // This function is only valid when called in host mode.
+ //
+ if(g_eOTGModeState == eUSBOTGModeAHost)
+ {
+ //
+ // No longer a host so switch to unconfigured mode.
+ //
+ USBOTGSetMode(eUSBModeNone);
+
+ g_eOTGModeState = eUSBOTGModeWait;
+ }
+}
+
+//*****************************************************************************
+//
+//! This function is the main routine for the OTG Controller Driver.
+//!
+//! \param ui32MsTicks is the number of milliseconds that have passed since the
+//! last time this function was called.
+//!
+//! This function is the main routine for the USB controller when using the
+//! library in OTG mode. This routine must be called periodically by the main
+//! application outside of a callback context. The \e ui32MsTicks value is
+//! used for basic timing needed by the USB library when operating in OTG mode.
+//! This allows for a simple cooperative system to access the the OTG
+//! controller driver interface without the need for an RTOS. All time
+//! critical operations are handled in interrupt context but all longer
+//! operations are run from the this function to allow them to block and wait
+//! for completion without holding off other interrupts.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+USBOTGMain(uint32_t ui32MsTicks)
+{
+ tEventInfo sEvent;
+
+ if(ui32MsTicks > g_ui32WaitTicks)
+ {
+ g_ui32WaitTicks = 0;
+ }
+ else
+ {
+ g_ui32WaitTicks -= ui32MsTicks;
+ }
+
+ switch(g_eOTGModeState)
+ {
+ case eUSBOTGModeIdle:
+ {
+ g_eOTGModeState = eUSBOTGModeWaitID;
+
+ //
+ // Initiate a session request and check the ID pin.
+ //
+ USBOTGSessionRequest(USB0_BASE, true);
+ break;
+ }
+ case eUSBOTGModeWait:
+ case eUSBOTGModeWaitID:
+ {
+ //
+ // If reached the timeout and polling is enabled then look again.
+ //
+ if((g_ui32WaitTicks == 0) && (g_ui32PollRate != 0))
+ {
+ //
+ // Remove the session request.
+ //
+ USBOTGSessionRequest(USB0_BASE, false);
+
+ //
+ // Return to idle mode.
+ //
+ USBOTGSetMode(eUSBModeNone);
+
+ //
+ // Check if the controller is automatically applying power or
+ // not.
+ //
+ if(USBHCDPowerAutomatic(0) == 0)
+ {
+ //
+ // Call the registered event driver to allow it to disable
+ // power.
+ //
+ sEvent.ui32Event = USB_EVENT_POWER_DISABLE;
+ sEvent.ui32Instance = 0;
+ InternalUSBHCDSendEvent(0, &sEvent, USBHCD_EVFLAG_PWRDIS);
+ }
+
+ //
+ // Go back to the idle state.
+ //
+ g_eOTGModeState = eUSBOTGModeIdle;
+ }
+ break;
+ }
+ case eUSBOTGModeAHost:
+ {
+ //
+ // Call the host main routine when acting as a host.
+ //
+ USBHCDMain();
+ break;
+ }
+ case eUSBOTGModeBWaitCon:
+ case eUSBOTGModeBDevice:
+ default:
+ {
+ break;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! This function sets one of the \b USBLIB_FEATURE_ requests.
+//!
+//! \param ui32Index is the index of the USB controller to access.
+//! \param ui32Feature is one of the \b USBLIB_FEATURE_ defines.
+//! \param pvFeature is a pointer to the data for the \b USBLIB_FEATURE
+//! request.
+//!
+//! This function sends the requested feature request to the USB library.
+//! Not all features are supported by all devices so see the documentation
+//! for the \b USBLIB_FEATURE_ to determine if the feature is supported.
+//!
+//! \return Returns \b true if the feature was set and \b false if the feature
+//! is not supported or could not be changed to the requested value.
+//
+//*****************************************************************************
+bool
+USBOTGFeatureSet(uint32_t ui32Index, uint32_t ui32Feature, void *pvFeature)
+{
+ bool bRetCode;
+
+ bRetCode = true;
+
+ //
+ // Pass this on to the host and device and indicate false if
+ // either fails.
+ //
+ if(USBDCDFeatureSet(ui32Index, ui32Feature, pvFeature) == false)
+ {
+ bRetCode = false;
+ }
+
+ if(USBHCDFeatureSet(ui32Index, ui32Feature, pvFeature) == false)
+ {
+ bRetCode = false;
+ }
+
+ return(bRetCode);
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
|
