efm8 usb bridge working

This commit is contained in:
Conor Patrick
2018-07-04 12:48:18 -04:00
parent ca882dc38a
commit 344a104ece
39 changed files with 9027 additions and 812 deletions

View File

@@ -20,7 +20,7 @@ Known Issues and Limitations:
Target and Tool Chain Information:
---------------------------------
Target: EFM8UB1, EFM8UB2, EFM8UB3, EFM8UB4, C8051F320/1, C8051F326/7, C8051F34x, C8051F38x
Target: EFM8UB1, EFM8UB2, C8051F320/1, C8051F326/7, C8051F34x, C8051F38x
Tool chain: Keil
File List:
@@ -51,13 +51,6 @@ Version 1.0.1
USB_PWRSAVE_MODE_FASTWAKE was enabled.
- Improved documentation of USB_PWRSAVE_MODE_FASTWAKE feature.
Version 1.0.2
- Added ability to detect short OUT packet in Isochronous mode and
stuff the buffer with zeroes to keep isochronous stream in sync.
Version 1.0.3
- Added support for EFM8UB3 and EFM8UB4 devices.
-------------------------------------------------------------------------------
End Of File
-------------------------------------------------------------------------------

View File

@@ -21,7 +21,6 @@
*
* @section usb_device_contents Contents
*
* @li @ref usb_device_library_revision
* @li @ref usb_device_intro
* @li @ref usb_device_api
* @li @ref usb_device_conf
@@ -29,9 +28,6 @@
* @li @ref usb_device_transfers
* @li @ref usb_device_pitfalls
*
* @n @section usb_device_library_revision EFM8 USB Library Revision
* Library Revision: 1.0.3
*
* @n @section usb_device_intro Introduction
*
* The USB device protocol stack provides an API which makes it possible to
@@ -112,10 +108,11 @@
*
* @ref USBD_RemoteWakeup() @n
* Used in SUSPENDED state (see @ref USB_Status_TypeDef) to signal resume to
* host. The function will be called automatically by the library if the
* @ref USBD_RemoteWakeupCb() function returns true. The function will
* also check that the host has sent a SET_FEATURE request to enable Remote
* Wakeup before issuing the resume.
* host. It's the applications responsibility to adhere to the USB standard
* which states that a device can not signal resume before it has been
* SUSPENDED for at least 5 ms. The function will also check that the host
* has sent a SET_FEATURE request to enable Remote Wakeup before issuing the
* resume.
*
* @ref USBD_GetUsbState() @n
* Returns the device USB state (see @ref USBD_State_TypeDef). Refer to
@@ -263,16 +260,6 @@
* #define SLAB_USB_LANGUAGE USB_LANGID_ENUS
*
* // -----------------------------------------------------------------------------
* // Enable use of UTF-8 strings for string descriptors.
* // If this option is enabled then packed string descriptors that are created
* // with UTF8_PACKED_STATIC_CONST_STRING_DESC() can be UTF-8 encoded and they
* // will be decoded into UCS-2 16-bit wide character format used for USB string
* // descriptors. If this feature is not needed then it can be disabled to save
* // some code memory space.
* // -----------------------------------------------------------------------------
* #define SLAB_USB_UTF8_STRINGS 1
*
* // -----------------------------------------------------------------------------
* // Set the power saving mode
* //
* // SLAB_USB_PWRSAVE_MODE configures when the device will automatically enter
@@ -282,17 +269,9 @@
* // USB_PWRSAVE_MODE_ONSUSPEND - Enter USB power-save mode on USB suspend
* // USB_PWRSAVE_MODE_ONVBUSOFF - Enter USB power-save mode when not attached
* // to the USB host.
* // USB_PWRSAVE_MODE_FASTWAKE - Exit USB power-save mode more quickly, but
* // consume more power while in USB power-save
* // mode.
* // While the device is in USB power-save mode
* // (typically during USB suspend), the
* // internal voltage regulator stays in normal
* // power mode instead of entering suspend
* // power mode.
* // This is an advanced feature that may be
* // useful in certain applications that support
* // remote wakeup.
* // USB_PWRSAVE_MODE_FASTWAKE - Exit USB power-save mode more quickly.
* // This is useful for some applications that
* // support remote wakeup.
* // -----------------------------------------------------------------------------
* #define SLAB_USB_PWRSAVE_MODE (USB_PWRSAVE_MODE_ONVBUSOFF \
* | USB_PWRSAVE_MODE_ONSUSPEND)
@@ -707,19 +686,14 @@
#endif
#ifndef UNREFERENCED_ARGUMENT
#if defined __C51__
/// Macro for removing unreferenced arguments from compiler warnings
#define UNREFERENCED_ARGUMENT(arg) (0, arg)
#elif defined __ICC8051__
/// Macro for removing unreferenced arguments from compiler warnings
#define UNREFERENCED_ARGUMENT(arg) ((void)arg)
#endif
#endif
/***************************************************************************//**
* @brief Macro for creating USB-compliant UTF-16LE UNICODE string
* descriptor from a C string.
* @details This macro should be used for ASCII strings in which all
* @details This macro should be used for UTF-8 strings in which all
* characters are represented by a single ASCII byte (i.e.
* U.S. English strings).
* The USB Library will expand variables created with this macro
@@ -736,71 +710,9 @@
* @param __val
* The value of the string descriptor
******************************************************************************/
#define UTF16LE_PACKED_STATIC_CONST_STRING_DESC(__name, __val, __size) \
#define UTF16LE_PACKED_STATIC_CONST_STRING_DESC(__name, __val) \
SI_SEGMENT_VARIABLE(__name, static const USB_StringDescriptor_TypeDef, SI_SEG_CODE) = \
{ USB_STRING_DESCRIPTOR_UTF16LE_PACKED, __size * 2, USB_STRING_DESCRIPTOR, __val }
/***************************************************************************//**
* @brief Macro for creating USB-compliant UTF-16LE UNICODE string
* descriptor from a UTF-8 string.
* @details This macro should be used for UTF-8 strings in which all
* characters are represented by a valid UTF-8 byte sequence
* of 1-3 bytes per character. The USB library will expand
* variables created with this macro by decoding the UTF-8
* sequence into 16-bit wide UCS-2 characters required for USB
* string descriptors.
* @n@n This example set an array named _manufacturer[]_ to a
* series of symbols: an anchor, a lightning bolt, and a
* fußball as the Manufacturer String:
*
* #define MFR_STRING "⚓⚡⚽"
*
* // This string has 3 Unicode characters so the __len
* // parameter is 3, even though it will take 3 bytes to
* // represent each character
* UTF8_PACKED_STATIC_CONST_STRING_DESC(manufacturer[], 3, \
* MFR_STRING);
* @param __name
* The name of the variable that holds the string descriptor
* @param __len
* Number of Unicode characters (or codepoints) in the string
* @param __val
* The value of the string descriptor
******************************************************************************/
#define UTF8_PACKED_STATIC_CONST_STRING_DESC(__name, __len, __val) \
SI_SEGMENT_VARIABLE(__name, static const USB_StringDescriptor_TypeDef, SI_SEG_CODE) = \
{ USB_STRING_DESCRIPTOR_UTF8, (__len) * 2, USB_STRING_DESCRIPTOR, __val }
/***************************************************************************//**
* @brief Macro for creating USB-compliant UTF-16LE UNICODE string
* descriptor from a UTF-8 string.
* @details This macro should be used for UTF-8 strings in which all
* characters are represented by a valid UTF-8 byte sequence
* of 1-3 bytes per character. The USB library will expand
* variables created with this macro by decoding the UTF-8
* sequence into 16-bit wide UCS-2 characters required for USB
* string descriptors.
* @n@n This example set an array named _manufacturer[]_ to a
* series of symbols: an anchor, a lightning bolt, and a
* fußball as the Manufacturer String:
*
* #define MFR_STRING "⚓⚡⚽"
*
* // This string has 3 Unicode characters so the __len
* // parameter is 3, even though it will take 3 bytes to
* // represent each character
* UTF8_PACKED_STATIC_CONST_STRING_DESC(manufacturer[], 3, \
* MFR_STRING);
* @param __name
* The name of the variable that holds the string descriptor
* @param __len
* Number of Unicode characters (or codepoints) in the string
* @param __val
* The value of the string descriptor
******************************************************************************/
#define UTF8_PACKED_STATIC_CONST_STRING_DESC(__name, __len, __val) \
SI_SEGMENT_VARIABLE(__name, static const USB_StringDescriptor_TypeDef, SI_SEG_CODE) = \
{ USB_STRING_DESCRIPTOR_UTF8, (__len) * 2, USB_STRING_DESCRIPTOR, __val }
{ USB_STRING_DESCRIPTOR_UTF16LE_PACKED, sizeof(__val) * 2, USB_STRING_DESCRIPTOR, __val }
/***************************************************************************//**
* @brief Macro for creating USB-compliant UTF-16LE UNICODE string
@@ -867,8 +779,8 @@
* The value of the string descriptor
******************************************************************************/
#define LANGID_STATIC_CONST_STRING_DESC(__name, __val) \
SI_SEGMENT_VARIABLE(__name, static const USB_LangId_StringDescriptor_Typedef, SI_SEG_CODE) = \
{ htole16(((SLAB_USB_NUM_LANGUAGES * 2) + 2) + (USB_STRING_DESCRIPTOR << 8)), __val }
SI_SEGMENT_VARIABLE(__name, static const USB_LangId_StringDescriptor_Typedef, __code) = \
{ (((SLAB_USB_NUM_LANGUAGES * 2) + 2) << 8) + USB_STRING_DESCRIPTOR, __val }
/** @} (end addtogroup efm8_usb_macros Macros) */
@@ -897,8 +809,7 @@ typedef enum
USB_STATUS_DEVICE_RESET = -11, ///< Device is/was reset.
USB_STATUS_TIMEOUT = -12, ///< Transfer timeout.
USB_STATUS_DEVICE_REMOVED = -13, ///< Device was removed.
USB_STATUS_EP_RX_BUFFER_OVERRUN = -14, ///< Not enough data in the Rx buffer to hold the
USB_STATUS_DATA_ERROR = -15, ///< OUT packet had CRC or bit-stuffing error
USB_STATUS_EP_RX_BUFFER_OVERRUN = -14 ///< Not enough data in the Rx buffer to hold the
///< last received packet
} USB_Status_TypeDef;
@@ -952,7 +863,7 @@ typedef enum
#if (SLAB_USB_EP3OUT_USED)
EP3OUT,
#endif
} USB_EP_Index_TypeDef;
}USB_EP_Index_TypeDef;
/// @brief USB Setup type.
typedef struct
@@ -1083,7 +994,7 @@ typedef uint16_t USB_LangId_StringDescriptor_Typedef; ///< The language ID strin
#if (SLAB_USB_NUM_LANGUAGES == 1)
/// @brief USB String Table Structure.
typedef SI_VARIABLE_SEGMENT_POINTER(, USB_StringDescriptor_TypeDef, SI_SEG_GENERIC) USB_StringTable_TypeDef;
typedef USB_StringDescriptor_TypeDef * *USB_StringTable_TypeDef;
#elif (SLAB_USB_NUM_LANGUAGES > 1)
typedef struct
{
@@ -1097,17 +1008,17 @@ typedef struct
/// the device.
typedef struct
{
SI_VARIABLE_SEGMENT_POINTER(deviceDescriptor, USB_DeviceDescriptor_TypeDef, SI_SEG_GENERIC); ///< Pointer to the device descriptor
SI_VARIABLE_SEGMENT_POINTER(configDescriptor, USB_ConfigurationDescriptor_TypeDef, SI_SEG_GENERIC); ///< Pointer to the configuration descriptor
SI_VARIABLE_SEGMENT_POINTER(stringDescriptors, USB_StringTable_TypeDef, SI_SEG_GENERIC); ///< Pointer to an array of string descriptor pointers
uint8_t numberOfStrings; ///< Number of strings in string descriptor array
USB_DeviceDescriptor_TypeDef *deviceDescriptor; ///< Pointer to the device descriptor
uint8_t *configDescriptor; ///< Pointer to the configuration descriptor
USB_StringTable_TypeDef *stringDescriptors; ///< Pointer to an array of string descriptor pointers
uint8_t numberOfStrings; ///< Number of strings in string descriptor array
} USBD_Init_TypeDef;
/// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
// Endpoint structure
typedef struct
{
SI_VARIABLE_SEGMENT_POINTER(buf, uint8_t, SI_SEG_GENERIC);
uint8_t *buf;
uint16_t remaining;
USBD_EpState_TypeDef state;
union
@@ -1171,9 +1082,9 @@ typedef struct
#if SLAB_USB_SUPPORT_ALT_INTERFACES
uint8_t interfaceAltSetting[SLAB_USB_NUM_INTERFACES];
#endif
SI_VARIABLE_SEGMENT_POINTER(deviceDescriptor, USB_DeviceDescriptor_TypeDef, SI_SEG_GENERIC);
SI_VARIABLE_SEGMENT_POINTER(configDescriptor, USB_ConfigurationDescriptor_TypeDef, SI_SEG_GENERIC);
SI_VARIABLE_SEGMENT_POINTER(stringDescriptors, USB_StringTable_TypeDef, SI_SEG_GENERIC);
USB_DeviceDescriptor_TypeDef *deviceDescriptor;
USB_ConfigurationDescriptor_TypeDef *configDescriptor;
USB_StringTable_TypeDef *stringDescriptors;
} USBD_Device_TypeDef;
/// @endcond DO_NOT_INCLUDE_WITH_DOXYGEN
@@ -1307,10 +1218,6 @@ USB_Status_TypeDef USBDCH9_SetupCmd(void);
*
* Default setting is '1' and may be overridden by defining in 'usbconfig.h'.
*
* @note The EFM8UB1, EFM8UB3, and EFM8UB4 devices can be configured to ignore
* the voltage on the VBUS pin and to instead use that pin as GPIO. If
* this feature is used, SLAB_USB_BUS_POWERED should be set to '1' even if
* the device is not drawing its power from the VBUS line.
*****************************************************************************/
/**************************************************************************//**
@@ -1343,9 +1250,9 @@ USB_Status_TypeDef USBDCH9_SetupCmd(void);
* @brief Enables/disables remote wakeup capability
* @details Remote wakeup allow the USB device to wake the host from suspend.
* When enabled, the library will call @ref USBD_RemoteWakeupCb() to determine
* if the remote wakeup source caused the device to wake up. If it did, the
* library will exit suspend mode and call @ref USBD_RemoteWakeup() to wake
* up the host.
* if the remote wakeup source caused the device to wake up. If it was, the
* library will exit suspend mode and the application should call
* @ref USBD_RemoteWakeup() to wake up the host.
*
* When '1' remote wakeup is enabled
* When '0' remote wakeup is disabled
@@ -1673,25 +1580,6 @@ USB_Status_TypeDef USBDCH9_SetupCmd(void);
*
*****************************************************************************/
/**************************************************************************//**
* @def SLAB_USB_UTF8_STRINGS
* @brief
* Enables UTF-8 string decoding for USB string descriptors that are created
* using @ref UTF8_PACKED_STATIC_CONST_STRING_DESC.
*
* @details
* If this option is enabled, USB descriptor strings that are created using
* @ref UTF8_PACKED_STATIC_CONST_STRING_DESC can be encoded as UTF-8 which
* allows for Unicode characters (up to 16-bits wide) to be used for USB
* string descriptors. The UTF-8 strings will be decoded into UCS-2 16-bit
* wide character format required by USB. If this feature is not needed then
* this option can be disabled to save code memory space. If this option is
* disabled, then @ref UTF8_PACKED_STATIC_CONST_STRING_DESC should not be used.
*
* Default setting is '0' and may be overridden by defining in 'usbconfig.h'.
*
*****************************************************************************/
/**************************************************************************//**
* @def SLAB_USB_PWRSAVE_MODE
* @brief Configures the power-saving options supported by the device
@@ -1856,10 +1744,6 @@ USB_Status_TypeDef USBDCH9_SetupCmd(void);
#define SLAB_USB_LANGUAGE USB_LANGID_ENUS
#endif
#ifndef SLAB_USB_UTF8_STRINGS
#define SLAB_USB_UTF8_STRINGS 0
#endif
#ifndef SLAB_USB_PWRSAVE_MODE
#define SLAB_USB_PWRSAVE_MODE USB_PWRSAVE_MODE_ONSUSPEND
#endif
@@ -1956,7 +1840,7 @@ USBD_State_TypeDef USBD_GetUsbState(void);
* @return
* @ref USB_STATUS_OK on success, else an appropriate error code.
******************************************************************************/
int8_t USBD_Init(SI_VARIABLE_SEGMENT_POINTER(p, const USBD_Init_TypeDef, SI_SEG_GENERIC));
int8_t USBD_Init(const USBD_Init_TypeDef *p);
/***************************************************************************//**
* @brief
@@ -1982,8 +1866,8 @@ int8_t USBD_Init(SI_VARIABLE_SEGMENT_POINTER(p, const USBD_Init_TypeDef, SI_SEG_
* @return
* @ref USB_STATUS_OK on success, else an appropriate error code.
******************************************************************************/
int8_t USBD_Read(uint8_t epAddr,
SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC),
int8_t USBD_Read(uint8_t epAddr,
uint8_t *dat,
uint16_t byteCount,
bool callback);
@@ -1992,9 +1876,10 @@ int8_t USBD_Read(uint8_t epAddr,
* Perform a remote wakeup signaling sequence.
*
* @note
* This function is typically called by the library if @ref
* USBD_RemoteWakeupCb() returns true, so it does not need to be called by
* application code.
* It is the responsibility of the application to ensure that remote wakeup
* is not attempted before the device has been suspended for at least 5
* miliseconds. This function should not be called from within an interrupt
* handler.
*
* @return
* @ref USB_STATUS_OK on success, else an appropriate error code.
@@ -2030,7 +1915,7 @@ void USBD_Run(void);
* @return
* @ref USB_STATUS_OK on success, else an appropriate error code.
******************************************************************************/
int8_t USBD_StallEp(uint8_t epAddr);
int8_t USBD_StallEp(int8_t epAddr);
/***************************************************************************//**
* @brief
@@ -2089,7 +1974,7 @@ int8_t USBD_UnStallEp(uint8_t epAddr);
* @ref USB_STATUS_OK on success, else an appropriate error code.
******************************************************************************/
int8_t USBD_Write(uint8_t epAddr,
SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC),
uint8_t *dat,
uint16_t byteCount,
bool callback);
@@ -2228,8 +2113,8 @@ USB_Status_TypeDef USBD_SetInterfaceCb(uint8_t interface, uint8_t altSetting);
* If remote wakeup is enabled via @ref SLAB_USB_REMOTE_WAKEUP_ENABLED, the
* USB library will query the application after waking from suspend to see if
* the remote wakeup source was the reason for the wakeup. If this function
* returns True, the library will call @ref USBD_RemoteWakeup() to wake up the
* host and exit suspend mode.
* returns True, the library will exit suspend mode and the application should
* call @ref USBD_RemoteWakeup() to wake up the host.
* @return
* True if the remote wakeup source was the reason the device woke from
* suspend, false otherwise.
@@ -2311,8 +2196,8 @@ uint16_t USBD_XferCompleteCb(uint8_t epAddr, \
/// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
// -------------------- FIFO Access Functions ---------------------------------
void USB_ReadFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC));
void USB_WriteFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC), bool txPacket);
void USB_ReadFIFO(uint8_t fifoNum, uint8_t numBytes, uint8_t *dat);
void USB_WriteFIFO(uint8_t fifoNum, uint8_t numBytes, uint8_t *dat, bool txPacket);
/// @endcond DO_NOT_INCLUDE_WITH_DOXYGEN
// -------------------- Include Files ------------------------------------------

View File

@@ -6,9 +6,9 @@
#include "si_toolchain.h"
#include "efm8_usb.h"
#include "assert.h"
//#include "assert.h"
#include <stdint.h>
#define SLAB_ASSERT(x)
// -----------------------------------------------------------------------------
// Global Variables
@@ -65,8 +65,8 @@ void USBD_AbortAllTransfers(void)
int8_t USBD_AbortTransfer(uint8_t epAddr)
{
SI_VARIABLE_SEGMENT_POINTER(ep, USBD_Ep_TypeDef, MEM_MODEL_SEG);
int8_t retVal = USB_STATUS_OK;
USBD_Ep_TypeDef MEM_MODEL_SEG *ep;
uint8_t retVal = USB_STATUS_OK;
bool usbIntsEnabled;
USB_SaveSfrPage();
@@ -150,7 +150,7 @@ void USBD_Disconnect(void)
bool USBD_EpIsBusy(uint8_t epAddr)
{
SI_VARIABLE_SEGMENT_POINTER(ep, USBD_Ep_TypeDef, MEM_MODEL_SEG);
USBD_Ep_TypeDef MEM_MODEL_SEG *ep;
// Verify this is a valid endpoint address
if (epAddr >= SLAB_USB_NUM_EPS_USED)
@@ -174,7 +174,7 @@ USBD_State_TypeDef USBD_GetUsbState(void)
return myUsbDevice.state;
}
int8_t USBD_Init(SI_VARIABLE_SEGMENT_POINTER(p, const USBD_Init_TypeDef, SI_SEG_GENERIC))
int8_t USBD_Init(const USBD_Init_TypeDef *p)
{
uint8_t i;
@@ -190,12 +190,12 @@ int8_t USBD_Init(SI_VARIABLE_SEGMENT_POINTER(p, const USBD_Init_TypeDef, SI_SEG_
// Zero out the myUsbDevice struct, then initialize all non-zero members
for (i = 0; i < sizeof(myUsbDevice); i++)
{
*((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, MEM_MODEL_SEG))&myUsbDevice + i) = 0;
*((uint8_t MEM_MODEL_SEG *)&myUsbDevice + i) = 0;
}
// Get the USB descriptors from p
myUsbDevice.deviceDescriptor = p->deviceDescriptor;
myUsbDevice.configDescriptor = p->configDescriptor;
myUsbDevice.configDescriptor = (USB_ConfigurationDescriptor_TypeDef *)p->configDescriptor;
myUsbDevice.stringDescriptors = p->stringDescriptors;
myUsbDevice.numberOfStrings = p->numberOfStrings;
@@ -246,12 +246,12 @@ int8_t USBD_Init(SI_VARIABLE_SEGMENT_POINTER(p, const USBD_Init_TypeDef, SI_SEG_
}
int8_t USBD_Read(uint8_t epAddr,
SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC),
uint8_t *dat,
uint16_t byteCount,
bool callback)
{
bool usbIntsEnabled;
SI_VARIABLE_SEGMENT_POINTER(ep, USBD_Ep_TypeDef, MEM_MODEL_SEG);
USBD_Ep_TypeDef MEM_MODEL_SEG *ep;
USB_SaveSfrPage();
@@ -432,13 +432,8 @@ void USBD_Stop(void)
void USBD_Suspend(void)
{
#if (!(SLAB_USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_FASTWAKE))
uint8_t i;
#endif
bool regulatorEnabled, prefetchEnabled;
#if SLAB_USB_REMOTE_WAKEUP_ENABLED
bool remoteWakeup = false;
#endif
USB_SaveSfrPage();
@@ -494,9 +489,8 @@ void USBD_Suspend(void)
// wakeup event occurred. If so, exit USBD_Suspend().
if (USB_IsSuspended() == true)
{
remoteWakeup = USBD_RemoteWakeupCb();
if (remoteWakeup == true)
{
if (USBD_RemoteWakeupCb() == true)
{
break;
}
}
@@ -510,13 +504,8 @@ void USBD_Suspend(void)
break;
}
#endif
#if ((!(SLAB_USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF)) || \
(SLAB_USB_BUS_POWERED))
} while (USB_IsSuspended() == true);
#else
} while ((USB_IsSuspended() == true) || (USB_IsVbusOn() == false));
#endif
// Restore the internal regulator
if (regulatorEnabled == true)
{
@@ -534,20 +523,6 @@ void USBD_Suspend(void)
USB_SetNormalClock();
#endif
USB_EnableTransceiver();
#if SLAB_USB_REMOTE_WAKEUP_ENABLED
// If the device woke from suspend due to a remote wakeup source, call
// USBD_RemoteWakeup() here to wake up the host.
if (remoteWakeup == true)
{
// Wake up the host
if (USBD_RemoteWakeup() == USB_STATUS_OK)
{
// If the remote wakeup succeeded, transition out of USB suspend state
USBD_SetUsbState(myUsbDevice.savedState);
}
}
#endif
}
USB_RestoreSfrPage();
@@ -624,12 +599,12 @@ int8_t USBD_UnStallEp(uint8_t epAddr)
}
int8_t USBD_Write(uint8_t epAddr,
SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC),
uint8_t *dat,
uint16_t byteCount,
bool callback)
{
bool usbIntsEnabled;
SI_VARIABLE_SEGMENT_POINTER(ep, USBD_Ep_TypeDef, MEM_MODEL_SEG);
USBD_Ep_TypeDef MEM_MODEL_SEG *ep;
USB_SaveSfrPage();

View File

@@ -22,13 +22,14 @@ static USB_Status_TypeDef SetConfiguration(void);
static USB_Status_TypeDef SetFeature(void);
static USB_Status_TypeDef SetInterface(void);
static void USBD_ActivateAllEps(bool forceIdle);
static void EP0_Write(SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC), uint16_t numBytes);
static void EP0_Write(uint8_t *dat, uint16_t numBytes);
void SendEp0Stall(void);
// -----------------------------------------------------------------------------
// Global Variables
extern SI_SEGMENT_VARIABLE(myUsbDevice, USBD_Device_TypeDef, MEM_MODEL_SEG);
const SI_SEGMENT_VARIABLE(txZero[2], uint8_t, SI_SEG_CODE);
SI_SEGMENT_VARIABLE(txZero[2], uint8_t, SI_SEG_CODE);
// -----------------------------------------------------------------------------
// Static Global Variables
@@ -91,6 +92,15 @@ USB_Status_TypeDef USBDCH9_SetupCmd(void)
break;
}
// Reset index to 0 in case one of the above commands modified it
USB_SetIndex(0);
// If the command resulted in an error, send a procedural stall
if (status == USB_STATUS_REQ_ERR)
{
SendEp0Stall();
}
return status;
}
@@ -228,7 +238,7 @@ static USB_Status_TypeDef GetConfiguration(void)
{
if (myUsbDevice.state == USBD_STATE_ADDRESSED)
{
EP0_Write((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))txZero, 1);
EP0_Write(txZero, 1);
retVal = USB_STATUS_OK;
}
else if (myUsbDevice.state == USBD_STATE_CONFIGURED)
@@ -257,7 +267,7 @@ static USB_Status_TypeDef GetDescriptor(void)
uint8_t index;
uint16_t length = 0;
SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC);
uint8_t *dat;
USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
if (*((uint8_t *)&myUsbDevice.setup.bmRequestType) ==
@@ -272,7 +282,7 @@ static USB_Status_TypeDef GetDescriptor(void)
{
break;
}
dat = (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))myUsbDevice.deviceDescriptor;
dat = (uint8_t *)myUsbDevice.deviceDescriptor;
length = myUsbDevice.deviceDescriptor->bLength;
break;
@@ -281,14 +291,14 @@ static USB_Status_TypeDef GetDescriptor(void)
{
break;
}
dat = (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))myUsbDevice.configDescriptor;
dat = (uint8_t *)myUsbDevice.configDescriptor;
length = le16toh(myUsbDevice.configDescriptor->wTotalLength);
break;
case USB_STRING_DESCRIPTOR:
#if (SLAB_USB_NUM_LANGUAGES == 1)
dat = (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))myUsbDevice.stringDescriptors[index];
dat = (uint8_t *)myUsbDevice.stringDescriptors[index];
// Index 0 is the language string. If SLAB_USB_NUM_LANGUAGES == 1, we
// know the length will be 4 and the format will be UTF16LE.
@@ -317,7 +327,7 @@ static USB_Status_TypeDef GetDescriptor(void)
// Index 0 is the language.
if (index == 0)
{
dat = ((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))myUsbDevice.stringDescriptors->languageArray[0][index]);
dat = ((uint8_t *)myUsbDevice.stringDescriptors->languageArray[0][index]);
length = *((uint8_t *)dat);
myUsbDevice.ep0String.encoding.type = USB_STRING_DESCRIPTOR_UTF16LE;
}
@@ -335,7 +345,7 @@ static USB_Status_TypeDef GetDescriptor(void)
}
if ((langSupported == true) && (index < myUsbDevice.numberOfStrings))
{
dat = ((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))myUsbDevice.stringDescriptors->languageArray[lang][index]);
dat = ((uint8_t *)myUsbDevice.stringDescriptors->languageArray[lang][index]);
length = *(dat + USB_STRING_DESCRIPTOR_LENGTH);
myUsbDevice.ep0String.encoding.type = *(dat + USB_STRING_DESCRIPTOR_ENCODING);
dat += USB_STRING_DESCRIPTOR_LENGTH;
@@ -393,10 +403,10 @@ static USB_Status_TypeDef GetInterface(void)
{
#if (SLAB_USB_SUPPORT_ALT_INTERFACES)
// Return the alternate setting for the specified interface
EP0_Write((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))&myUsbDevice.interfaceAltSetting[interface], 1);
EP0_Write(&myUsbDevice.interfaceAltSetting[interface], 1);
#else
// Alternate interfaces are not supported, so return 0x0000.
EP0_Write((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))&txZero, 1);
EP0_Write(&txZero, 1);
#endif
retVal = USB_STATUS_OK;
}
@@ -531,7 +541,7 @@ static USB_Status_TypeDef GetStatus(void)
// If the command was valid, send the requested status.
if (retVal == USB_STATUS_OK)
{
EP0_Write((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))&pStatus, 2);
EP0_Write((uint8_t *)&pStatus, 2);
}
}
@@ -858,11 +868,11 @@ static void USBD_ActivateAllEps(bool forceIdle)
* @param numBytes
* Number of bytes to transmit on Endpoint 0
******************************************************************************/
static void EP0_Write(SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC), uint16_t numBytes)
static void EP0_Write(uint8_t *dat, uint16_t numBytes)
{
if (myUsbDevice.ep0.state == D_EP_IDLE)
{
myUsbDevice.ep0.buf = dat;
myUsbDevice.ep0.buf = (uint8_t *)dat;
myUsbDevice.ep0.remaining = numBytes;
myUsbDevice.ep0.state = D_EP_TRANSMITTING;
myUsbDevice.ep0.misc.c = 0;

View File

@@ -40,16 +40,11 @@ static void USB_WriteFIFO_Code(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat
// -------------------------------
// Generic FIFO access functions
static void USB_ReadFIFO_Generic(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC), uint8_t fifoNum);
static void USB_WriteFIFO_Generic(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC));
static void USB_ReadFIFO_Generic(uint8_t numBytes, uint8_t *dat, uint8_t fifoNum);
static void USB_WriteFIFO_Generic(uint8_t numBytes, uint8_t *dat);
#endif // #ifdef SI_GPTR
#if (SLAB_USB_EP3OUT_USED && (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC))
static void memclearXdata(SI_VARIABLE_SEGMENT_POINTER(s, uint8_t, SI_SEG_XDATA),
uint16_t n);
#endif
// -----------------------------------------------------------------------------
// Functions
@@ -67,7 +62,7 @@ static void memclearXdata(SI_VARIABLE_SEGMENT_POINTER(s, uint8_t, SI_SEG_XDATA),
// If Isochronous mode is enabled and the max packet size is greater than 255,
// break the FIFO reads up into multiple reads of 255 or less bytes.
// ----------------------------------------------------------------------------
void USB_ReadFIFOIso(uint8_t fifoNum, uint16_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC))
void USB_ReadFIFOIso(uint8_t fifoNum, uint16_t numBytes, uint8_t *dat)
{
uint8_t numBytesRead;
@@ -99,7 +94,7 @@ void USB_ReadFIFOIso(uint8_t fifoNum, uint16_t numBytes, SI_VARIABLE_SEGMENT_POI
// If Isochronous mode is enabled and the max packet size is greater than 255,
// break the FIFO writes up into multiple writes of 255 or less bytes.
// ----------------------------------------------------------------------------
void USB_WriteFIFOIso(uint8_t fifoNum, uint16_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC))
void USB_WriteFIFOIso(uint8_t fifoNum, uint16_t numBytes, uint8_t *dat)
{
uint8_t numBytesWrite;
@@ -322,6 +317,7 @@ void handleUsbIn3Int(void)
void handleUsbOut1Int(void)
{
uint8_t count;
USB_Status_TypeDef status;
bool xferComplete = false;
@@ -361,7 +357,6 @@ void handleUsbOut1Int(void)
myUsbDevice.ep1out.state = D_EP_IDLE;
xferComplete = true;
}
status = USB_STATUS_OK;
USB_EpnClearOutPacketReady();
}
@@ -371,7 +366,6 @@ void handleUsbOut1Int(void)
{
myUsbDevice.ep1out.misc.bits.callback = false;
}
USBD_XferCompleteCb(EP1OUT, status, count, myUsbDevice.ep1out.remaining);
}
}
@@ -387,6 +381,7 @@ void handleUsbOut1Int(void)
void handleUsbOut2Int(void)
{
uint8_t count;
USB_Status_TypeDef status;
bool xferComplete = false;
@@ -451,10 +446,19 @@ void handleUsbOut2Int(void)
* @note This function takes no parameters, but it uses the EP3OUT status
* variables stored in @ref myUsbDevice.ep3out.
******************************************************************************/
#if ((SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR))
void handleUsbOut3Int(void)
{
#if (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC)
uint16_t nextIdx;
#if (SLAB_USB_EP3OUT_MAX_PACKET_SIZE > 255)
uint16_t count;
#else
uint8_t count;
#endif // ( SLAB_USB_EP3OUT_MAX_PACKET_SIZE > 255 )
#else
uint8_t count;
#endif // ( SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC )
USB_Status_TypeDef status;
bool xferComplete = false;
@@ -474,6 +478,7 @@ void handleUsbOut3Int(void)
myUsbDevice.ep3out.misc.bits.outPacketPending = true;
status = USB_STATUS_EP_ERROR;
}
#if ((SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR))
// Check for overrun of user buffer
else if (myUsbDevice.ep3out.remaining < count)
{
@@ -481,11 +486,12 @@ void handleUsbOut3Int(void)
myUsbDevice.ep3out.misc.bits.outPacketPending = true;
status = USB_STATUS_EP_RX_BUFFER_OVERRUN;
}
#endif
else
{
#if ((SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR))
USB_ReadFIFO(3, count, myUsbDevice.ep3out.buf);
myUsbDevice.ep3out.misc.bits.outPacketPending = false;
myUsbDevice.ep3out.remaining -= count;
myUsbDevice.ep3out.buf += count;
@@ -494,7 +500,26 @@ void handleUsbOut3Int(void)
myUsbDevice.ep3out.state = D_EP_IDLE;
xferComplete = true;
}
#elif (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC)
nextIdx = count + myUsbDevice.ep3outIsoIdx;
// In isochronous mode, a circular buffer is used to hold the data
// If the next index into the circular buffer passes the end of the
// buffer, make two calls to USB_ReadFIFOIso()
if (nextIdx > myUsbDevice.ep3out.remaining)
{
USB_ReadFIFOIso(3, myUsbDevice.ep3out.remaining - myUsbDevice.ep3outIsoIdx, &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx]);
myUsbDevice.ep3outIsoIdx = nextIdx - myUsbDevice.ep3out.remaining;
USB_ReadFIFOIso(3, myUsbDevice.ep3outIsoIdx, myUsbDevice.ep3out.buf);
}
else
{
USB_ReadFIFOIso(3, count, &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx]);
myUsbDevice.ep3outIsoIdx = nextIdx;
}
#endif // ( ( SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK ) || ( SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR ) )
myUsbDevice.ep3out.misc.bits.outPacketPending = false;
status = USB_STATUS_OK;
USB_EpnClearOutPacketReady();
}
@@ -505,175 +530,18 @@ void handleUsbOut3Int(void)
myUsbDevice.ep3out.misc.bits.callback = false;
}
#if ((SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR))
USBD_XferCompleteCb(EP3OUT, status, count, myUsbDevice.ep3out.remaining);
}
}
}
#elif (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC)
void handleUsbOut3Int(void)
{
uint16_t nextIdx;
uint16_t numZeroBytesFromCb;
#if (SLAB_USB_EP3OUT_MAX_PACKET_SIZE > 255)
uint16_t count;
#else
uint8_t count;
#endif
USB_Status_TypeDef status = USB_STATUS_OK;
bool xferComplete = false;
USB_SetIndex(3);
if (USB_EpnOutGetSentStall())
{
USB_EpnOutClearSentStall();
}
else if (USB_EpnGetOutPacketReady())
{
count = USB_EpOutGetCount();
// If USBD_Read() has not been called, return an error
if (myUsbDevice.ep3out.state != D_EP_RECEIVING)
{
myUsbDevice.ep3out.misc.bits.outPacketPending = true;
status = USB_STATUS_EP_ERROR;
}
else
{
// DATERR bit set (i.e. CRC/bit-stuffing error)
if (USB_EpnGetDataError()
#ifdef SLAB_USB_ISOC_OUT_MIN_PACKET_SIZE
|| (count < SLAB_USB_ISOC_OUT_MIN_PACKET_SIZE)
#endif
#ifdef SLAB_USB_ISOC_OUT_MAX_PACKET_SIZE
|| (count > SLAB_USB_ISOC_OUT_MAX_PACKET_SIZE)
#endif
)
{
status = USB_STATUS_DATA_ERROR;
}
#ifdef SLAB_USB_ISOC_OUT_PACKETSIZE_MOD2
if ((count % 2) != 0)
{
status = USB_STATUS_DATA_ERROR;
}
#elif defined SLAB_USB_ISOC_OUT_PACKETSIZE_MOD4
if (( count % 4) != 0)
{
status = USB_STATUS_DATA_ERROR;
}
#elif defined SLAB_USB_ISOC_OUT_PACKETSIZE_MOD6
if (count % 6) != 0)
{
status = USB_STATUS_DATA_ERROR;
}
#endif
if (status == USB_STATUS_DATA_ERROR)
{
count = 0;
// Flush FIFO to get rid of bad packet
USB_EpnOutFlush();
myUsbDevice.ep3out.misc.bits.outPacketPending = false;
// Flush clears OPRDY, so no need to call USB_EpnClearOutPacketReady() now
}
else // No data error
{
nextIdx = count + myUsbDevice.ep3outIsoIdx;
// In isochronous mode, a circular buffer is used to hold the data
// If the next index into the circular buffer passes the end of the
// buffer, make two calls to USB_ReadFIFOIso()
if (nextIdx > myUsbDevice.ep3out.remaining)
{
USB_ReadFIFOIso(3, myUsbDevice.ep3out.remaining - myUsbDevice.ep3outIsoIdx, &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx]);
myUsbDevice.ep3outIsoIdx = nextIdx - myUsbDevice.ep3out.remaining;
USB_ReadFIFOIso(3, myUsbDevice.ep3outIsoIdx, myUsbDevice.ep3out.buf);
}
else
{
USB_ReadFIFOIso(3, count, &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx]);
myUsbDevice.ep3outIsoIdx = nextIdx;
}
myUsbDevice.ep3out.misc.bits.outPacketPending = false;
USB_EpnClearOutPacketReady();
}
}
if (myUsbDevice.ep3out.misc.bits.callback == true)
{
if (xferComplete == true)
{
myUsbDevice.ep3out.misc.bits.callback = false;
}
// In Isochronous mode, the meaning of the USBD_XferCompleteCb parameters changes:
// xferred is the number of bytes received in the last packet
// remaining is the current index into the circular buffer
numZeroBytesFromCb = USBD_XferCompleteCb(EP3OUT, status, count, myUsbDevice.ep3outIsoIdx);
// If data error occurred, the callback return value specifies how many zero-valued bytes to queue
if (numZeroBytesFromCb && (status == USB_STATUS_DATA_ERROR))
{
uint16_t numZeroBytesToWrite;
SI_SEGMENT_VARIABLE_SEGMENT_POINTER(bufPtr,
uint8_t,
SI_SEG_XDATA,
SI_SEG_DATA);
// Clear status after calling USBD_XferCompleteCb()
status = USB_STATUS_OK;
// Add the specified number of zero-value bytes
nextIdx = numZeroBytesFromCb + myUsbDevice.ep3outIsoIdx;
// Next index is past the end of the buffer (requires two writes)
if (nextIdx > myUsbDevice.ep3out.remaining)
{
// Write up to the end of the buffer
numZeroBytesToWrite = myUsbDevice.ep3out.remaining - myUsbDevice.ep3outIsoIdx;
bufPtr = &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx];
memclearXdata(bufPtr, numZeroBytesToWrite);
// Write the rest, starting at beginning of buffer
myUsbDevice.ep3outIsoIdx = nextIdx - myUsbDevice.ep3out.remaining;
numZeroBytesToWrite = myUsbDevice.ep3outIsoIdx;
bufPtr = &myUsbDevice.ep3out.buf[0];
memclearXdata(bufPtr, numZeroBytesToWrite);
}
// Next index is not past the end of the buffer
else
{
bufPtr = &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx];
memclearXdata(bufPtr, numZeroBytesFromCb);
myUsbDevice.ep3outIsoIdx = nextIdx;
}
}
USBD_XferCompleteCb(EP3OUT, status, count, myUsbDevice.ep3outIsoIdx);
#endif
}
}
}
/***************************************************************************//**
* @brief Sets all elements in a contiguous array of XDATA to zero
* @param s
* Pointer to the block of memory to fill
* @param n
* Number of bytes to be set to the value
******************************************************************************/
static void memclearXdata(SI_VARIABLE_SEGMENT_POINTER(s, uint8_t, SI_SEG_XDATA),
uint16_t n)
{
while (n)
{
*s++ = 0;
n--;
}
}
#endif // #if ((SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR))
#endif // EP3OUT_USED
/***************************************************************************//**
@@ -685,7 +553,7 @@ static void memclearXdata(SI_VARIABLE_SEGMENT_POINTER(s, uint8_t, SI_SEG_XDATA),
* @param dat
* Pointer to buffer to hold data read from the FIFO
******************************************************************************/
void USB_ReadFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC))
void USB_ReadFIFO(uint8_t fifoNum, uint8_t numBytes, uint8_t *dat)
{
if (numBytes > 0)
{
@@ -699,7 +567,7 @@ void USB_ReadFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER
switch (((SI_GEN_PTR_t *)&dat)->gptr.memtype)
{
case SI_GPTR_MTYPE_IDATA:
USB_ReadFIFO_Idata(numBytes, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_IDATA))dat, fifoNum);
USB_ReadFIFO_Idata(numBytes, dat, fifoNum);
break;
// For some compilers, IDATA and DATA are treated the same.
@@ -712,7 +580,7 @@ void USB_ReadFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER
#endif
case SI_GPTR_MTYPE_XDATA:
USB_ReadFIFO_Xdata(numBytes, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_XDATA))dat, fifoNum);
USB_ReadFIFO_Xdata(numBytes, dat, fifoNum);
break;
// For some compilers, XDATA and PDATA are treated the same.
@@ -750,7 +618,7 @@ void USB_ReadFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER
* If FALSE, the packet will be stored in the FIFO and the
* transmission must be started at a later time
******************************************************************************/
void USB_WriteFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC), bool txPacket)
void USB_WriteFIFO(uint8_t fifoNum, uint8_t numBytes, uint8_t *dat, bool txPacket)
{
USB_EnableWriteFIFO(fifoNum);
@@ -762,7 +630,7 @@ void USB_WriteFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTE
switch (((SI_GEN_PTR_t *)&dat)->gptr.memtype)
{
case SI_GPTR_MTYPE_IDATA:
USB_WriteFIFO_Idata(numBytes, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_IDATA))dat);
USB_WriteFIFO_Idata(numBytes, dat);
break;
// For some compilers, IDATA and DATA are treated the same.
@@ -775,7 +643,7 @@ void USB_WriteFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTE
#endif
case SI_GPTR_MTYPE_XDATA:
USB_WriteFIFO_Xdata(numBytes, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_XDATA))dat);
USB_WriteFIFO_Xdata(numBytes, dat);
break;
// For some compilers, XDATA and PDATA are treated the same.
@@ -788,7 +656,7 @@ void USB_WriteFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTE
#endif
case SI_GPTR_MTYPE_CODE:
USB_WriteFIFO_Code(numBytes, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_CODE))dat);
USB_WriteFIFO_Code(numBytes, dat);
break;
default:
@@ -944,10 +812,10 @@ static void USB_ReadFIFO_Data(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat,
{
while (--numBytes)
{
USB_GetFIFOByte(dat);
USB_GetFIFOByte(*dat);
dat++;
}
USB_GetLastFIFOByte(dat, fifoNum);
USB_GetLastFIFOByte(*dat, fifoNum);
}
/***************************************************************************//**
@@ -997,14 +865,14 @@ static void USB_WriteFIFO_Code(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat
* @param fifoNum
* USB FIFO to read
******************************************************************************/
static void USB_ReadFIFO_Generic(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC), uint8_t fifoNum)
static void USB_ReadFIFO_Generic(uint8_t numBytes, uint8_t *dat, uint8_t fifoNum)
{
while (--numBytes)
{
USB_GetFIFOByte(dat);
USB_GetFIFOByte(*dat);
dat++;
}
USB_GetLastFIFOByte(dat, fifoNum);
USB_GetLastFIFOByte(*dat, fifoNum);
}
/***************************************************************************//**
@@ -1016,7 +884,7 @@ static void USB_ReadFIFO_Generic(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(d
* @param dat
* Pointer to generic buffer holding data to write to the FIFO
******************************************************************************/
static void USB_WriteFIFO_Generic(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC))
static void USB_WriteFIFO_Generic(uint8_t numBytes, uint8_t *dat)
{
while (numBytes--)
{

View File

@@ -13,7 +13,7 @@
// Global variables
extern SI_SEGMENT_VARIABLE(myUsbDevice, USBD_Device_TypeDef, MEM_MODEL_SEG);
extern SI_SEGMENT_VARIABLE(txZero[2], const uint8_t, SI_SEG_CODE);
extern SI_SEGMENT_VARIABLE(txZero[2], uint8_t, SI_SEG_CODE);
// -----------------------------------------------------------------------------
// Function prototypes
@@ -48,12 +48,6 @@ void handleUsbOut3Int(void);
void SendEp0Stall(void);
#if SLAB_USB_UTF8_STRINGS == 1
static uint8_t decodeUtf8toUcs2(
const uint8_t *pUtf8in,
SI_VARIABLE_SEGMENT_POINTER(pUcs2out, uint16_t, MEM_MODEL_SEG));
#endif
// -----------------------------------------------------------------------------
// Functions
@@ -218,8 +212,6 @@ void usbIrqHandler(void)
******************************************************************************/
static void handleUsbEp0Int(void)
{
USB_Status_TypeDef retVal = USB_STATUS_REQ_UNHANDLED;
USB_SetIndex(0);
if (USB_Ep0SentStall() || USB_GetSetupEnd())
@@ -242,55 +234,32 @@ static void handleUsbEp0Int(void)
// Vendor unique, Class or Standard setup commands override?
#if SLAB_USB_SETUP_CMD_CB
retVal = USBD_SetupCmdCb(&myUsbDevice.setup);
if (retVal == USB_STATUS_REQ_UNHANDLED)
if (USBD_SetupCmdCb(&myUsbDevice.setup) == USB_STATUS_REQ_UNHANDLED)
{
#endif
if (myUsbDevice.setup.bmRequestType.Type == USB_SETUP_TYPE_STANDARD)
{
retVal = USBDCH9_SetupCmd();
}
#if SLAB_USB_SETUP_CMD_CB
}
#endif
// Reset index to 0 in case the call to USBD_SetupCmdCb() or
// USBDCH9_SetupCmd() changed it.
USB_SetIndex(0);
// Put the Enpoint 0 hardware into the correct state here.
if (retVal == USB_STATUS_OK)
if (myUsbDevice.setup.bmRequestType.Type == USB_SETUP_TYPE_STANDARD)
{
// If wLength is 0, there is no Data Phase
// Set both the Serviced Out Packet Ready and Data End bits
if (myUsbDevice.setup.wLength == 0)
{
USB_Ep0SetLastOutPacketReady();
}
// If wLength is non-zero, there is a Data Phase.
// Set only the Serviced Out Packet Ready bit.
else
{
USB_Ep0ServicedOutPacketReady();
#if SLAB_USB_SETUP_CMD_CB
// If OUT packet but callback didn't set up a USBD_Read and we are expecting a
// data byte then we need to wait for the read to be setup and NACK packets until
// USBD_Read is called.
if ((myUsbDevice.setup.bmRequestType.Direction == USB_SETUP_DIR_OUT)
&& (myUsbDevice.ep0.state != D_EP_RECEIVING))
{
myUsbDevice.ep0.misc.bits.waitForRead = true;
}
#endif
}
USBDCH9_SetupCmd();
}
// If the setup transaction detected an error, send a stall
else
{
SendEp0Stall();
}
#if SLAB_USB_SETUP_CMD_CB
}
else
{
// If in-packet but callback didn't setup a USBD_Read and we are expecting a data byte then
// we need to wait for the read to be setup and nack packets till USBD_Read is called.
if ((myUsbDevice.setup.bmRequestType.Direction == USB_SETUP_DIR_OUT)
&& (myUsbDevice.ep0.state != D_EP_RECEIVING)
&& (myUsbDevice.setup.wLength)
)
{
myUsbDevice.ep0.misc.bits.waitForRead = true;
}
}
#endif
}
else if (myUsbDevice.ep0.state == D_EP_RECEIVING)
{
@@ -312,9 +281,11 @@ static void handleUsbEp0Int(void)
******************************************************************************/
static void USB_ReadFIFOSetup(void)
{
SI_VARIABLE_SEGMENT_POINTER(ptr, uint16_t, MEM_MODEL_SEG) = (SI_VARIABLE_SEGMENT_POINTER(, uint16_t, MEM_MODEL_SEG))&myUsbDevice.setup;
uint16_t MEM_MODEL_SEG *ptr = &myUsbDevice.setup;
USB_ReadFIFO(0, 8, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))ptr);
USB_ReadFIFO(0, 8, (uint8_t *)ptr);
USB_Ep0ServicedOutPacketReady();
// Modify for Endian-ness of the compiler
ptr[1] = le16toh(ptr[1]);
@@ -368,11 +339,9 @@ static void handleUsbResetInt(void)
USB_EnableSuspendDetection();
USB_EnableDeviceInts();
// If the device is bus-powered, always put it in the Default state.
// If the device is self-powered and VBUS is present, put the device in the
// Default state. Otherwise, put it in the Attached state.
#if (!SLAB_USB_BUS_POWERED) && \
(!(SLAB_USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF))
// If VBUS is preset, put the device in the Default state.
// Otherwise, put it in the Attached state.
#if (!(SLAB_USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF))
if (USB_IsVbusOn())
{
USBD_SetUsbState(USBD_STATE_DEFAULT);
@@ -437,16 +406,12 @@ static void handleUsbEp0Tx(void)
// Strings can use the USB_STRING_DESCRIPTOR_UTF16LE_PACKED type to pack
// UTF16LE data without the zero's between each character.
// If the current string is of type USB_STRING_DESCRIPTOR_UTF16LE_PACKED,
// unpack it by inserting a zero between each character in the string.
if ((myUsbDevice.ep0String.encoding.type == USB_STRING_DESCRIPTOR_UTF16LE_PACKED)
#if SLAB_USB_UTF8_STRINGS == 1
|| (myUsbDevice.ep0String.encoding.type == USB_STRING_DESCRIPTOR_UTF8)
#endif
)
// unpacket it by inserting a zero between each character in the string.
if (myUsbDevice.ep0String.encoding.type == USB_STRING_DESCRIPTOR_UTF16LE_PACKED)
{
// If ep0String.encoding.init is true, this is the beginning of the string.
// The first two bytes of the string are the bLength and bDescriptorType
// fields. These are not packed like the reset of the string, so write them
// fields. These are no packed like the reset of the string, so write them
// to the FIFO and set ep0String.encoding.init to false.
if (myUsbDevice.ep0String.encoding.init == true)
{
@@ -459,36 +424,9 @@ static void handleUsbEp0Tx(void)
// Insert a 0x00 between each character of the string.
for (i = 0; i < count / 2; i++)
{
#if SLAB_USB_UTF8_STRINGS == 1
if (myUsbDevice.ep0String.encoding.type == USB_STRING_DESCRIPTOR_UTF8)
{
SI_SEGMENT_VARIABLE(ucs2, uint16_t, MEM_MODEL_SEG);
uint8_t utf8count;
// decode the utf8 into ucs2 for usb string
utf8count = decodeUtf8toUcs2(myUsbDevice.ep0.buf, &ucs2);
// if consumed utf8 bytes is 0, it means either null byte was
// input or bad utf8 byte sequence. Either way its an error and
// there's not much we can do. So just advance the input string
// by one character and keep going until count is expired.
if (utf8count == 0)
{
utf8count = 1;
}
// adjust to next char in utf8 byte sequence
myUsbDevice.ep0.buf += utf8count;
ucs2 = htole16(ucs2); // usb 16-bit chars are little endian
USB_WriteFIFO(0, 2, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))&ucs2, false);
}
else
#endif
{
USB_WriteFIFO(0, 1, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))myUsbDevice.ep0.buf, false);
myUsbDevice.ep0.buf++;
USB_WriteFIFO(0, 1, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))&txZero, false);
}
USB_WriteFIFO(0, 1, myUsbDevice.ep0.buf, false);
myUsbDevice.ep0.buf++;
USB_WriteFIFO(0, 1, &txZero, false);
}
}
// For any data other than USB_STRING_DESCRIPTOR_UTF16LE_PACKED, just send the
@@ -588,98 +526,6 @@ void SendEp0Stall(void)
USB_Ep0SendStall();
}
#if SLAB_USB_UTF8_STRINGS == 1
/***************************************************************************//**
* Decodes UTF-8 to UCS-2 (16-bit) character encoding that is used
* for USB string descriptors.
*
* @param pUtf8in pointer to next character in UTF-8 string
* @param pUcs2out pointer to location for 16-bit character output
*
* Decodes a UTF-8 byte sequence into a single UCS-2 character. This
* will only decode up to 16-bit code point and will not handle the
* 21-bit case (4 bytes input).
*
* For valid cases, the UTF8 character sequence decoded into a 16-bit
* character and stored at the location pointed at by _pUcs2out_.
* The function will then return the number of input bytes that were
* consumed (1, 2, or 3). The caller can use the return value to find
* the start of the next character sequence in a utf-8 string.
*
* If either of the input pointers are NULL, then 0 is returned.
*
* If the first input character is NULL, then the output 16-bit value
* will be set to NULL and the function will return 0.
*
* If any other invalid sequence is detected, then the 16-bit output
* will be set to the equivalent of the question mark character (0x003F)
* and the return code will be 0.
*
* @return count of UTF8 bytes consumed
******************************************************************************/
static uint8_t decodeUtf8toUcs2(
const uint8_t *pUtf8in,
SI_VARIABLE_SEGMENT_POINTER(pUcs2out, uint16_t, MEM_MODEL_SEG))
{
uint8_t ret = 0;
// check the input pointers
if (!pUtf8in || !pUcs2out)
{
return 0;
}
// set default decode to error '?';
*pUcs2out = '?';
// valid cases:
// 0xxxxxxx (7 bits)
// 110xxxxx 10xxxxxx (11 bits)
// 1110xxxx 10xxxxxx 10xxxxxx (16 bits)
// null input
if (pUtf8in[0] == 0)
{
*pUcs2out = 0;
ret = 0;
}
// 7-bit char
else if (pUtf8in[0] < 128)
{
*pUcs2out = pUtf8in[0];
ret = 1;
}
// 11-bit char
else if ((pUtf8in[0] & 0xE0) == 0xC0)
{
if ((pUtf8in[1] & 0xC0) == 0x80)
{
*pUcs2out = ((pUtf8in[0] & 0x1F) << 6) | (pUtf8in[1] & 0x3F);
ret = 2;
}
}
// 16-bit char
else if ((pUtf8in[0] & 0xF0) == 0xE0)
{
if ((pUtf8in[1] & 0xC0) == 0x80)
{
if ((pUtf8in[2] & 0xC0) == 0x80)
{
*pUcs2out = ((pUtf8in[0] & 0x0F) << 12)
| ((pUtf8in[1] & 0x3F) << 6)
| (pUtf8in[2] & 0x3F);
ret = 3;
}
}
}
return ret;
}
#endif // SLAB_USB_UTF8_STRINGS
// This function is called from USBD_Init(). It forces the user project to pull
// this module from the library so that the declared ISR can be seen and
// included. If this is not done then this entire module by never be included