move to targets/
This commit is contained in:
16
Makefile
16
Makefile
@ -32,24 +32,24 @@ cbor:
|
||||
test: testgcm
|
||||
|
||||
efm8prog:
|
||||
cd '.\efm8\Keil 8051 v9.53 - Debug' && $(MAKE) all
|
||||
cd './targets/efm8\Keil 8051 v9.53 - Debug' && $(MAKE) all
|
||||
flashefm8.exe -part EFM8UB10F8G -sn 440105518 -erase
|
||||
flashefm8.exe -part EFM8UB10F8G -sn 440105518 -upload '.\efm8\Keil 8051 v9.53 - Debug\efm8.hex'
|
||||
flashefm8.exe -part EFM8UB10F8G -sn 440105518 -upload './targets/efm8/Keil 8051 v9.53 - Debug/efm8.hex'
|
||||
|
||||
efm32com:
|
||||
cd '.\efm32\GNU ARM v7.2.1 - Debug' && $(MAKE) all
|
||||
cd './targets/efm32/GNU ARM v7.2.1 - Debug' && $(MAKE) all
|
||||
efm32prog:
|
||||
cd '.\efm32\GNU ARM v7.2.1 - Debug' && $(MAKE) all
|
||||
commander flash '.\efm32\GNU ARM v7.2.1 - Debug\EFM32.hex' $(EFM32_DEBUGGER) -p "0x1E7FC:0x00000000:4"
|
||||
cd './targets/efm32/GNU ARM v7.2.1 - Debug' && $(MAKE) all
|
||||
commander flash './targets/efm32/GNU ARM v7.2.1 - Debug/EFM32.hex' $(EFM32_DEBUGGER) -p "0x1E7FC:0x00000000:4"
|
||||
efm32read:
|
||||
cd '.\efm32\GNU ARM v7.2.1 - Debug' && $(MAKE) all
|
||||
cd './targets/efm32/GNU ARM v7.2.1 - Debug' && $(MAKE) all
|
||||
commander swo read $(EFM32_DEBUGGER)
|
||||
|
||||
|
||||
|
||||
efm32bootprog:
|
||||
cd '.\efm32boot\GNU ARM v7.2.1 - Debug' && $(MAKE) all
|
||||
commander flash '.\efm32boot\GNU ARM v7.2.1 - Debug\efm32boot.hex' $(EFM32_DEBUGGER) --masserase
|
||||
cd './targets/efm32boot/GNU ARM v7.2.1 - Debug' && $(MAKE) all
|
||||
commander flash './efm32boot/GNU ARM v7.2.1 - Debug/efm32boot.hex' $(EFM32_DEBUGGER) --masserase
|
||||
|
||||
$(name): $(obj)
|
||||
$(CC) $(LDFLAGS) -o $@ $(obj) $(LDFLAGS)
|
||||
|
@ -1,15 +0,0 @@
|
||||
/**************************************************************************//**
|
||||
* Copyright (c) 2015 by Silicon Laboratories Inc. All rights reserved.
|
||||
*
|
||||
* http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef NDEBUG
|
||||
void slab_Assert( const char * file, int line )
|
||||
{
|
||||
file = file;
|
||||
line = line;
|
||||
|
||||
while ( 1 );
|
||||
}
|
||||
#endif
|
@ -1,60 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2014 by Silicon Laboratories Inc. All rights reserved.
|
||||
*
|
||||
* http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __ASSERT_H__
|
||||
|
||||
#include "efm8_config.h"
|
||||
|
||||
/**************************************************************************//**
|
||||
* @addtogroup efm8_assert
|
||||
* @{
|
||||
*
|
||||
* @brief Runtime assert for EFM8
|
||||
*
|
||||
* This module contains a runtime assert macro. It can be compiled out by setting
|
||||
* the NDEBUG flag.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************//**
|
||||
* @def NDEBUG
|
||||
* @brief Controls if the asserts are present.
|
||||
*
|
||||
* Asserts are removed if this symbol is defined
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************************************//**
|
||||
* @def USER_ASSERT
|
||||
* @brief User implemented assert function.
|
||||
*
|
||||
* When asserts are enabled the default handler can be be replaced with a user defined
|
||||
* function of the form 'void userAssertName( const char * file, int line )' by setting
|
||||
* the value of USER_ASSERT to the userAssertName.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************************************//**
|
||||
* @def SLAB_ASSERT(expr)
|
||||
* @brief default implementation of assert_failed.
|
||||
*
|
||||
* This function can be replaced by a user defined assert function by setting the USER_ASSERT flag
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define SLAB_ASSERT(expr)
|
||||
#else
|
||||
#ifdef USER_ASSERT
|
||||
#define SLAB_ASSERT(expr) ((expr) ? ((void)0) : USER_ASSERT( __FILE__, __LINE__ ))
|
||||
#else
|
||||
void slab_Assert( const char * file, int line );
|
||||
//Yes this is smaller than if(!expr){assert}
|
||||
#define SLAB_ASSERT(expr) if(expr){}else{slab_Assert( __FILE__, __LINE__ );}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif //!__ASSERT_H__
|
@ -1,56 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
Readme.txt
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Copyright 2014 Silicon Laboratories, Inc.
|
||||
http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt
|
||||
|
||||
Program Description:
|
||||
-------------------
|
||||
|
||||
This is the generic EFM8 USB Firmware Library. Please see the EFM8 Libraries
|
||||
Documentation for more information (/doc/EFM8/software/Lib/index.html).
|
||||
|
||||
Known Issues and Limitations:
|
||||
----------------------------
|
||||
|
||||
1) The library does not reset its Data Toggle after receiving a SET_INTERFACE
|
||||
request.
|
||||
|
||||
Target and Tool Chain Information:
|
||||
---------------------------------
|
||||
|
||||
Target: EFM8UB1, EFM8UB2, C8051F320/1, C8051F326/7, C8051F34x, C8051F38x
|
||||
Tool chain: Keil
|
||||
|
||||
File List:
|
||||
---------
|
||||
|
||||
/inc/efm8_usb.h
|
||||
/src/efm8_usbd.c
|
||||
/src/efm8_usbdch9.c
|
||||
/src/efm8_usbdep.c
|
||||
/src/efm8_usbdint.c
|
||||
|
||||
Release Information:
|
||||
-------------------
|
||||
|
||||
Version 1.0.0
|
||||
- Initial release.
|
||||
|
||||
Version 1.0.1
|
||||
- Fixed bug in logic of remote wakeup feature where the device would
|
||||
attempt to wake the host before enabling its USB transceiver.
|
||||
- Fixed bug where the device would stall the Data Phase instead of the
|
||||
Setup Phase when sending a procedural stall on Endpoint 0.
|
||||
- Fixed bug where a bus-powered device would look at VBUS after a USB Reset
|
||||
to determine if it should enter the Default or Attached State. VBUS is
|
||||
always present on a bus-powered device, so it should automatically enter
|
||||
the Default State.
|
||||
- Removed code that generated a compiler warning when
|
||||
USB_PWRSAVE_MODE_FASTWAKE was enabled.
|
||||
- Improved documentation of USB_PWRSAVE_MODE_FASTWAKE feature.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
End Of File
|
||||
-------------------------------------------------------------------------------
|
File diff suppressed because it is too large
Load Diff
@ -1,755 +0,0 @@
|
||||
/**************************************************************************//**
|
||||
* Copyright (c) 2015 by Silicon Laboratories Inc. All rights reserved.
|
||||
*
|
||||
* http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt
|
||||
*****************************************************************************/
|
||||
|
||||
#include "si_toolchain.h"
|
||||
#include "efm8_usb.h"
|
||||
//#include "assert.h"
|
||||
#include <stdint.h>
|
||||
#define SLAB_ASSERT(x)
|
||||
// -----------------------------------------------------------------------------
|
||||
// Global Variables
|
||||
|
||||
/// Tracks the state of the USB device and endpoints and contains pointers
|
||||
/// to all descriptors.
|
||||
SI_SEGMENT_VARIABLE(myUsbDevice, USBD_Device_TypeDef, MEM_MODEL_SEG);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Macros
|
||||
|
||||
/// Returns the requested endpoint object of type USBD_Ep_TypeDef
|
||||
/// This macro does not check that epAddr is valid, so the calling function
|
||||
/// should verify epAddr before using the macro.
|
||||
#define GetEp(epAddr) (&myUsbDevice.ep0 + epAddr)
|
||||
|
||||
|
||||
#if SLAB_USB_POLLED_MODE
|
||||
#define DISABLE_USB_INTS {}
|
||||
#define ENABLE_USB_INTS {}
|
||||
|
||||
#else
|
||||
/// Saves the current state of the USB Interrupt Enable to a variable called
|
||||
/// usbIntsEnabled, then disables USB interrupts.
|
||||
#define DISABLE_USB_INTS { usbIntsEnabled = USB_GetIntsEnabled(); USB_DisableInts(); }
|
||||
|
||||
/// Sets the USB Interrupt Enable bit to the value of usbIntsEnabled.
|
||||
/// @ref DISABLE_USB_INTS must be used before this macro is used.
|
||||
#define ENABLE_USB_INTS { if (usbIntsEnabled) {USB_EnableInts(); } }
|
||||
#endif // SLAB_USB_POLLED_MODE
|
||||
|
||||
// Function in efm8_usbdint.c to force load the module for libraries
|
||||
extern void forceModuleLoad_usbint(void);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// USB API Functions
|
||||
|
||||
void USBD_AbortAllTransfers(void)
|
||||
{
|
||||
uint8_t i;
|
||||
bool usbIntsEnabled;
|
||||
|
||||
USB_SaveSfrPage();
|
||||
DISABLE_USB_INTS;
|
||||
|
||||
// Call USBD_AbortTransfer() for each endpoint
|
||||
for (i = 1; i < SLAB_USB_NUM_EPS_USED; i++)
|
||||
{
|
||||
USBD_AbortTransfer(i);
|
||||
}
|
||||
|
||||
ENABLE_USB_INTS;
|
||||
USB_RestoreSfrPage();
|
||||
}
|
||||
|
||||
int8_t USBD_AbortTransfer(uint8_t epAddr)
|
||||
{
|
||||
USBD_Ep_TypeDef MEM_MODEL_SEG *ep;
|
||||
uint8_t retVal = USB_STATUS_OK;
|
||||
bool usbIntsEnabled;
|
||||
|
||||
USB_SaveSfrPage();
|
||||
|
||||
// Verify this is a valid endpoint address and is not Endpoint 0.
|
||||
if ((epAddr == EP0) || (epAddr >= SLAB_USB_NUM_EPS_USED))
|
||||
{
|
||||
SLAB_ASSERT(false);
|
||||
retVal = USB_STATUS_ILLEGAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
DISABLE_USB_INTS;
|
||||
ep = GetEp(epAddr);
|
||||
|
||||
// If the state of the endpoint is already idle, there is not need to abort
|
||||
// a transfer
|
||||
if (ep->state != D_EP_IDLE)
|
||||
{
|
||||
switch (epAddr)
|
||||
{
|
||||
#if SLAB_USB_EP1IN_USED
|
||||
case EP1IN:
|
||||
USB_AbortInEp(1);
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP2IN_USED
|
||||
case EP2IN:
|
||||
USB_AbortInEp(2);
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP3IN_USED
|
||||
case EP3IN:
|
||||
USB_AbortInEp(3);
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP1OUT_USED
|
||||
case EP1OUT:
|
||||
USB_AbortOutEp(1);
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP2OUT_USED
|
||||
case EP2OUT:
|
||||
USB_AbortOutEp(2);
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP3OUT_USED
|
||||
case EP3OUT:
|
||||
USB_AbortOutEp(3);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set the endpoint state to idle and clear out endpoint state variables
|
||||
ep->state = D_EP_IDLE;
|
||||
ep->misc.c = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ENABLE_USB_INTS;
|
||||
USB_RestoreSfrPage();
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void USBD_Connect(void)
|
||||
{
|
||||
USB_SaveSfrPage();
|
||||
myUsbDevice.ep0.state = D_EP_IDLE;
|
||||
USB_EnablePullUpResistor();
|
||||
USB_EnableTransceiver();
|
||||
USB_RestoreSfrPage();
|
||||
}
|
||||
|
||||
void USBD_Disconnect(void)
|
||||
{
|
||||
USB_SaveSfrPage();
|
||||
USB_DisablePullUpResistor();
|
||||
USB_RestoreSfrPage();
|
||||
}
|
||||
|
||||
bool USBD_EpIsBusy(uint8_t epAddr)
|
||||
{
|
||||
USBD_Ep_TypeDef MEM_MODEL_SEG *ep;
|
||||
|
||||
// Verify this is a valid endpoint address
|
||||
if (epAddr >= SLAB_USB_NUM_EPS_USED)
|
||||
{
|
||||
SLAB_ASSERT(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
ep = GetEp(epAddr);
|
||||
|
||||
if (ep->state == D_EP_IDLE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
USBD_State_TypeDef USBD_GetUsbState(void)
|
||||
{
|
||||
return myUsbDevice.state;
|
||||
}
|
||||
|
||||
int8_t USBD_Init(const USBD_Init_TypeDef *p)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
USB_SaveSfrPage();
|
||||
USB_DisableInts();
|
||||
|
||||
// This forces the liner to bring in the contents efm8_usbdint
|
||||
// It is place here since all users MUST call this function
|
||||
// for the library to work properly
|
||||
forceModuleLoad_usbint();
|
||||
|
||||
|
||||
// Zero out the myUsbDevice struct, then initialize all non-zero members
|
||||
for (i = 0; i < sizeof(myUsbDevice); i++)
|
||||
{
|
||||
*((uint8_t MEM_MODEL_SEG *)&myUsbDevice + i) = 0;
|
||||
}
|
||||
|
||||
// Get the USB descriptors from p
|
||||
myUsbDevice.deviceDescriptor = p->deviceDescriptor;
|
||||
myUsbDevice.configDescriptor = (USB_ConfigurationDescriptor_TypeDef *)p->configDescriptor;
|
||||
myUsbDevice.stringDescriptors = p->stringDescriptors;
|
||||
myUsbDevice.numberOfStrings = p->numberOfStrings;
|
||||
|
||||
// Enable USB clock
|
||||
#if SLAB_USB_FULL_SPEED
|
||||
USB_SetClockIntOsc();
|
||||
USB_SelectFullSpeed();
|
||||
#else
|
||||
USB_SetClockIntOscDiv8();
|
||||
USB_SelectLowSpeed();
|
||||
#endif // SLAB_USB_FULL_SPEED
|
||||
|
||||
// Enable or disable VBUS detection
|
||||
#if SLAB_USB_BUS_POWERED
|
||||
USB_VbusDetectDisable();
|
||||
#else
|
||||
USB_VbusDetectEnable();
|
||||
#endif
|
||||
|
||||
USB_ForceReset();
|
||||
USB_EnableDeviceInts();
|
||||
USBD_Connect();
|
||||
|
||||
// If VBUS is present, the state should be Default.
|
||||
// Otherwise, it is Attached.
|
||||
#if SLAB_USB_BUS_POWERED
|
||||
myUsbDevice.state = USBD_STATE_DEFAULT;
|
||||
#else
|
||||
if (USB_IsVbusOn())
|
||||
{
|
||||
myUsbDevice.state = USBD_STATE_DEFAULT;
|
||||
}
|
||||
else
|
||||
{
|
||||
myUsbDevice.state = USBD_STATE_ATTACHED;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Only enable USB interrupts when not in polled mode
|
||||
#if (SLAB_USB_POLLED_MODE == 0)
|
||||
USB_EnableInts();
|
||||
#endif
|
||||
|
||||
USB_RestoreSfrPage();
|
||||
USB_DisableInhibit();
|
||||
|
||||
return USB_STATUS_OK;
|
||||
}
|
||||
|
||||
int8_t USBD_Read(uint8_t epAddr,
|
||||
uint8_t *dat,
|
||||
uint16_t byteCount,
|
||||
bool callback)
|
||||
{
|
||||
bool usbIntsEnabled;
|
||||
USBD_Ep_TypeDef MEM_MODEL_SEG *ep;
|
||||
|
||||
USB_SaveSfrPage();
|
||||
|
||||
// Verify the endpoint address is valid.
|
||||
switch (epAddr)
|
||||
{
|
||||
case EP0:
|
||||
#if SLAB_USB_EP1OUT_USED
|
||||
case EP1OUT:
|
||||
#endif
|
||||
#if SLAB_USB_EP2OUT_USED
|
||||
case EP2OUT:
|
||||
#endif
|
||||
#if SLAB_USB_EP3OUT_USED
|
||||
case EP3OUT:
|
||||
#endif
|
||||
break;
|
||||
#if SLAB_USB_EP1IN_USED
|
||||
case EP1IN:
|
||||
#endif
|
||||
#if SLAB_USB_EP2IN_USED
|
||||
case EP2IN:
|
||||
#endif
|
||||
#if SLAB_USB_EP3IN_USED
|
||||
case EP3IN:
|
||||
#endif
|
||||
default:
|
||||
SLAB_ASSERT(false);
|
||||
return USB_STATUS_ILLEGAL;
|
||||
}
|
||||
|
||||
// If the device has not been configured, we cannot start a transfer.
|
||||
if ((epAddr != EP0) && (myUsbDevice.state != USBD_STATE_CONFIGURED))
|
||||
{
|
||||
return USB_STATUS_DEVICE_UNCONFIGURED;
|
||||
}
|
||||
|
||||
ep = GetEp(epAddr);
|
||||
|
||||
// If the endpoint is not idle, we cannot start a new transfer.
|
||||
// Return the appropriate error code.
|
||||
if (ep->state != D_EP_IDLE)
|
||||
{
|
||||
if (ep->state == D_EP_STALL)
|
||||
{
|
||||
return USB_STATUS_EP_STALLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
return USB_STATUS_EP_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
DISABLE_USB_INTS;
|
||||
|
||||
ep->buf = dat;
|
||||
ep->remaining = byteCount;
|
||||
ep->state = D_EP_RECEIVING;
|
||||
ep->misc.bits.callback = callback;
|
||||
ep->misc.bits.waitForRead = false;
|
||||
|
||||
// If isochronous, set the buffer index to 0
|
||||
#if ((SLAB_USB_EP3OUT_USED) && (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC))
|
||||
if (epAddr == EP3OUT)
|
||||
{
|
||||
myUsbDevice.ep3outIsoIdx = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
ENABLE_USB_INTS;
|
||||
USB_RestoreSfrPage();
|
||||
|
||||
return USB_STATUS_OK;
|
||||
}
|
||||
|
||||
#if SLAB_USB_REMOTE_WAKEUP_ENABLED
|
||||
int8_t USBD_RemoteWakeup(void)
|
||||
{
|
||||
// The device must be suspended and Remote Wakeup must have been previously
|
||||
// configured with a SET_FEATURE (Remote Wakeup) command.
|
||||
if ((myUsbDevice.state != USBD_STATE_SUSPENDED) ||
|
||||
(myUsbDevice.remoteWakeupEnabled == false))
|
||||
{
|
||||
return USB_STATUS_ILLEGAL;
|
||||
}
|
||||
|
||||
USB_ForceResume();
|
||||
USBD_RemoteWakeupDelay(); // Application will provide the delay between
|
||||
// starting and stopping the resume signal.
|
||||
USB_ClearResume();
|
||||
|
||||
return USB_STATUS_OK;
|
||||
}
|
||||
#endif // SLAB_USB_REMOTE_WAKEUP_ENABLED
|
||||
|
||||
#if SLAB_USB_POLLED_MODE
|
||||
void USBD_Run(void)
|
||||
{
|
||||
usbIrqHandler();
|
||||
}
|
||||
#endif // SLAB_USB_POLLED_MODE
|
||||
|
||||
int8_t USBD_StallEp(uint8_t epAddr)
|
||||
{
|
||||
bool usbIntsEnabled;
|
||||
|
||||
USB_SaveSfrPage();
|
||||
|
||||
// Verify the endpoint address is valid and not Endpoint 0.
|
||||
if ((epAddr == EP0) || (epAddr >= SLAB_USB_NUM_EPS_USED))
|
||||
{
|
||||
SLAB_ASSERT(false);
|
||||
return USB_STATUS_ILLEGAL;
|
||||
}
|
||||
|
||||
DISABLE_USB_INTS;
|
||||
|
||||
// Halt the appropriate endpoint by sending a stall and setting the endpoint
|
||||
// state to Halted (D_EP_HALT).
|
||||
switch (epAddr)
|
||||
{
|
||||
#if SLAB_USB_EP1IN_USED
|
||||
case (EP1IN):
|
||||
myUsbDevice.ep1in.state = D_EP_HALT;
|
||||
USB_SetIndex(1);
|
||||
USB_EpnInStall();
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP2IN_USED
|
||||
case (EP2IN):
|
||||
myUsbDevice.ep2in.state = D_EP_HALT;
|
||||
USB_SetIndex(2);
|
||||
USB_EpnInStall();
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP3IN_USED
|
||||
case (EP3IN):
|
||||
myUsbDevice.ep3in.state = D_EP_HALT;
|
||||
USB_SetIndex(3);
|
||||
USB_EpnInStall();
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP1OUT_USED
|
||||
case (EP1OUT):
|
||||
myUsbDevice.ep1out.state = D_EP_HALT;
|
||||
USB_SetIndex(1);
|
||||
USB_EpnOutStall();
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP2OUT_USED
|
||||
case (EP2OUT):
|
||||
myUsbDevice.ep2out.state = D_EP_HALT;
|
||||
USB_SetIndex(2);
|
||||
USB_EpnOutStall();
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP3OUT_USED
|
||||
case (EP3OUT):
|
||||
myUsbDevice.ep3out.state = D_EP_HALT;
|
||||
USB_SetIndex(3);
|
||||
USB_EpnOutStall();
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
ENABLE_USB_INTS;
|
||||
USB_RestoreSfrPage();
|
||||
|
||||
return USB_STATUS_OK;
|
||||
}
|
||||
|
||||
void USBD_Stop(void)
|
||||
{
|
||||
USB_DisableInts();
|
||||
USBD_Disconnect();
|
||||
USBD_SetUsbState(USBD_STATE_NONE);
|
||||
}
|
||||
|
||||
void USBD_Suspend(void)
|
||||
{
|
||||
uint8_t i;
|
||||
bool regulatorEnabled, prefetchEnabled;
|
||||
|
||||
USB_SaveSfrPage();
|
||||
|
||||
// If the USB_PWRSAVE_MODE_ONVBUSOFF is enabled, we can enter suspend if VBUS
|
||||
// is not present even if the USB has not detected a suspend event.
|
||||
#if ((!(SLAB_USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF)) || \
|
||||
(SLAB_USB_BUS_POWERED))
|
||||
if (USB_IsSuspended() == true)
|
||||
#else
|
||||
if ((USB_IsSuspended() == true) || (USB_IsVbusOn() == false))
|
||||
#endif
|
||||
{
|
||||
USB_SuspendTransceiver();
|
||||
|
||||
#if SLAB_USB_FULL_SPEED
|
||||
USB_SetSuspendClock();
|
||||
#endif
|
||||
|
||||
// Get the state of the prefetch engine enable bit and disable the prefetch
|
||||
// engine
|
||||
prefetchEnabled = USB_IsPrefetchEnabled();
|
||||
USB_DisablePrefetch();
|
||||
|
||||
// Get the state of the internal regulator before suspending it.
|
||||
if (USB_IsRegulatorEnabled() == true)
|
||||
{
|
||||
regulatorEnabled = true;
|
||||
|
||||
#if (SLAB_USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_FASTWAKE)
|
||||
USB_SuspendRegulatorFastWake();
|
||||
#else
|
||||
USB_SuspendRegulator();
|
||||
|
||||
// Wait at least 12 clock instructions before halting the internal oscillator
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
regulatorEnabled = false;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
USB_SuspendOscillator();
|
||||
|
||||
// When we arrive here, the device has waked from suspend mode.
|
||||
|
||||
#if SLAB_USB_REMOTE_WAKEUP_ENABLED
|
||||
// If remote wakeup is enabled, query the application if the remote
|
||||
// wakeup event occurred. If so, exit USBD_Suspend().
|
||||
if (USB_IsSuspended() == true)
|
||||
{
|
||||
if (USBD_RemoteWakeupCb() == true)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if ((!(SLAB_USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF)) && \
|
||||
(SLAB_USB_BUS_POWERED == 0))
|
||||
// If the USB_PWRSAVE_MODE_ONVBUSOFF mode is disabled, VBUS has been
|
||||
// removed, so exit USBD_Suspend().
|
||||
if (USB_IsVbusOn() == false)
|
||||
{
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
} while (USB_IsSuspended() == true);
|
||||
|
||||
// Restore the internal regulator
|
||||
if (regulatorEnabled == true)
|
||||
{
|
||||
USB_UnsuspendRegulator();
|
||||
}
|
||||
|
||||
// Restore the prefetch engine
|
||||
if (prefetchEnabled == true)
|
||||
{
|
||||
USB_EnablePrefetch();
|
||||
}
|
||||
|
||||
#if SLAB_USB_FULL_SPEED
|
||||
// Restore the clock
|
||||
USB_SetNormalClock();
|
||||
#endif
|
||||
USB_EnableTransceiver();
|
||||
}
|
||||
|
||||
USB_RestoreSfrPage();
|
||||
}
|
||||
|
||||
int8_t USBD_UnStallEp(uint8_t epAddr)
|
||||
{
|
||||
bool usbIntsEnabled;
|
||||
|
||||
USB_SaveSfrPage();
|
||||
|
||||
// Verify the endpoint address is valid and not Endpoint 0.
|
||||
if ((epAddr == EP0) || (epAddr >= SLAB_USB_NUM_EPS_USED))
|
||||
{
|
||||
SLAB_ASSERT(false);
|
||||
return USB_STATUS_ILLEGAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
DISABLE_USB_INTS;
|
||||
|
||||
// End the stall condition and set the endpoint state to idle.
|
||||
switch (epAddr)
|
||||
{
|
||||
#if SLAB_USB_EP1IN_USED
|
||||
case (EP1IN):
|
||||
myUsbDevice.ep1in.state = D_EP_IDLE;
|
||||
USB_SetIndex(1);
|
||||
USB_EpnInEndStall();
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP2IN_USED
|
||||
case (EP2IN):
|
||||
myUsbDevice.ep2in.state = D_EP_IDLE;
|
||||
USB_SetIndex(2);
|
||||
USB_EpnInEndStall();
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP3IN_USED
|
||||
case (EP3IN):
|
||||
myUsbDevice.ep3in.state = D_EP_IDLE;
|
||||
USB_SetIndex(3);
|
||||
USB_EpnInEndStall();
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP1OUT_USED
|
||||
case (EP1OUT):
|
||||
myUsbDevice.ep1out.state = D_EP_IDLE;
|
||||
USB_SetIndex(1);
|
||||
USB_EpnOutEndStall();
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP2OUT_USED
|
||||
case (EP2OUT):
|
||||
myUsbDevice.ep2out.state = D_EP_IDLE;
|
||||
USB_SetIndex(2);
|
||||
USB_EpnOutEndStall();
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP3OUT_USED
|
||||
case (EP3OUT):
|
||||
myUsbDevice.ep3out.state = D_EP_IDLE;
|
||||
USB_SetIndex(3);
|
||||
USB_EpnOutEndStall();
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
ENABLE_USB_INTS;
|
||||
USB_RestoreSfrPage();
|
||||
}
|
||||
|
||||
return USB_STATUS_OK;
|
||||
}
|
||||
|
||||
int8_t USBD_Write(uint8_t epAddr,
|
||||
uint8_t *dat,
|
||||
uint16_t byteCount,
|
||||
bool callback)
|
||||
{
|
||||
bool usbIntsEnabled;
|
||||
USBD_Ep_TypeDef MEM_MODEL_SEG *ep;
|
||||
|
||||
USB_SaveSfrPage();
|
||||
|
||||
// Verify the endpoint address is valid.
|
||||
switch (epAddr)
|
||||
{
|
||||
case EP0:
|
||||
#if SLAB_USB_EP1IN_USED
|
||||
case EP1IN:
|
||||
#endif
|
||||
#if SLAB_USB_EP2IN_USED
|
||||
case EP2IN:
|
||||
#endif
|
||||
#if SLAB_USB_EP3IN_USED
|
||||
case EP3IN:
|
||||
#endif
|
||||
break;
|
||||
#if SLAB_USB_EP1OUT_USED
|
||||
case EP1OUT:
|
||||
#endif
|
||||
#if SLAB_USB_EP2OUT_USED
|
||||
case EP2OUT:
|
||||
#endif
|
||||
#if SLAB_USB_EP3OUT_USED
|
||||
case EP3OUT:
|
||||
#endif
|
||||
default:
|
||||
SLAB_ASSERT(false);
|
||||
return USB_STATUS_ILLEGAL;
|
||||
}
|
||||
|
||||
// If the device is not configured and it is not Endpoint 0, we cannot begin
|
||||
// a transfer.
|
||||
if ((epAddr != EP0) && (myUsbDevice.state != USBD_STATE_CONFIGURED))
|
||||
{
|
||||
return USB_STATUS_DEVICE_UNCONFIGURED;
|
||||
}
|
||||
|
||||
ep = GetEp(epAddr);
|
||||
|
||||
// If the endpoint is not idle, we cannot start a new transfer.
|
||||
// Return the appropriate error code.
|
||||
if (ep->state != D_EP_IDLE)
|
||||
{
|
||||
if (ep->state == D_EP_STALL)
|
||||
{
|
||||
return USB_STATUS_EP_STALLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
return USB_STATUS_EP_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
DISABLE_USB_INTS;
|
||||
|
||||
ep->buf = dat;
|
||||
ep->remaining = byteCount;
|
||||
ep->state = D_EP_TRANSMITTING;
|
||||
ep->misc.bits.callback = callback;
|
||||
|
||||
switch (epAddr)
|
||||
{
|
||||
// For Endpoint 0, set the inPacketPending flag to true. The USB handler
|
||||
// will see this on the next SOF and begin the transfer.
|
||||
case (EP0):
|
||||
myUsbDevice.ep0.misc.bits.inPacketPending = true;
|
||||
break;
|
||||
|
||||
// For data endpoints, we will call USB_WriteFIFO here to reduce latency
|
||||
// between the call to USBD_Write() and the first packet being sent.
|
||||
#if SLAB_USB_EP1IN_USED
|
||||
case (EP1IN):
|
||||
USB_WriteFIFO(1,
|
||||
(byteCount > SLAB_USB_EP1IN_MAX_PACKET_SIZE) ? SLAB_USB_EP1IN_MAX_PACKET_SIZE : byteCount,
|
||||
myUsbDevice.ep1in.buf,
|
||||
true);
|
||||
break;
|
||||
#endif // SLAB_USB_EP1IN_USED
|
||||
#if SLAB_USB_EP2IN_USED
|
||||
case (EP2IN):
|
||||
USB_WriteFIFO(2,
|
||||
(byteCount > SLAB_USB_EP2IN_MAX_PACKET_SIZE) ? SLAB_USB_EP2IN_MAX_PACKET_SIZE : byteCount,
|
||||
myUsbDevice.ep2in.buf,
|
||||
true);
|
||||
break;
|
||||
#endif // SLAB_USB_EP2IN_USED
|
||||
#if SLAB_USB_EP3IN_USED
|
||||
case (EP3IN):
|
||||
#if ((SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_INTR))
|
||||
USB_WriteFIFO(3,
|
||||
(byteCount > SLAB_USB_EP3IN_MAX_PACKET_SIZE) ? SLAB_USB_EP3IN_MAX_PACKET_SIZE : byteCount,
|
||||
myUsbDevice.ep3in.buf,
|
||||
true);
|
||||
#elif (SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_ISOC)
|
||||
myUsbDevice.ep3in.misc.bits.inPacketPending = true;
|
||||
myUsbDevice.ep3inIsoIdx = 0;
|
||||
#endif
|
||||
break;
|
||||
#endif // SLAB_USB_EP3IN_USED
|
||||
}
|
||||
|
||||
ENABLE_USB_INTS;
|
||||
USB_RestoreSfrPage();
|
||||
|
||||
return USB_STATUS_OK;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// UtilityFunctions
|
||||
|
||||
void USBD_SetUsbState(USBD_State_TypeDef newState)
|
||||
{
|
||||
#if (SLAB_USB_SUPPORT_ALT_INTERFACES)
|
||||
uint8_t i;
|
||||
#endif
|
||||
USBD_State_TypeDef currentState;
|
||||
|
||||
currentState = myUsbDevice.state;
|
||||
|
||||
// If the device is un-configuring, disable the data endpoints and clear out
|
||||
// alternate interface settings
|
||||
if ((currentState >= USBD_STATE_SUSPENDED)
|
||||
&& (newState < USBD_STATE_SUSPENDED))
|
||||
{
|
||||
USBD_AbortAllTransfers();
|
||||
|
||||
#if (SLAB_USB_SUPPORT_ALT_INTERFACES)
|
||||
for (i = 0; i < SLAB_USB_NUM_INTERFACES; i++)
|
||||
{
|
||||
myUsbDevice.interfaceAltSetting[i] = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (newState == USBD_STATE_SUSPENDED)
|
||||
{
|
||||
myUsbDevice.savedState = currentState;
|
||||
}
|
||||
|
||||
myUsbDevice.state = newState;
|
||||
|
||||
#if SLAB_USB_STATE_CHANGE_CB
|
||||
if (currentState != newState)
|
||||
{
|
||||
USBD_DeviceStateChangeCb(currentState, newState);
|
||||
}
|
||||
#endif
|
||||
}
|
@ -1,880 +0,0 @@
|
||||
/**************************************************************************//**
|
||||
* Copyright (c) 2015 by Silicon Laboratories Inc. All rights reserved.
|
||||
*
|
||||
* http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt
|
||||
*****************************************************************************/
|
||||
|
||||
#include "si_toolchain.h"
|
||||
#include "efm8_usb.h"
|
||||
#include <stdint.h>
|
||||
#include <endian.h>
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Function Prototypes
|
||||
|
||||
static USB_Status_TypeDef ClearFeature(void);
|
||||
static USB_Status_TypeDef GetConfiguration(void);
|
||||
static USB_Status_TypeDef GetDescriptor(void);
|
||||
static USB_Status_TypeDef GetInterface(void);
|
||||
static USB_Status_TypeDef GetStatus(void);
|
||||
static USB_Status_TypeDef SetAddress(void);
|
||||
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(uint8_t *dat, uint16_t numBytes);
|
||||
void SendEp0Stall(void);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Global Variables
|
||||
|
||||
extern SI_SEGMENT_VARIABLE(myUsbDevice, USBD_Device_TypeDef, MEM_MODEL_SEG);
|
||||
SI_SEGMENT_VARIABLE(txZero[2], uint8_t, SI_SEG_CODE);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Static Global Variables
|
||||
|
||||
static uint16_t pStatus;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Chapter 9 Functions
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Processes Standard Request (Chapter 9 Command)
|
||||
* @return Status of request (type @ref USB_Status_TypeDef)
|
||||
* @note This function takes no parameters, but it uses the setup command
|
||||
* stored in @ref myUsbDevice.setup.
|
||||
******************************************************************************/
|
||||
USB_Status_TypeDef USBDCH9_SetupCmd(void)
|
||||
{
|
||||
USB_Status_TypeDef status = USB_STATUS_OK;
|
||||
|
||||
switch (myUsbDevice.setup.bRequest)
|
||||
{
|
||||
case GET_STATUS:
|
||||
status = GetStatus();
|
||||
break;
|
||||
|
||||
case CLEAR_FEATURE:
|
||||
status = ClearFeature();
|
||||
break;
|
||||
|
||||
case SET_FEATURE:
|
||||
status = SetFeature();
|
||||
break;
|
||||
|
||||
case SET_ADDRESS:
|
||||
status = SetAddress();
|
||||
break;
|
||||
|
||||
case GET_DESCRIPTOR:
|
||||
status = GetDescriptor();
|
||||
break;
|
||||
|
||||
case GET_CONFIGURATION:
|
||||
status = GetConfiguration();
|
||||
break;
|
||||
|
||||
case SET_CONFIGURATION:
|
||||
status = SetConfiguration();
|
||||
break;
|
||||
|
||||
case GET_INTERFACE:
|
||||
status = GetInterface();
|
||||
break;
|
||||
|
||||
case SET_INTERFACE:
|
||||
status = SetInterface();
|
||||
break;
|
||||
|
||||
default:
|
||||
status = USB_STATUS_REQ_ERR;
|
||||
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;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Clears the requested feature
|
||||
* @details Supports CLEAR_FEATURE for Remote Wakeup and Endpoint Halt
|
||||
* @return Status of request (type @ref USB_Status_TypeDef)
|
||||
* @note This function takes no parameters, but it uses the setup command
|
||||
* stored in @ref myUsbDevice.setup.
|
||||
******************************************************************************/
|
||||
static USB_Status_TypeDef ClearFeature(void)
|
||||
{
|
||||
USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
|
||||
|
||||
if (myUsbDevice.setup.wLength == 0)
|
||||
{
|
||||
switch (myUsbDevice.setup.bmRequestType.Recipient)
|
||||
{
|
||||
#if SLAB_USB_REMOTE_WAKEUP_ENABLED
|
||||
case USB_SETUP_RECIPIENT_DEVICE:
|
||||
if ((myUsbDevice.setup.wIndex == 0)
|
||||
&& (myUsbDevice.setup.wValue == USB_FEATURE_DEVICE_REMOTE_WAKEUP)
|
||||
&& (myUsbDevice.state >= USBD_STATE_ADDRESSED))
|
||||
{
|
||||
// Remote wakeup feature clear
|
||||
myUsbDevice.remoteWakeupEnabled = false;
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
break;
|
||||
#endif // SLAB_USB_REMOTE_WAKEUP_ENABLED
|
||||
case USB_SETUP_RECIPIENT_ENDPOINT:
|
||||
if (myUsbDevice.setup.wValue == USB_FEATURE_ENDPOINT_HALT)
|
||||
{
|
||||
// Device does not support halting endpoint 0, but do not return
|
||||
// an error as this is a valid request
|
||||
if (((myUsbDevice.setup.wIndex & ~USB_EP_DIR_IN) == 0)
|
||||
&& (myUsbDevice.state >= USBD_STATE_ADDRESSED))
|
||||
{
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
else if (((myUsbDevice.setup.wIndex & ~USB_SETUP_DIR_D2H) < SLAB_USB_NUM_EPS_USED)
|
||||
&& (myUsbDevice.state == USBD_STATE_CONFIGURED))
|
||||
{
|
||||
retVal = USB_STATUS_OK;
|
||||
USB_SetIndex((myUsbDevice.setup.wIndex & 0xFF) & ~USB_SETUP_DIR_D2H);
|
||||
|
||||
#if (SLAB_USB_EP1IN_USED || SLAB_USB_EP2IN_USED || SLAB_USB_EP3IN_USED)
|
||||
if ((myUsbDevice.setup.wIndex & 0xFF) & USB_EP_DIR_IN)
|
||||
{
|
||||
USB_EpnInEndStallAndClearDataToggle();
|
||||
}
|
||||
#endif
|
||||
#if (SLAB_USB_EP1OUT_USED || SLAB_USB_EP2OUT_USED || SLAB_USB_EP3OUT_USED)
|
||||
if (((myUsbDevice.setup.wIndex & 0xFF) & USB_EP_DIR_IN) == 0)
|
||||
{
|
||||
USB_EpnOutEndStallAndClearDataToggle();
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (myUsbDevice.setup.wIndex & 0xFF)
|
||||
{
|
||||
#if SLAB_USB_EP1OUT_USED
|
||||
case (USB_EP_DIR_OUT | 1):
|
||||
if (myUsbDevice.ep1out.state != D_EP_RECEIVING)
|
||||
{
|
||||
myUsbDevice.ep1out.state = D_EP_IDLE;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP2OUT_USED
|
||||
case (USB_EP_DIR_OUT | 2):
|
||||
if (myUsbDevice.ep2out.state != D_EP_RECEIVING)
|
||||
{
|
||||
myUsbDevice.ep2out.state = D_EP_IDLE;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP3OUT_USED
|
||||
case (USB_EP_DIR_OUT | 3):
|
||||
if (myUsbDevice.ep3out.state != D_EP_RECEIVING)
|
||||
{
|
||||
myUsbDevice.ep3out.state = D_EP_IDLE;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP1IN_USED
|
||||
case (USB_EP_DIR_IN | 1):
|
||||
if (myUsbDevice.ep1in.state != D_EP_TRANSMITTING)
|
||||
{
|
||||
myUsbDevice.ep1in.state = D_EP_IDLE;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP2IN_USED
|
||||
case (USB_EP_DIR_IN | 2):
|
||||
if (myUsbDevice.ep2in.state != D_EP_TRANSMITTING)
|
||||
{
|
||||
myUsbDevice.ep2in.state = D_EP_IDLE;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP3IN_USED
|
||||
case (USB_EP_DIR_IN | 3):
|
||||
if (myUsbDevice.ep3in.state != D_EP_TRANSMITTING)
|
||||
{
|
||||
myUsbDevice.ep3in.state = D_EP_IDLE;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Gets the current configuration value
|
||||
* @details Zero means the device is not configured, a non-zero value
|
||||
* is the configuration value of the configured device.
|
||||
* @return Status of request (type @ref USB_Status_TypeDef)
|
||||
* @note This function takes no parameters, but it uses the setup command
|
||||
* stored in @ref myUsbDevice.setup.
|
||||
******************************************************************************/
|
||||
static USB_Status_TypeDef GetConfiguration(void)
|
||||
{
|
||||
USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
|
||||
|
||||
if ((myUsbDevice.setup.wIndex == 0)
|
||||
&& (myUsbDevice.setup.wValue == 0)
|
||||
&& (myUsbDevice.setup.wLength == 1)
|
||||
&& (myUsbDevice.setup.bmRequestType.Direction == USB_SETUP_DIR_IN)
|
||||
&& (myUsbDevice.setup.bmRequestType.Recipient == USB_SETUP_RECIPIENT_DEVICE))
|
||||
{
|
||||
if (myUsbDevice.state == USBD_STATE_ADDRESSED)
|
||||
{
|
||||
EP0_Write(txZero, 1);
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
else if (myUsbDevice.state == USBD_STATE_CONFIGURED)
|
||||
{
|
||||
EP0_Write(&myUsbDevice.configurationValue, 1);
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Sends the requested USB Descriptor
|
||||
* @details Supports single or multiple languages (configured by
|
||||
* @ref SLAB_USB_NUM_LANGUAGES).
|
||||
* @return Status of request (type @ref USB_Status_TypeDef)
|
||||
* @note This function takes no parameters, but it uses the setup command
|
||||
* stored in @ref myUsbDevice.setup.
|
||||
******************************************************************************/
|
||||
static USB_Status_TypeDef GetDescriptor(void)
|
||||
{
|
||||
#if (SLAB_USB_NUM_LANGUAGES > 1)
|
||||
bool langSupported;
|
||||
uint8_t lang;
|
||||
#endif
|
||||
|
||||
uint8_t index;
|
||||
uint16_t length = 0;
|
||||
uint8_t *dat;
|
||||
USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
|
||||
|
||||
if (*((uint8_t *)&myUsbDevice.setup.bmRequestType) ==
|
||||
(USB_SETUP_DIR_D2H | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE))
|
||||
{
|
||||
index = myUsbDevice.setup.wValue & 0xFF;
|
||||
|
||||
switch (myUsbDevice.setup.wValue >> 8)
|
||||
{
|
||||
case USB_DEVICE_DESCRIPTOR:
|
||||
if (index != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
dat = (uint8_t *)myUsbDevice.deviceDescriptor;
|
||||
length = myUsbDevice.deviceDescriptor->bLength;
|
||||
break;
|
||||
|
||||
case USB_CONFIG_DESCRIPTOR:
|
||||
if (index != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
dat = (uint8_t *)myUsbDevice.configDescriptor;
|
||||
length = le16toh(myUsbDevice.configDescriptor->wTotalLength);
|
||||
break;
|
||||
|
||||
case USB_STRING_DESCRIPTOR:
|
||||
#if (SLAB_USB_NUM_LANGUAGES == 1)
|
||||
|
||||
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.
|
||||
if (index == 0)
|
||||
{
|
||||
length = 4;
|
||||
myUsbDevice.ep0String.encoding.type = USB_STRING_DESCRIPTOR_UTF16LE;
|
||||
}
|
||||
// Otherwise, verify the language is correct (either the value set as
|
||||
// SLAB_USB_LANGUAGE in usbconfig.h, or 0).
|
||||
else if ((myUsbDevice.setup.wIndex == 0) || (myUsbDevice.setup.wIndex == SLAB_USB_LANGUAGE))
|
||||
{
|
||||
// Verify the index is valid
|
||||
if (index < myUsbDevice.numberOfStrings)
|
||||
{
|
||||
length = *(dat + USB_STRING_DESCRIPTOR_LENGTH);
|
||||
myUsbDevice.ep0String.encoding.type = *(dat + USB_STRING_DESCRIPTOR_ENCODING);
|
||||
dat += USB_STRING_DESCRIPTOR_LENGTH;
|
||||
myUsbDevice.ep0String.encoding.init = true;
|
||||
}
|
||||
}
|
||||
#elif (SLAB_USB_NUM_LANGUAGES > 1)
|
||||
|
||||
langSupported = false;
|
||||
|
||||
// Index 0 is the language.
|
||||
if (index == 0)
|
||||
{
|
||||
dat = ((uint8_t *)myUsbDevice.stringDescriptors->languageArray[0][index]);
|
||||
length = *((uint8_t *)dat);
|
||||
myUsbDevice.ep0String.encoding.type = USB_STRING_DESCRIPTOR_UTF16LE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, verify the language is one of the supported languages or 0.
|
||||
for (lang = 0; lang < SLAB_USB_NUM_LANGUAGES; lang++)
|
||||
{
|
||||
if ((myUsbDevice.stringDescriptors->languageIDs[lang] == myUsbDevice.setup.wIndex)
|
||||
|| (myUsbDevice.stringDescriptors->languageIDs[lang] == 0))
|
||||
{
|
||||
langSupported = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((langSupported == true) && (index < myUsbDevice.numberOfStrings))
|
||||
{
|
||||
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;
|
||||
|
||||
if (myUsbDevice.ep0String.encoding.type == USB_STRING_DESCRIPTOR_UTF16LE_PACKED)
|
||||
{
|
||||
myUsbDevice.ep0String.encoding.init = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
myUsbDevice.ep0String.encoding.init = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ( SLAB_USB_NUM_LANGUAGES == 1 )
|
||||
}
|
||||
|
||||
// If there is a descriptor to send, get the proper length, then call
|
||||
// EP0_Write() to send.
|
||||
if (length)
|
||||
{
|
||||
if (length > myUsbDevice.setup.wLength)
|
||||
{
|
||||
length = myUsbDevice.setup.wLength;
|
||||
}
|
||||
|
||||
EP0_Write(dat, length);
|
||||
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Sends the current interface alternate setting
|
||||
* @details Sends 0x0000 if alternate interfaces are not supported.
|
||||
* @return Status of request (type @ref USB_Status_TypeDef)
|
||||
* @note This function takes no parameters, but it uses the setup command
|
||||
* stored in @ref myUsbDevice.setup.
|
||||
******************************************************************************/
|
||||
static USB_Status_TypeDef GetInterface(void)
|
||||
{
|
||||
uint16_t interface = myUsbDevice.setup.wIndex;
|
||||
USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
|
||||
|
||||
if ((interface < SLAB_USB_NUM_INTERFACES)
|
||||
&& (myUsbDevice.setup.wLength == 1)
|
||||
&& (myUsbDevice.setup.wValue == 0)
|
||||
&& (*((uint8_t *)&myUsbDevice.setup.bmRequestType) ==
|
||||
(USB_SETUP_DIR_D2H | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE)))
|
||||
{
|
||||
if (myUsbDevice.state == USBD_STATE_CONFIGURED)
|
||||
{
|
||||
#if (SLAB_USB_SUPPORT_ALT_INTERFACES)
|
||||
// Return the alternate setting for the specified interface
|
||||
EP0_Write(&myUsbDevice.interfaceAltSetting[interface], 1);
|
||||
#else
|
||||
// Alternate interfaces are not supported, so return 0x0000.
|
||||
EP0_Write(&txZero, 1);
|
||||
#endif
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Sends the requested Remote Wakeup, Self-Powered, or
|
||||
* Endpoint Status
|
||||
* @return Status of request (type @ref USB_Status_TypeDef)
|
||||
* @note This function takes no parameters, but it uses the setup command
|
||||
* stored in @ref myUsbDevice.setup.
|
||||
******************************************************************************/
|
||||
static USB_Status_TypeDef GetStatus(void)
|
||||
{
|
||||
USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
|
||||
|
||||
if ((myUsbDevice.setup.wLength == 2)
|
||||
&& (myUsbDevice.setup.wValue == 0)
|
||||
&& (myUsbDevice.setup.bmRequestType.Direction == USB_SETUP_DIR_IN)
|
||||
&& (myUsbDevice.state >= USBD_STATE_ADDRESSED))
|
||||
{
|
||||
pStatus = htole16(0); // Default return value is 0x0000
|
||||
|
||||
switch (myUsbDevice.setup.bmRequestType.Recipient)
|
||||
{
|
||||
case USB_SETUP_RECIPIENT_DEVICE:
|
||||
if (myUsbDevice.setup.wIndex == 0)
|
||||
{
|
||||
#if SLAB_USB_REMOTE_WAKEUP_ENABLED
|
||||
// Remote wakeup feature status
|
||||
if (myUsbDevice.remoteWakeupEnabled)
|
||||
{
|
||||
pStatus |= htole16(REMOTE_WAKEUP_ENABLED);
|
||||
}
|
||||
#endif // SLAB_USB_REMOTE_WAKEUP_ENABLED
|
||||
|
||||
#if SLAB_USB_IS_SELF_POWERED_CB
|
||||
// Current self/bus power status
|
||||
if (USBD_IsSelfPoweredCb())
|
||||
{
|
||||
pStatus |= htole16(DEVICE_IS_SELFPOWERED);
|
||||
}
|
||||
#elif (SLAB_USB_BUS_POWERED == 0)
|
||||
pStatus |= htole16(DEVICE_IS_SELFPOWERED);
|
||||
#endif // SLAB_USB_IS_SELF_POWERED_CB
|
||||
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_SETUP_RECIPIENT_INTERFACE:
|
||||
if (myUsbDevice.setup.wIndex < SLAB_USB_NUM_INTERFACES)
|
||||
{
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case USB_SETUP_RECIPIENT_ENDPOINT:
|
||||
// Device does not support halting endpoint 0, but do not give
|
||||
// an error as this is a valid request
|
||||
if (((myUsbDevice.setup.wIndex & ~USB_EP_DIR_IN) == 0)
|
||||
&& (myUsbDevice.state == USBD_STATE_ADDRESSED))
|
||||
{
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
else if (myUsbDevice.state == USBD_STATE_CONFIGURED)
|
||||
{
|
||||
switch (myUsbDevice.setup.wIndex & 0xFF)
|
||||
{
|
||||
#if SLAB_USB_EP1OUT_USED
|
||||
case (USB_EP_DIR_OUT | 1):
|
||||
if (myUsbDevice.ep1out.state == D_EP_HALT)
|
||||
{
|
||||
pStatus = htole16(1);
|
||||
}
|
||||
retVal = USB_STATUS_OK;
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP2OUT_USED
|
||||
case (USB_EP_DIR_OUT | 2):
|
||||
if (myUsbDevice.ep2out.state == D_EP_HALT)
|
||||
{
|
||||
pStatus = htole16(1);
|
||||
}
|
||||
retVal = USB_STATUS_OK;
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP3OUT_USED
|
||||
case (USB_EP_DIR_OUT | 3):
|
||||
if (myUsbDevice.ep3out.state == D_EP_HALT)
|
||||
{
|
||||
pStatus = htole16(1);
|
||||
}
|
||||
retVal = USB_STATUS_OK;
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP1IN_USED
|
||||
case (USB_EP_DIR_IN | 1):
|
||||
if (myUsbDevice.ep1in.state == D_EP_HALT)
|
||||
{
|
||||
pStatus = htole16(1);
|
||||
}
|
||||
retVal = USB_STATUS_OK;
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP2IN_USED
|
||||
case (USB_EP_DIR_IN | 2):
|
||||
if (myUsbDevice.ep2in.state == D_EP_HALT)
|
||||
{
|
||||
pStatus = htole16(1);
|
||||
}
|
||||
retVal = USB_STATUS_OK;
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP3IN_USED
|
||||
case (USB_EP_DIR_IN | 3):
|
||||
if (myUsbDevice.ep3in.state == D_EP_HALT)
|
||||
{
|
||||
pStatus = htole16(1);
|
||||
}
|
||||
retVal = USB_STATUS_OK;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// If the command was valid, send the requested status.
|
||||
if (retVal == USB_STATUS_OK)
|
||||
{
|
||||
EP0_Write((uint8_t *)&pStatus, 2);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Sets the Address
|
||||
* @return Status of request (type @ref USB_Status_TypeDef)
|
||||
* @note This function takes no parameters, but it uses the setup command
|
||||
* stored in @ref myUsbDevice.setup.
|
||||
******************************************************************************/
|
||||
static USB_Status_TypeDef SetAddress(void)
|
||||
{
|
||||
USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
|
||||
|
||||
if ((myUsbDevice.setup.wValue < 128)
|
||||
&& (myUsbDevice.setup.wLength == 0)
|
||||
&& (myUsbDevice.setup.bmRequestType.Recipient == USB_SETUP_RECIPIENT_DEVICE)
|
||||
&& (myUsbDevice.setup.wIndex == 0))
|
||||
{
|
||||
// If the device is in the Default state and the address is non-zero, put
|
||||
// the device in the Addressed state.
|
||||
if (myUsbDevice.state == USBD_STATE_DEFAULT)
|
||||
{
|
||||
if (myUsbDevice.setup.wValue != 0)
|
||||
{
|
||||
USBD_SetUsbState(USBD_STATE_ADDRESSED);
|
||||
}
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
// If the device is already addressed and the address is zero, put the
|
||||
// device in the Default state.
|
||||
else if (myUsbDevice.state == USBD_STATE_ADDRESSED)
|
||||
{
|
||||
if (myUsbDevice.setup.wValue == 0)
|
||||
{
|
||||
USBD_SetUsbState(USBD_STATE_DEFAULT);
|
||||
}
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
|
||||
// Set the new address if the request was valid.
|
||||
if (retVal == USB_STATUS_OK)
|
||||
{
|
||||
USB_SetAddress(myUsbDevice.setup.wValue);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Sets the Configuration
|
||||
* @return Status of request (type @ref USB_Status_TypeDef)
|
||||
* @note This function takes no parameters, but it uses the setup command
|
||||
* stored in @ref myUsbDevice.setup.
|
||||
******************************************************************************/
|
||||
static USB_Status_TypeDef SetConfiguration(void)
|
||||
{
|
||||
USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
|
||||
|
||||
if (((myUsbDevice.setup.wValue >> 8) == 0)
|
||||
&& (myUsbDevice.setup.bmRequestType.Recipient == USB_SETUP_RECIPIENT_DEVICE)
|
||||
&& (myUsbDevice.setup.wLength == 0)
|
||||
&& (myUsbDevice.setup.wIndex == 0))
|
||||
{
|
||||
// If the device is in the Addressed state and a valid Configuration value
|
||||
// was sent, enter the Configured state.
|
||||
if (myUsbDevice.state == USBD_STATE_ADDRESSED)
|
||||
{
|
||||
if ((myUsbDevice.setup.wValue == 0)
|
||||
|| (myUsbDevice.setup.wValue == myUsbDevice.configDescriptor->bConfigurationValue))
|
||||
{
|
||||
myUsbDevice.configurationValue = myUsbDevice.setup.wValue;
|
||||
if (myUsbDevice.setup.wValue == myUsbDevice.configDescriptor->bConfigurationValue)
|
||||
{
|
||||
USBD_ActivateAllEps(true);
|
||||
USBD_SetUsbState(USBD_STATE_CONFIGURED);
|
||||
}
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
}
|
||||
// If the device is in the Configured state and Configuration zero is sent,
|
||||
// abort all transfer and enter the Addressed state.
|
||||
else if (myUsbDevice.state == USBD_STATE_CONFIGURED)
|
||||
{
|
||||
if ((myUsbDevice.setup.wValue == 0)
|
||||
|| (myUsbDevice.setup.wValue == myUsbDevice.configDescriptor->bConfigurationValue))
|
||||
{
|
||||
myUsbDevice.configurationValue = myUsbDevice.setup.wValue;
|
||||
if (myUsbDevice.setup.wValue == 0)
|
||||
{
|
||||
USBD_SetUsbState(USBD_STATE_ADDRESSED);
|
||||
USBD_AbortAllTransfers();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reenable device endpoints, will reset data toggles
|
||||
USBD_ActivateAllEps(false);
|
||||
}
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Sets the Remote Wakeup or Endpoint Halt Feature
|
||||
* @return Status of request (type @ref USB_Status_TypeDef)
|
||||
* @note This function takes no parameters, but it uses the setup command
|
||||
* stored in @ref myUsbDevice.setup.
|
||||
******************************************************************************/
|
||||
static USB_Status_TypeDef SetFeature(void)
|
||||
{
|
||||
USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
|
||||
|
||||
if (myUsbDevice.setup.wLength == 0)
|
||||
{
|
||||
switch (myUsbDevice.setup.bmRequestType.Recipient)
|
||||
{
|
||||
#if SLAB_USB_REMOTE_WAKEUP_ENABLED
|
||||
case USB_SETUP_RECIPIENT_DEVICE:
|
||||
if ((myUsbDevice.setup.wIndex == 0) // ITF no. 0
|
||||
&& (myUsbDevice.setup.wValue == USB_FEATURE_DEVICE_REMOTE_WAKEUP)
|
||||
&& (myUsbDevice.state == USBD_STATE_CONFIGURED))
|
||||
{
|
||||
myUsbDevice.remoteWakeupEnabled = true;
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
break;
|
||||
#endif // SLAB_USB_REMOTE_WAKEUP_ENABLED
|
||||
case USB_SETUP_RECIPIENT_ENDPOINT:
|
||||
// Device does not support halting endpoint 0, but do not return
|
||||
// an error as this is a valid request
|
||||
if (((myUsbDevice.setup.wIndex & ~USB_EP_DIR_IN) == 0)
|
||||
&& (myUsbDevice.state >= USBD_STATE_ADDRESSED))
|
||||
{
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
else if ((((myUsbDevice.setup.wIndex) & ~USB_SETUP_DIR_D2H) < SLAB_USB_NUM_EPS_USED)
|
||||
&& (myUsbDevice.setup.wValue == USB_FEATURE_ENDPOINT_HALT)
|
||||
&& (myUsbDevice.state == USBD_STATE_CONFIGURED))
|
||||
{
|
||||
retVal = USB_STATUS_OK;
|
||||
USB_SetIndex((myUsbDevice.setup.wIndex & 0xFF) & ~USB_SETUP_DIR_D2H);
|
||||
|
||||
// Enable Stalls on the specified endpoint.
|
||||
#if (SLAB_USB_EP1IN_USED || SLAB_USB_EP2IN_USED || SLAB_USB_EP3IN_USED)
|
||||
if ((myUsbDevice.setup.wIndex & 0xFF) & USB_EP_DIR_IN)
|
||||
{
|
||||
USB_EpnInStall();
|
||||
}
|
||||
#endif
|
||||
#if (SLAB_USB_EP1OUT_USED || SLAB_USB_EP2OUT_USED || SLAB_USB_EP3OUT_USED)
|
||||
if (((myUsbDevice.setup.wIndex & 0xFF) & USB_EP_DIR_IN) == 0)
|
||||
{
|
||||
USB_EpnOutStall();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Put the specified endpoint in the Halted state.
|
||||
switch (myUsbDevice.setup.wIndex & 0xFF)
|
||||
{
|
||||
#if SLAB_USB_EP1OUT_USED
|
||||
case (USB_EP_DIR_OUT | 1):
|
||||
myUsbDevice.ep1out.state = D_EP_HALT;
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP2OUT_USED
|
||||
case (USB_EP_DIR_OUT | 2):
|
||||
myUsbDevice.ep2out.state = D_EP_HALT;
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP3OUT_USED
|
||||
case (USB_EP_DIR_OUT | 3):
|
||||
myUsbDevice.ep3out.state = D_EP_HALT;
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP1IN_USED
|
||||
case (USB_EP_DIR_IN | 1):
|
||||
myUsbDevice.ep1in.state = D_EP_HALT;
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP2IN_USED
|
||||
case (USB_EP_DIR_IN | 2):
|
||||
myUsbDevice.ep2in.state = D_EP_HALT;
|
||||
break;
|
||||
#endif
|
||||
#if SLAB_USB_EP3IN_USED
|
||||
case (USB_EP_DIR_IN | 3):
|
||||
myUsbDevice.ep3in.state = D_EP_HALT;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Sets the Interface and Alternate Interface (if supported)
|
||||
* @return Status of request (type @ref USB_Status_TypeDef)
|
||||
* @note This function takes no parameters, but it uses the setup command
|
||||
* stored in @ref myUsbDevice.setup.
|
||||
******************************************************************************/
|
||||
static USB_Status_TypeDef SetInterface(void)
|
||||
{
|
||||
USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
|
||||
uint8_t interface = (uint8_t)myUsbDevice.setup.wIndex;
|
||||
uint8_t altSetting = (uint8_t)myUsbDevice.setup.wValue;
|
||||
|
||||
if ((interface < SLAB_USB_NUM_INTERFACES)
|
||||
&& (myUsbDevice.state == USBD_STATE_CONFIGURED)
|
||||
&& (myUsbDevice.setup.wLength == 0)
|
||||
#if (SLAB_USB_SUPPORT_ALT_INTERFACES == 0)
|
||||
&& (altSetting == 0)
|
||||
#endif
|
||||
&& (myUsbDevice.setup.bmRequestType.Recipient == USB_SETUP_RECIPIENT_INTERFACE))
|
||||
{
|
||||
#if (SLAB_USB_SUPPORT_ALT_INTERFACES)
|
||||
if (USBD_SetInterfaceCb(interface, altSetting) == USB_STATUS_OK)
|
||||
{
|
||||
myUsbDevice.interfaceAltSetting[interface] = altSetting;
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
#else
|
||||
#if (SLAB_USB_NUM_INTERFACES == 1)
|
||||
// Reset data toggles on EP's
|
||||
USBD_ActivateAllEps(false);
|
||||
#endif // ( SLAB_USB_NUM_INTERFACES == 1 )
|
||||
retVal = USB_STATUS_OK;
|
||||
#endif // ( SLAB_USB_SUPPORT_ALT_INTERFACES )
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Utility Functions
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Enables all endpoints for data transfers
|
||||
* @return Status of request (type @ref USB_Status_TypeDef)
|
||||
* @note This function takes no parameters, but it uses the setup command
|
||||
* stored in @ref myUsbDevice.setup.
|
||||
******************************************************************************/
|
||||
static void USBD_ActivateAllEps(bool forceIdle)
|
||||
{
|
||||
if (forceIdle == true)
|
||||
{
|
||||
#if SLAB_USB_EP1IN_USED
|
||||
myUsbDevice.ep1in.state = D_EP_IDLE;
|
||||
#endif
|
||||
#if SLAB_USB_EP2IN_USED
|
||||
myUsbDevice.ep2in.state = D_EP_IDLE;
|
||||
#endif
|
||||
#if SLAB_USB_EP3IN_USED
|
||||
myUsbDevice.ep3in.state = D_EP_IDLE;
|
||||
#endif
|
||||
#if SLAB_USB_EP1OUT_USED
|
||||
myUsbDevice.ep1out.state = D_EP_IDLE;
|
||||
#endif
|
||||
#if SLAB_USB_EP2OUT_USED
|
||||
myUsbDevice.ep2out.state = D_EP_IDLE;
|
||||
#endif
|
||||
#if SLAB_USB_EP3OUT_USED
|
||||
myUsbDevice.ep3out.state = D_EP_IDLE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SLAB_USB_EP1IN_USED
|
||||
USB_ActivateEp(1, // ep
|
||||
SLAB_USB_EP1IN_MAX_PACKET_SIZE, // packetSize
|
||||
1, // inDir
|
||||
SLAB_USB_EP1OUT_USED, // splitMode
|
||||
0); // isoMod
|
||||
#endif // SLAB_USB_EP1IN_USED
|
||||
#if SLAB_USB_EP2IN_USED
|
||||
USB_ActivateEp(2, // ep
|
||||
SLAB_USB_EP2IN_MAX_PACKET_SIZE, // packetSize
|
||||
1, // inDir
|
||||
SLAB_USB_EP2OUT_USED, // splitMode
|
||||
0); // isoMod
|
||||
#endif // SLAB_USB_EP2IN_USED
|
||||
#if SLAB_USB_EP3IN_USED
|
||||
USB_ActivateEp(3, // ep
|
||||
SLAB_USB_EP3IN_MAX_PACKET_SIZE, // packetSize
|
||||
1, // inDir
|
||||
SLAB_USB_EP3OUT_USED, // splitMode
|
||||
(SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_ISOC)); // isoMod
|
||||
#endif // SLAB_USB_EP3IN_USED
|
||||
#if SLAB_USB_EP1OUT_USED
|
||||
USB_ActivateEp(1, // ep
|
||||
SLAB_USB_EP1OUT_MAX_PACKET_SIZE, // packetSize
|
||||
0, // inDir
|
||||
SLAB_USB_EP1IN_USED, // splitMode
|
||||
0); // isoMod
|
||||
#endif // SLAB_USB_EP1OUT_USED
|
||||
#if SLAB_USB_EP2OUT_USED
|
||||
USB_ActivateEp(2, // ep
|
||||
SLAB_USB_EP2OUT_MAX_PACKET_SIZE, // packetSize
|
||||
0, // inDir
|
||||
SLAB_USB_EP2IN_USED, // splitMode
|
||||
0); // isoMod
|
||||
#endif // SLAB_USB_EP2OUT_USED
|
||||
#if SLAB_USB_EP3OUT_USED
|
||||
USB_ActivateEp(3, // ep
|
||||
SLAB_USB_EP3OUT_MAX_PACKET_SIZE, // packetSize
|
||||
0, // inDir
|
||||
SLAB_USB_EP3IN_USED, // splitMode
|
||||
(SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC)); // isoMod
|
||||
#endif // SLAB_USB_EP1OUT_USED
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Sets up an Endpoint 0 Write
|
||||
* @param dat
|
||||
* Data to transmit on Endpoint 0
|
||||
* @param numBytes
|
||||
* Number of bytes to transmit on Endpoint 0
|
||||
******************************************************************************/
|
||||
static void EP0_Write(uint8_t *dat, uint16_t numBytes)
|
||||
{
|
||||
if (myUsbDevice.ep0.state == D_EP_IDLE)
|
||||
{
|
||||
myUsbDevice.ep0.buf = (uint8_t *)dat;
|
||||
myUsbDevice.ep0.remaining = numBytes;
|
||||
myUsbDevice.ep0.state = D_EP_TRANSMITTING;
|
||||
myUsbDevice.ep0.misc.c = 0;
|
||||
}
|
||||
}
|
@ -1,896 +0,0 @@
|
||||
/**************************************************************************//**
|
||||
* Copyright (c) 2015 by Silicon Laboratories Inc. All rights reserved.
|
||||
*
|
||||
* http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt
|
||||
*****************************************************************************/
|
||||
|
||||
#include "si_toolchain.h"
|
||||
#include "efm8_usb.h"
|
||||
#include <stdint.h>
|
||||
#include <endian.h>
|
||||
|
||||
extern SI_SEGMENT_VARIABLE(myUsbDevice, USBD_Device_TypeDef, MEM_MODEL_SEG);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Function Prototypes
|
||||
|
||||
// -------------------------------
|
||||
// Memory-specific FIFO access functions
|
||||
#ifdef SI_GPTR
|
||||
|
||||
static void USB_ReadFIFO_Idata(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_IDATA), uint8_t fifoNum);
|
||||
static void USB_WriteFIFO_Idata(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_IDATA));
|
||||
|
||||
static void USB_ReadFIFO_Xdata(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_XDATA), uint8_t fifoNum);
|
||||
static void USB_WriteFIFO_Xdata(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_XDATA));
|
||||
|
||||
#if SI_GPTR_MTYPE_PDATA != SI_GPTR_MTYPE_XDATA
|
||||
static void USB_ReadFIFO_Pdata(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_PDATA), uint8_t fifoNum);
|
||||
static void USB_WriteFIFO_Pdata(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_PDATA));
|
||||
#endif
|
||||
|
||||
#if SI_GPTR_MTYPE_DATA != SI_GPTR_MTYPE_IDATA
|
||||
static void USB_ReadFIFO_Data(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_DATA), uint8_t fifoNum);
|
||||
static void USB_WriteFIFO_Data(uint8_t numBytes, uint8_t SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_DATA));
|
||||
#endif
|
||||
|
||||
static void USB_WriteFIFO_Code(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_CODE));
|
||||
|
||||
#else
|
||||
|
||||
// -------------------------------
|
||||
// Generic FIFO access functions
|
||||
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
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Functions
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Reads Isochronous data from the Endpoint FIFO
|
||||
* @param fifoNum
|
||||
* USB Endpoint FIFO to read
|
||||
* @param numBytes
|
||||
* Number of bytes to read from the FIFO
|
||||
* @param dat
|
||||
* Pointer to buffer to hold data read from the FIFO
|
||||
******************************************************************************/
|
||||
#if (SLAB_USB_EP3OUT_USED && (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC) && (SLAB_USB_EP3OUT_MAX_PACKET_SIZE > 255))
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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, uint8_t *dat)
|
||||
{
|
||||
uint8_t numBytesRead;
|
||||
|
||||
// USB_ReadFIFO() accepts a maximum of 255 bytes. If the number of bytes to
|
||||
// send is greated than 255, call USB_ReadFIFO() multiple times.
|
||||
while (numBytes > 0)
|
||||
{
|
||||
numBytesRead = (numBytes > 255) ? 255 : numBytes;
|
||||
USB_ReadFIFO(fifoNum, numBytesRead, dat);
|
||||
numBytes -= numBytesRead;
|
||||
dat += numBytesRead;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define USB_ReadFIFOIso(a, b, c) USB_ReadFIFO(a, b, c)
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Writes Isochronous data to the Endpoint FIFO
|
||||
* @param fifoNum
|
||||
* USB Endpoint FIFO to write
|
||||
* @param numBytes
|
||||
* Number of bytes to write to the FIFO
|
||||
* @param dat
|
||||
* Pointer to buffer hoding data to write to the FIFO
|
||||
******************************************************************************/
|
||||
#if (SLAB_USB_EP3IN_USED && (SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_ISOC) && (SLAB_USB_EP3IN_MAX_PACKET_SIZE > 255))
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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, uint8_t *dat)
|
||||
{
|
||||
uint8_t numBytesWrite;
|
||||
|
||||
// USB_WriteFIFO() accepts a maximum of 255 bytes. If the number of bytes to
|
||||
// send is greated than 255, call USB_WriteFIFO() multiple times.
|
||||
while (numBytes > 0)
|
||||
{
|
||||
numBytesWrite = (numBytes > 255) ? 255 : numBytes;
|
||||
numBytes -= numBytesWrite;
|
||||
USB_WriteFIFO(fifoNum, numBytesWrite, dat, (numBytes == 0));
|
||||
dat += numBytesWrite;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define USB_WriteFIFOIso(a, b, c) USB_WriteFIFO(a, b, c, true)
|
||||
#endif
|
||||
|
||||
#if SLAB_USB_EP1IN_USED
|
||||
/***************************************************************************//**
|
||||
* @brief Handle Endpoint 1 IN transfer interrupt
|
||||
* @note This function takes no parameters, but it uses the EP1IN status
|
||||
* variables stored in @ref myUsbDevice.ep1in.
|
||||
******************************************************************************/
|
||||
void handleUsbIn1Int(void)
|
||||
{
|
||||
uint8_t xferred;
|
||||
bool callback;
|
||||
|
||||
USB_SetIndex(1);
|
||||
|
||||
if (USB_EpnInGetSentStall())
|
||||
{
|
||||
USB_EpnInClearSentStall();
|
||||
}
|
||||
else if (myUsbDevice.ep1in.state == D_EP_TRANSMITTING)
|
||||
{
|
||||
xferred = (myUsbDevice.ep1in.remaining > SLAB_USB_EP1IN_MAX_PACKET_SIZE)
|
||||
? SLAB_USB_EP1IN_MAX_PACKET_SIZE : myUsbDevice.ep1in.remaining;
|
||||
myUsbDevice.ep1in.remaining -= xferred;
|
||||
myUsbDevice.ep1in.buf += xferred;
|
||||
|
||||
callback = myUsbDevice.ep1in.misc.bits.callback;
|
||||
|
||||
// Load more data
|
||||
if (myUsbDevice.ep1in.remaining > 0)
|
||||
{
|
||||
USB_WriteFIFO(1,
|
||||
(myUsbDevice.ep1in.remaining > SLAB_USB_EP1IN_MAX_PACKET_SIZE)
|
||||
? SLAB_USB_EP1IN_MAX_PACKET_SIZE
|
||||
: myUsbDevice.ep1in.remaining,
|
||||
myUsbDevice.ep1in.buf,
|
||||
true);
|
||||
}
|
||||
else
|
||||
{
|
||||
myUsbDevice.ep1in.misc.bits.callback = false;
|
||||
myUsbDevice.ep1in.state = D_EP_IDLE;
|
||||
}
|
||||
|
||||
if (callback == true)
|
||||
{
|
||||
USBD_XferCompleteCb(EP1IN, USB_STATUS_OK, xferred, myUsbDevice.ep1in.remaining);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif // SLAB_USB_EP1IN_USED
|
||||
|
||||
#if SLAB_USB_EP2IN_USED
|
||||
/***************************************************************************//**
|
||||
* @brief Handle Endpoint 2 IN transfer interrupt
|
||||
* @note This function takes no parameters, but it uses the EP2IN status
|
||||
* variables stored in @ref myUsbDevice.ep2in.
|
||||
******************************************************************************/
|
||||
void handleUsbIn2Int(void)
|
||||
{
|
||||
uint8_t xferred;
|
||||
bool callback;
|
||||
|
||||
USB_SetIndex(2);
|
||||
|
||||
if (USB_EpnInGetSentStall())
|
||||
{
|
||||
USB_EpnInClearSentStall();
|
||||
}
|
||||
else if (myUsbDevice.ep2in.state == D_EP_TRANSMITTING)
|
||||
{
|
||||
xferred = (myUsbDevice.ep2in.remaining > SLAB_USB_EP2IN_MAX_PACKET_SIZE)
|
||||
? SLAB_USB_EP2IN_MAX_PACKET_SIZE : myUsbDevice.ep2in.remaining;
|
||||
myUsbDevice.ep2in.remaining -= xferred;
|
||||
myUsbDevice.ep2in.buf += xferred;
|
||||
|
||||
callback = myUsbDevice.ep2in.misc.bits.callback;
|
||||
|
||||
// Load more data
|
||||
if (myUsbDevice.ep2in.remaining > 0)
|
||||
{
|
||||
USB_WriteFIFO(2,
|
||||
(myUsbDevice.ep2in.remaining > SLAB_USB_EP2IN_MAX_PACKET_SIZE)
|
||||
? SLAB_USB_EP2IN_MAX_PACKET_SIZE
|
||||
: myUsbDevice.ep2in.remaining,
|
||||
myUsbDevice.ep2in.buf,
|
||||
true);
|
||||
}
|
||||
else
|
||||
{
|
||||
myUsbDevice.ep2in.misc.bits.callback = false;
|
||||
myUsbDevice.ep2in.state = D_EP_IDLE;
|
||||
}
|
||||
|
||||
if (callback == true)
|
||||
{
|
||||
USBD_XferCompleteCb(EP2IN, USB_STATUS_OK, xferred, myUsbDevice.ep2in.remaining);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif // SLAB_USB_EP2IN_USED
|
||||
|
||||
#if SLAB_USB_EP3IN_USED
|
||||
/***************************************************************************//**
|
||||
* @brief Handle Endpoint 3 IN transfer interrupt
|
||||
* @details Endpoint 3 IN is the only IN endpoint that supports isochronous
|
||||
* transfers.
|
||||
* @note This function takes no parameters, but it uses the EP3IN status
|
||||
* variables stored in @ref myUsbDevice.ep3in.
|
||||
******************************************************************************/
|
||||
void handleUsbIn3Int(void)
|
||||
{
|
||||
#if SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_ISOC
|
||||
uint16_t xferred, nextIdx;
|
||||
#else
|
||||
uint8_t xferred;
|
||||
bool callback;
|
||||
#endif
|
||||
|
||||
USB_SetIndex(3);
|
||||
|
||||
if (USB_EpnInGetSentStall())
|
||||
{
|
||||
USB_EpnInClearSentStall();
|
||||
}
|
||||
else if (myUsbDevice.ep3in.state == D_EP_TRANSMITTING)
|
||||
{
|
||||
#if ((SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_INTR))
|
||||
xferred = (myUsbDevice.ep3in.remaining > SLAB_USB_EP3IN_MAX_PACKET_SIZE)
|
||||
? SLAB_USB_EP3IN_MAX_PACKET_SIZE : myUsbDevice.ep3in.remaining;
|
||||
myUsbDevice.ep3in.remaining -= xferred;
|
||||
myUsbDevice.ep3in.buf += xferred;
|
||||
#endif
|
||||
|
||||
#if ((SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_INTR))
|
||||
|
||||
callback = myUsbDevice.ep3in.misc.bits.callback;
|
||||
|
||||
#elif (SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_ISOC)
|
||||
if (myUsbDevice.ep3in.misc.bits.callback == true)
|
||||
{
|
||||
// In Isochronous mode, the meaning of the USBD_XferCompleteCb parameters changes:
|
||||
// xferred is ignored
|
||||
// remaining is the current index into the circular buffer
|
||||
// the return value is the number of bytes to transmit in the next packet
|
||||
xferred = USBD_XferCompleteCb(EP3IN, USB_STATUS_OK, 0, myUsbDevice.ep3inIsoIdx);
|
||||
if (xferred == 0)
|
||||
{
|
||||
myUsbDevice.ep3in.misc.bits.inPacketPending = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Load more data
|
||||
#if ((SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_INTR))
|
||||
if (myUsbDevice.ep3in.remaining > 0)
|
||||
{
|
||||
USB_WriteFIFO(3,
|
||||
(myUsbDevice.ep3in.remaining > SLAB_USB_EP3IN_MAX_PACKET_SIZE)
|
||||
? SLAB_USB_EP3IN_MAX_PACKET_SIZE
|
||||
: myUsbDevice.ep3in.remaining,
|
||||
myUsbDevice.ep3in.buf,
|
||||
true);
|
||||
}
|
||||
else
|
||||
{
|
||||
myUsbDevice.ep3in.misc.bits.callback = false;
|
||||
myUsbDevice.ep3in.state = D_EP_IDLE;
|
||||
}
|
||||
|
||||
if (callback == true)
|
||||
{
|
||||
USBD_XferCompleteCb(EP3IN, USB_STATUS_OK, xferred, myUsbDevice.ep3in.remaining);
|
||||
}
|
||||
#elif (SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_ISOC)
|
||||
nextIdx = xferred + myUsbDevice.ep3inIsoIdx;
|
||||
myUsbDevice.ep3in.misc.bits.inPacketPending = false;
|
||||
|
||||
// Check if the next index is past the end of the circular buffer.
|
||||
// If so, break the write up into two calls to USB_WriteFIFOIso()
|
||||
if (nextIdx > myUsbDevice.ep3in.remaining)
|
||||
{
|
||||
USB_WriteFIFOIso(3, myUsbDevice.ep3in.remaining - myUsbDevice.ep3inIsoIdx, &myUsbDevice.ep3in.buf[myUsbDevice.ep3inIsoIdx]);
|
||||
myUsbDevice.ep3inIsoIdx = nextIdx - myUsbDevice.ep3in.remaining;
|
||||
USB_WriteFIFOIso(3, myUsbDevice.ep3inIsoIdx, myUsbDevice.ep3in.buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
USB_WriteFIFOIso(3, xferred, &myUsbDevice.ep3in.buf[myUsbDevice.ep3inIsoIdx]);
|
||||
myUsbDevice.ep3inIsoIdx = nextIdx;
|
||||
}
|
||||
#endif // ( ( SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_BULK ) || ( SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_INTR ) )
|
||||
}
|
||||
}
|
||||
#endif // SLAB_USB_EP3IN_USED
|
||||
|
||||
#if SLAB_USB_EP1OUT_USED
|
||||
/***************************************************************************//**
|
||||
* @brief Handle Endpoint 1 OUT transfer interrupt
|
||||
* @note This function takes no parameters, but it uses the EP1OUT status
|
||||
* variables stored in @ref myUsbDevice.ep1out.
|
||||
******************************************************************************/
|
||||
void handleUsbOut1Int(void)
|
||||
{
|
||||
uint8_t count;
|
||||
|
||||
USB_Status_TypeDef status;
|
||||
bool xferComplete = false;
|
||||
|
||||
USB_SetIndex(1);
|
||||
|
||||
if (USB_EpnOutGetSentStall())
|
||||
{
|
||||
USB_EpnOutClearSentStall();
|
||||
}
|
||||
else if (USB_EpnGetOutPacketReady())
|
||||
{
|
||||
count = USB_EpOutGetCount();
|
||||
|
||||
// If USBD_Read() has not been called, return an error
|
||||
if (myUsbDevice.ep1out.state != D_EP_RECEIVING)
|
||||
{
|
||||
myUsbDevice.ep1out.misc.bits.outPacketPending = true;
|
||||
status = USB_STATUS_EP_ERROR;
|
||||
}
|
||||
// Check for overrun of user buffer
|
||||
else if (myUsbDevice.ep1out.remaining < count)
|
||||
{
|
||||
myUsbDevice.ep1out.state = D_EP_IDLE;
|
||||
myUsbDevice.ep1out.misc.bits.outPacketPending = true;
|
||||
status = USB_STATUS_EP_RX_BUFFER_OVERRUN;
|
||||
}
|
||||
else
|
||||
{
|
||||
USB_ReadFIFO(1, count, myUsbDevice.ep1out.buf);
|
||||
|
||||
myUsbDevice.ep1out.misc.bits.outPacketPending = false;
|
||||
myUsbDevice.ep1out.remaining -= count;
|
||||
myUsbDevice.ep1out.buf += count;
|
||||
|
||||
if ((myUsbDevice.ep1out.remaining == 0) || (count != SLAB_USB_EP1OUT_MAX_PACKET_SIZE))
|
||||
{
|
||||
myUsbDevice.ep1out.state = D_EP_IDLE;
|
||||
xferComplete = true;
|
||||
}
|
||||
status = USB_STATUS_OK;
|
||||
USB_EpnClearOutPacketReady();
|
||||
}
|
||||
if (myUsbDevice.ep1out.misc.bits.callback == true)
|
||||
{
|
||||
if (xferComplete == true)
|
||||
{
|
||||
myUsbDevice.ep1out.misc.bits.callback = false;
|
||||
}
|
||||
USBD_XferCompleteCb(EP1OUT, status, count, myUsbDevice.ep1out.remaining);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // EP1OUT_USED
|
||||
|
||||
#if SLAB_USB_EP2OUT_USED
|
||||
/***************************************************************************//**
|
||||
* @brief Handle Endpoint 2 OUT transfer interrupt
|
||||
* @note This function takes no parameters, but it uses the EP2OUT status
|
||||
* variables stored in @ref myUsbDevice.ep2out.
|
||||
******************************************************************************/
|
||||
void handleUsbOut2Int(void)
|
||||
{
|
||||
uint8_t count;
|
||||
|
||||
USB_Status_TypeDef status;
|
||||
bool xferComplete = false;
|
||||
|
||||
USB_SetIndex(2);
|
||||
|
||||
if (USB_EpnOutGetSentStall())
|
||||
{
|
||||
USB_EpnOutClearSentStall();
|
||||
}
|
||||
else if (USB_EpnGetOutPacketReady())
|
||||
{
|
||||
count = USB_EpOutGetCount();
|
||||
|
||||
// If USBD_Read() has not been called, return an error
|
||||
if (myUsbDevice.ep2out.state != D_EP_RECEIVING)
|
||||
{
|
||||
myUsbDevice.ep2out.misc.bits.outPacketPending = true;
|
||||
status = USB_STATUS_EP_ERROR;
|
||||
}
|
||||
// Check for overrun of user buffer
|
||||
else if (myUsbDevice.ep2out.remaining < count)
|
||||
{
|
||||
myUsbDevice.ep2out.state = D_EP_IDLE;
|
||||
myUsbDevice.ep2out.misc.bits.outPacketPending = true;
|
||||
status = USB_STATUS_EP_RX_BUFFER_OVERRUN;
|
||||
}
|
||||
else
|
||||
{
|
||||
USB_ReadFIFO(2, count, myUsbDevice.ep2out.buf);
|
||||
|
||||
myUsbDevice.ep2out.misc.bits.outPacketPending = false;
|
||||
myUsbDevice.ep2out.remaining -= count;
|
||||
myUsbDevice.ep2out.buf += count;
|
||||
|
||||
if ((myUsbDevice.ep2out.remaining == 0) || (count != SLAB_USB_EP2OUT_MAX_PACKET_SIZE))
|
||||
{
|
||||
myUsbDevice.ep2out.state = D_EP_IDLE;
|
||||
xferComplete = true;
|
||||
}
|
||||
|
||||
status = USB_STATUS_OK;
|
||||
USB_EpnClearOutPacketReady();
|
||||
}
|
||||
if (myUsbDevice.ep2out.misc.bits.callback == true)
|
||||
{
|
||||
if (xferComplete == true)
|
||||
{
|
||||
myUsbDevice.ep2out.misc.bits.callback = false;
|
||||
}
|
||||
|
||||
USBD_XferCompleteCb(EP2OUT, status, count, myUsbDevice.ep2out.remaining);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // EP2OUT_USED
|
||||
|
||||
#if SLAB_USB_EP3OUT_USED
|
||||
/***************************************************************************//**
|
||||
* @brief Handle Endpoint 3 OUT transfer interrupt
|
||||
* @details Endpoint 3 OUT is the only OUT endpoint that supports
|
||||
* isochronous transfers.
|
||||
* @note This function takes no parameters, but it uses the EP3OUT status
|
||||
* variables stored in @ref myUsbDevice.ep3out.
|
||||
******************************************************************************/
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
#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)
|
||||
{
|
||||
myUsbDevice.ep3out.state = D_EP_IDLE;
|
||||
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.remaining -= count;
|
||||
myUsbDevice.ep3out.buf += count;
|
||||
|
||||
if ((myUsbDevice.ep3out.remaining == 0) || (count != SLAB_USB_EP3OUT_MAX_PACKET_SIZE))
|
||||
{
|
||||
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();
|
||||
}
|
||||
if (myUsbDevice.ep3out.misc.bits.callback == true)
|
||||
{
|
||||
if (xferComplete == true)
|
||||
{
|
||||
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)
|
||||
|
||||
// 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
|
||||
USBD_XferCompleteCb(EP3OUT, status, count, myUsbDevice.ep3outIsoIdx);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // EP3OUT_USED
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Reads data from the USB FIFO
|
||||
* @param fifoNum
|
||||
* USB Endpoint FIFO to read
|
||||
* @param numBytes
|
||||
* Number of bytes to read from the FIFO
|
||||
* @param dat
|
||||
* Pointer to buffer to hold data read from the FIFO
|
||||
******************************************************************************/
|
||||
void USB_ReadFIFO(uint8_t fifoNum, uint8_t numBytes, uint8_t *dat)
|
||||
{
|
||||
if (numBytes > 0)
|
||||
{
|
||||
USB_EnableReadFIFO(fifoNum);
|
||||
|
||||
// Convert generic pointer to memory-specific pointer and call the
|
||||
// the corresponding memory-specific function, if possible.
|
||||
// The memory-specific functions are much faster than the generic functions.
|
||||
#ifdef SI_GPTR
|
||||
|
||||
switch (((SI_GEN_PTR_t *)&dat)->gptr.memtype)
|
||||
{
|
||||
case SI_GPTR_MTYPE_IDATA:
|
||||
USB_ReadFIFO_Idata(numBytes, dat, fifoNum);
|
||||
break;
|
||||
|
||||
// For some compilers, IDATA and DATA are treated the same.
|
||||
// Only call the USB_ReadFIFO_Data() if the compiler differentiates
|
||||
// between DATA and IDATA.
|
||||
#if (SI_GPTR_MTYPE_DATA != SI_GPTR_MTYPE_IDATA)
|
||||
case SI_GPTR_MTYPE_DATA:
|
||||
USB_ReadFIFO_Data(numBytes, dat, fifoNum);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case SI_GPTR_MTYPE_XDATA:
|
||||
USB_ReadFIFO_Xdata(numBytes, dat, fifoNum);
|
||||
break;
|
||||
|
||||
// For some compilers, XDATA and PDATA are treated the same.
|
||||
// Only call the USB_ReadFIFO_Pdata() if the compiler differentiates
|
||||
// between XDATA and PDATA.
|
||||
#if (SI_GPTR_MTYPE_PDATA != SI_GPTR_MTYPE_XDATA)
|
||||
case SI_GPTR_MTYPE_PDATA:
|
||||
USB_ReadFIFO_Pdata(numBytes, dat, fifoNum);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#else
|
||||
USB_ReadFIFO_Generic(numBytes, dat, fifoNum);
|
||||
#endif // #ifdef SI_GPTR
|
||||
|
||||
USB_DisableReadFIFO(fifoNum);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Writes data to the USB FIFO
|
||||
* @param fifoNum
|
||||
* USB Endpoint FIFO to write
|
||||
* @param numBytes
|
||||
* Number of bytes to write to the FIFO
|
||||
* @param dat
|
||||
* Pointer to buffer hoding data to write to the FIFO
|
||||
* @param txPacket
|
||||
* If TRUE, the packet will be sent immediately after loading the
|
||||
* FIFO
|
||||
* 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, uint8_t *dat, bool txPacket)
|
||||
{
|
||||
USB_EnableWriteFIFO(fifoNum);
|
||||
|
||||
// Convert generic pointer to memory-specific pointer and call the
|
||||
// the corresponding memory-specific function, if possible.
|
||||
// The memory-specific functions are much faster than the generic functions.
|
||||
#ifdef SI_GPTR
|
||||
|
||||
switch (((SI_GEN_PTR_t *)&dat)->gptr.memtype)
|
||||
{
|
||||
case SI_GPTR_MTYPE_IDATA:
|
||||
USB_WriteFIFO_Idata(numBytes, dat);
|
||||
break;
|
||||
|
||||
// For some compilers, IDATA and DATA are treated the same.
|
||||
// Only call the USB_WriteFIFO_Data() if the compiler differentiates between
|
||||
// DATA and IDATA.
|
||||
#if (SI_GPTR_MTYPE_DATA != SI_GPTR_MTYPE_IDATA)
|
||||
case SI_GPTR_MTYPE_DATA:
|
||||
USB_WriteFIFO_Data(numBytes, dat);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case SI_GPTR_MTYPE_XDATA:
|
||||
USB_WriteFIFO_Xdata(numBytes, dat);
|
||||
break;
|
||||
|
||||
// For some compilers, XDATA and PDATA are treated the same.
|
||||
// Only call the USB_WriteFIFO_Pdata() if the compiler differentiates
|
||||
// between XDATA and PDATA.
|
||||
#if (SI_GPTR_MTYPE_PDATA != SI_GPTR_MTYPE_XDATA)
|
||||
case SI_GPTR_MTYPE_PDATA:
|
||||
USB_WriteFIFO_Pdata(numBytes, dat);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case SI_GPTR_MTYPE_CODE:
|
||||
USB_WriteFIFO_Code(numBytes, dat);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#else
|
||||
USB_WriteFIFO_Generic(numBytes, dat);
|
||||
#endif // #ifdef SI_GPTR
|
||||
|
||||
USB_DisableWriteFIFO(fifoNum);
|
||||
|
||||
if ((txPacket == true) && (fifoNum > 0))
|
||||
{
|
||||
USB_SetIndex(fifoNum);
|
||||
USB_EpnSetInPacketReady();
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Memory-Specific FIFO Access Functions
|
||||
//
|
||||
// Memory-specific functions are much faster (more than 2x) than generic
|
||||
// generic functions, so we will use memory-specific functions if possible.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#ifdef SI_GPTR
|
||||
/***************************************************************************//**
|
||||
* @brief Reads data from the USB FIFO to a buffer in IRAM
|
||||
* @param numBytes
|
||||
* Number of bytes to read from the FIFO
|
||||
* @param dat
|
||||
* Pointer to IDATA buffer to hold data read from the FIFO
|
||||
* @param fifoNum
|
||||
* USB FIFO to read
|
||||
******************************************************************************/
|
||||
static void USB_ReadFIFO_Idata(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_IDATA), uint8_t fifoNum)
|
||||
{
|
||||
while (--numBytes)
|
||||
{
|
||||
USB_GetFIFOByte(dat);
|
||||
dat++;
|
||||
}
|
||||
USB_GetLastFIFOByte(dat, fifoNum);
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Writes data held in IRAM to the USB FIFO
|
||||
* @details The FIFO to write must be set before calling the function with
|
||||
* @ref USB_EnableWriteFIFO().
|
||||
* @param numBytes
|
||||
* Number of bytes to write to the FIFO
|
||||
* @param dat
|
||||
* Pointer to IDATA buffer holding data to write to the FIFO
|
||||
******************************************************************************/
|
||||
static void USB_WriteFIFO_Idata(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_IDATA))
|
||||
{
|
||||
while (numBytes--)
|
||||
{
|
||||
USB_SetFIFOByte(*dat);
|
||||
dat++;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Reads data from the USB FIFO to a buffer in XRAM
|
||||
* @param numBytes
|
||||
* Number of bytes to read from the FIFO
|
||||
* @param dat
|
||||
* Pointer to XDATA buffer to hold data read from the FIFO
|
||||
* @param fifoNum
|
||||
* USB FIFO to read
|
||||
******************************************************************************/
|
||||
static void USB_ReadFIFO_Xdata(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_XDATA), uint8_t fifoNum)
|
||||
{
|
||||
while (--numBytes)
|
||||
{
|
||||
USB_GetFIFOByte(dat);
|
||||
dat++;
|
||||
}
|
||||
USB_GetLastFIFOByte(dat, fifoNum);
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Writes data held in XRAM to the USB FIFO
|
||||
* @details The FIFO to write must be set before calling the function with
|
||||
* @ref USB_EnableWriteFIFO().
|
||||
* @param numBytes
|
||||
* Number of bytes to write to the FIFO
|
||||
* @param dat
|
||||
* Pointer to XDATA buffer holding data to write to the FIFO
|
||||
******************************************************************************/
|
||||
static void USB_WriteFIFO_Xdata(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_XDATA))
|
||||
{
|
||||
while (numBytes--)
|
||||
{
|
||||
USB_SetFIFOByte(*dat);
|
||||
dat++;
|
||||
}
|
||||
}
|
||||
|
||||
#if SI_GPTR_MTYPE_PDATA != SI_GPTR_MTYPE_XDATA
|
||||
/***************************************************************************//**
|
||||
* @brief Reads data from the USB FIFO to a buffer in paged XRAM
|
||||
* @param numBytes
|
||||
* Number of bytes to read from the FIFO
|
||||
* @param dat
|
||||
* Pointer to PDATA buffer to hold data read from the FIFO
|
||||
* @param fifoNum
|
||||
* USB FIFO to read
|
||||
******************************************************************************/
|
||||
static void USB_ReadFIFO_Pdata(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_PDATA), uint8_t fifoNum)
|
||||
{
|
||||
while (--numBytes)
|
||||
{
|
||||
USB_GetFIFOByte(dat);
|
||||
dat++;
|
||||
}
|
||||
USB_GetLastFIFOByte(dat, fifoNum);
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Writes data held in paged XRAM to the USB FIFO
|
||||
* @details The FIFO to write must be set before calling the function with
|
||||
* @ref USB_EnableWriteFIFO().
|
||||
* @param numBytes
|
||||
* Number of bytes to write to the FIFO
|
||||
* @param dat
|
||||
* Pointer to PDATA buffer holding data to write to the FIFO
|
||||
******************************************************************************/
|
||||
static void USB_WriteFIFO_Pdata(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_PDATA))
|
||||
{
|
||||
while (numBytes--)
|
||||
{
|
||||
USB_SetFIFOByte(*dat);
|
||||
dat++;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if SI_GPTR_MTYPE_DATA != SI_GPTR_MTYPE_IDATA
|
||||
/***************************************************************************//**
|
||||
* @brief Reads data from the USB FIFO to a buffer in DRAM
|
||||
* @param numBytes
|
||||
* Number of bytes to read from the FIFO
|
||||
* @param dat
|
||||
* Pointer to DATA buffer to hold data read from the FIFO
|
||||
* @param fifoNum
|
||||
* USB FIFO to read
|
||||
******************************************************************************/
|
||||
static void USB_ReadFIFO_Data(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_DATA), uint8_t fifoNum)
|
||||
{
|
||||
while (--numBytes)
|
||||
{
|
||||
USB_GetFIFOByte(*dat);
|
||||
dat++;
|
||||
}
|
||||
USB_GetLastFIFOByte(*dat, fifoNum);
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Writes data held in DRAM to the USB FIFO
|
||||
* @details The FIFO to write must be set before calling the function with
|
||||
* @ref USB_EnableWriteFIFO().
|
||||
* @param numBytes
|
||||
* Number of bytes to write to the FIFO
|
||||
* @param dat
|
||||
* Pointer to DATA buffer to hold data read from the FIFO
|
||||
******************************************************************************/
|
||||
static void USB_WriteFIFO_Data(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_DATA))
|
||||
{
|
||||
while (numBytes--)
|
||||
{
|
||||
USB_SetFIFOByte(*dat);
|
||||
dat++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Writes data held in code space to the USB FIFO
|
||||
* @details The FIFO to write must be set before calling the function with
|
||||
* @ref USB_EnableWriteFIFO().
|
||||
* @param numBytes
|
||||
* Number of bytes to write to the FIFO
|
||||
* @param dat
|
||||
* Pointer to CODE buffer holding data to write to the FIFO
|
||||
******************************************************************************/
|
||||
static void USB_WriteFIFO_Code(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_CODE))
|
||||
{
|
||||
while (numBytes--)
|
||||
{
|
||||
USB_SetFIFOByte(*dat);
|
||||
dat++;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
/***************************************************************************//**
|
||||
* @brief Reads data from the USB FIFO to a buffer in generic memory space
|
||||
* @param numBytes
|
||||
* Number of bytes to read from the FIFO
|
||||
* @param dat
|
||||
* Pointer to generic buffer to hold data read from the FIFO
|
||||
* @param fifoNum
|
||||
* USB FIFO to read
|
||||
******************************************************************************/
|
||||
static void USB_ReadFIFO_Generic(uint8_t numBytes, uint8_t *dat, uint8_t fifoNum)
|
||||
{
|
||||
while (--numBytes)
|
||||
{
|
||||
USB_GetFIFOByte(*dat);
|
||||
dat++;
|
||||
}
|
||||
USB_GetLastFIFOByte(*dat, fifoNum);
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Writes data held in generic memory space to the USB FIFO
|
||||
* @details The FIFO to write must be set before calling the function with
|
||||
* @ref USB_EnableWriteFIFO().
|
||||
* @param numBytes
|
||||
* Number of bytes to write to the FIFO
|
||||
* @param dat
|
||||
* Pointer to generic buffer holding data to write to the FIFO
|
||||
******************************************************************************/
|
||||
static void USB_WriteFIFO_Generic(uint8_t numBytes, uint8_t *dat)
|
||||
{
|
||||
while (numBytes--)
|
||||
{
|
||||
USB_SetFIFOByte(*dat);
|
||||
dat++;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifdef SI_GPTR
|
@ -1,533 +0,0 @@
|
||||
/**************************************************************************//**
|
||||
* Copyright (c) 2015 by Silicon Laboratories Inc. All rights reserved.
|
||||
*
|
||||
* http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt
|
||||
*****************************************************************************/
|
||||
|
||||
#include "si_toolchain.h"
|
||||
#include "efm8_usb.h"
|
||||
#include <stdint.h>
|
||||
#include <endian.h>
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Global variables
|
||||
|
||||
extern SI_SEGMENT_VARIABLE(myUsbDevice, USBD_Device_TypeDef, MEM_MODEL_SEG);
|
||||
extern SI_SEGMENT_VARIABLE(txZero[2], uint8_t, SI_SEG_CODE);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Function prototypes
|
||||
|
||||
static void handleUsbEp0Int(void);
|
||||
static void handleUsbResetInt(void);
|
||||
static void handleUsbSuspendInt(void);
|
||||
static void handleUsbResumeInt(void);
|
||||
static void handleUsbEp0Tx(void);
|
||||
static void handleUsbEp0Rx(void);
|
||||
static void USB_ReadFIFOSetup(void);
|
||||
|
||||
#if (SLAB_USB_EP1IN_USED)
|
||||
void handleUsbIn1Int(void);
|
||||
#endif // SLAB_USB_EP1IN_USED
|
||||
#if (SLAB_USB_EP2IN_USED)
|
||||
void handleUsbIn2Int(void);
|
||||
#endif // SLAB_USB_EP2IN_USED
|
||||
#if (SLAB_USB_EP3IN_USED)
|
||||
void handleUsbIn3Int(void);
|
||||
#endif // SLAB_USB_EP3IN_USED
|
||||
|
||||
#if (SLAB_USB_EP1OUT_USED)
|
||||
void handleUsbOut1Int(void);
|
||||
#endif // SLAB_USB_EP1OUT_USED
|
||||
#if (SLAB_USB_EP2OUT_USED)
|
||||
void handleUsbOut2Int(void);
|
||||
#endif // SLAB_USB_EP2OUT_USED
|
||||
#if (SLAB_USB_EP3OUT_USED)
|
||||
void handleUsbOut3Int(void);
|
||||
#endif // SLAB_USB_EP3OUT_USED
|
||||
|
||||
void SendEp0Stall(void);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Functions
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief First-level handler for USB peripheral interrupt
|
||||
* @details If @ref SLAB_USB_POLLED_MODE is 1, this becomes a regular
|
||||
* function instead of an ISR and must be called by the application
|
||||
* periodically.
|
||||
******************************************************************************/
|
||||
#if (SLAB_USB_POLLED_MODE == 0)
|
||||
SI_INTERRUPT(usbIrqHandler, USB0_IRQn)
|
||||
#else
|
||||
void usbIrqHandler(void)
|
||||
#endif
|
||||
{
|
||||
uint8_t statusCommon, statusIn, statusOut, indexSave;
|
||||
|
||||
#if SLAB_USB_HANDLER_CB
|
||||
// Callback to user before processing
|
||||
USBD_EnterHandler();
|
||||
#endif
|
||||
|
||||
// Get the interrupt sources
|
||||
statusCommon = USB_GetCommonInts();
|
||||
statusIn = USB_GetInInts();
|
||||
statusOut = USB_GetOutInts();
|
||||
|
||||
#if SLAB_USB_POLLED_MODE
|
||||
if ((statusCommon == 0) && (statusIn == 0) && (statusOut == 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Save the current index
|
||||
indexSave = USB_GetIndex();
|
||||
|
||||
// Check Common USB Interrupts
|
||||
if (USB_IsSofIntActive(statusCommon))
|
||||
{
|
||||
#if SLAB_USB_SOF_CB
|
||||
USBD_SofCb(USB_GetSofNumber());
|
||||
#endif // SLAB_USB_SOF_CB
|
||||
|
||||
// Check for unhandled USB packets on EP0 and set the corresponding IN or
|
||||
// OUT interrupt active flag if necessary.
|
||||
if (((myUsbDevice.ep0.misc.bits.outPacketPending == true) && (myUsbDevice.ep0.state == D_EP_RECEIVING)) ||
|
||||
((myUsbDevice.ep0.misc.bits.inPacketPending == true) && (myUsbDevice.ep0.state == D_EP_TRANSMITTING)))
|
||||
{
|
||||
USB_SetEp0IntActive(statusIn);
|
||||
}
|
||||
// Check for unhandled USB OUT packets and set the corresponding OUT
|
||||
// interrupt active flag if necessary.
|
||||
#if SLAB_USB_EP1OUT_USED
|
||||
if ((myUsbDevice.ep1out.misc.bits.outPacketPending == true) && (myUsbDevice.ep1out.state == D_EP_RECEIVING))
|
||||
{
|
||||
USB_SetOut1IntActive(statusOut);
|
||||
}
|
||||
#endif
|
||||
#if SLAB_USB_EP2OUT_USED
|
||||
if ((myUsbDevice.ep2out.misc.bits.outPacketPending == true) && (myUsbDevice.ep2out.state == D_EP_RECEIVING))
|
||||
{
|
||||
USB_SetOut2IntActive(statusOut);
|
||||
}
|
||||
#endif
|
||||
#if SLAB_USB_EP3OUT_USED
|
||||
if ((myUsbDevice.ep3out.misc.bits.outPacketPending == true) && (myUsbDevice.ep3out.state == D_EP_RECEIVING))
|
||||
{
|
||||
USB_SetOut3IntActive(statusOut);
|
||||
}
|
||||
#endif
|
||||
#if (SLAB_USB_EP3IN_USED && (SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_ISOC))
|
||||
if ((myUsbDevice.ep3in.misc.bits.inPacketPending == true) && (myUsbDevice.ep3in.state == D_EP_TRANSMITTING))
|
||||
{
|
||||
USB_SetIn3IntActive(statusIn);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (USB_IsResetIntActive(statusCommon))
|
||||
{
|
||||
handleUsbResetInt();
|
||||
|
||||
// If VBUS is not present on detection of a USB reset, enter suspend mode.
|
||||
#if (SLAB_USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF)
|
||||
if (USB_IsVbusOn() == false)
|
||||
{
|
||||
USB_SetSuspendIntActive(statusCommon);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (USB_IsResumeIntActive(statusCommon))
|
||||
{
|
||||
handleUsbResumeInt();
|
||||
}
|
||||
|
||||
if (USB_IsSuspendIntActive(statusCommon))
|
||||
{
|
||||
handleUsbSuspendInt();
|
||||
}
|
||||
|
||||
#if SLAB_USB_EP3IN_USED
|
||||
if (USB_IsIn3IntActive(statusIn))
|
||||
{
|
||||
handleUsbIn3Int();
|
||||
}
|
||||
#endif // EP3IN_USED
|
||||
|
||||
#if SLAB_USB_EP3OUT_USED
|
||||
if (USB_IsOut3IntActive(statusOut))
|
||||
{
|
||||
handleUsbOut3Int();
|
||||
}
|
||||
#endif // EP3OUT_USED
|
||||
|
||||
#if SLAB_USB_EP2IN_USED
|
||||
if (USB_IsIn2IntActive(statusIn))
|
||||
{
|
||||
handleUsbIn2Int();
|
||||
}
|
||||
#endif // EP2IN_USED
|
||||
|
||||
#if SLAB_USB_EP1IN_USED
|
||||
if (USB_IsIn1IntActive(statusIn))
|
||||
{
|
||||
handleUsbIn1Int();
|
||||
}
|
||||
#endif // EP1IN_USED
|
||||
|
||||
#if SLAB_USB_EP2OUT_USED
|
||||
if (USB_IsOut2IntActive(statusOut))
|
||||
{
|
||||
handleUsbOut2Int();
|
||||
}
|
||||
#endif // EP2OUT_USED
|
||||
|
||||
#if SLAB_USB_EP1OUT_USED
|
||||
if (USB_IsOut1IntActive(statusOut))
|
||||
{
|
||||
handleUsbOut1Int();
|
||||
}
|
||||
#endif // EP1OUT_USED
|
||||
|
||||
// Check USB Endpoint 0 Interrupt
|
||||
if (USB_IsEp0IntActive(statusIn))
|
||||
{
|
||||
handleUsbEp0Int();
|
||||
}
|
||||
|
||||
// Restore index
|
||||
USB_SetIndex(indexSave);
|
||||
|
||||
#if SLAB_USB_HANDLER_CB
|
||||
// Callback to user before exiting
|
||||
USBD_ExitHandler();
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Handles Endpoint 0 transfer interrupt
|
||||
******************************************************************************/
|
||||
static void handleUsbEp0Int(void)
|
||||
{
|
||||
USB_SetIndex(0);
|
||||
|
||||
if (USB_Ep0SentStall() || USB_GetSetupEnd())
|
||||
{
|
||||
USB_Ep0ClearSentStall();
|
||||
USB_ServicedSetupEnd();
|
||||
myUsbDevice.ep0.state = D_EP_IDLE;
|
||||
myUsbDevice.ep0.misc.c = 0;
|
||||
}
|
||||
if (USB_Ep0OutPacketReady())
|
||||
{
|
||||
if (myUsbDevice.ep0.misc.bits.waitForRead == true)
|
||||
{
|
||||
myUsbDevice.ep0.misc.bits.outPacketPending = true;
|
||||
}
|
||||
else if (myUsbDevice.ep0.state == D_EP_IDLE)
|
||||
{
|
||||
myUsbDevice.ep0String.c = USB_STRING_DESCRIPTOR_UTF16LE;
|
||||
USB_ReadFIFOSetup();
|
||||
|
||||
// Vendor unique, Class or Standard setup commands override?
|
||||
#if SLAB_USB_SETUP_CMD_CB
|
||||
if (USBD_SetupCmdCb(&myUsbDevice.setup) == USB_STATUS_REQ_UNHANDLED)
|
||||
{
|
||||
#endif
|
||||
if (myUsbDevice.setup.bmRequestType.Type == USB_SETUP_TYPE_STANDARD)
|
||||
{
|
||||
USBDCH9_SetupCmd();
|
||||
}
|
||||
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)
|
||||
{
|
||||
handleUsbEp0Rx();
|
||||
}
|
||||
else
|
||||
{
|
||||
myUsbDevice.ep0.misc.bits.outPacketPending = true;
|
||||
}
|
||||
}
|
||||
if ((myUsbDevice.ep0.state == D_EP_TRANSMITTING) && (USB_Ep0InPacketReady() == 0))
|
||||
{
|
||||
handleUsbEp0Tx();
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Reads and formats a setup packet
|
||||
******************************************************************************/
|
||||
static void USB_ReadFIFOSetup(void)
|
||||
{
|
||||
uint16_t MEM_MODEL_SEG *ptr = &myUsbDevice.setup;
|
||||
|
||||
USB_ReadFIFO(0, 8, (uint8_t *)ptr);
|
||||
|
||||
USB_Ep0ServicedOutPacketReady();
|
||||
|
||||
// Modify for Endian-ness of the compiler
|
||||
ptr[1] = le16toh(ptr[1]);
|
||||
ptr[2] = le16toh(ptr[2]);
|
||||
ptr[3] = le16toh(ptr[3]);
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Handles USB port reset interrupt
|
||||
* @details After receiving a USB reset, halt all endpoints except for
|
||||
* Endpoint 0, set the device state, and configure USB hardware.
|
||||
******************************************************************************/
|
||||
static void handleUsbResetInt(void)
|
||||
{
|
||||
// Setup EP0 to receive SETUP packets
|
||||
myUsbDevice.ep0.state = D_EP_IDLE;
|
||||
|
||||
// Halt all other endpoints
|
||||
#if SLAB_USB_EP1IN_USED
|
||||
myUsbDevice.ep1in.state = D_EP_HALT;
|
||||
#endif
|
||||
#if SLAB_USB_EP2IN_USED
|
||||
myUsbDevice.ep2in.state = D_EP_HALT;
|
||||
#endif
|
||||
#if SLAB_USB_EP3IN_USED
|
||||
myUsbDevice.ep3in.state = D_EP_HALT;
|
||||
#endif
|
||||
#if SLAB_USB_EP1OUT_USED
|
||||
myUsbDevice.ep1out.state = D_EP_HALT;
|
||||
#endif
|
||||
#if SLAB_USB_EP2OUT_USED
|
||||
myUsbDevice.ep2out.state = D_EP_HALT;
|
||||
#endif
|
||||
#if SLAB_USB_EP3OUT_USED
|
||||
myUsbDevice.ep3out.state = D_EP_HALT;
|
||||
#endif
|
||||
|
||||
// After a USB reset, some USB hardware configurations will be reset and must
|
||||
// be reconfigured.
|
||||
|
||||
// Re-enable clock recovery
|
||||
#if SLAB_USB_CLOCK_RECOVERY_ENABLED
|
||||
#if SLAB_USB_FULL_SPEED
|
||||
USB_EnableFullSpeedClockRecovery();
|
||||
#else
|
||||
USB_EnableLowSpeedClockRecovery();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Re-enable USB interrupts
|
||||
USB_EnableSuspendDetection();
|
||||
USB_EnableDeviceInts();
|
||||
|
||||
// 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
USBD_SetUsbState(USBD_STATE_ATTACHED);
|
||||
}
|
||||
#else
|
||||
USBD_SetUsbState(USBD_STATE_DEFAULT);
|
||||
#endif // (!(SLAB_USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF))
|
||||
|
||||
#if SLAB_USB_RESET_CB
|
||||
// Make the USB Reset Callback
|
||||
USBD_ResetCb();
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Handle USB port suspend interrupt
|
||||
* @details After receiving a USB reset, set the device state and
|
||||
* call @ref USBD_Suspend() if configured to do so in
|
||||
* @ref SLAB_USB_PWRSAVE_MODE
|
||||
******************************************************************************/
|
||||
static void handleUsbSuspendInt(void)
|
||||
{
|
||||
if (myUsbDevice.state >= USBD_STATE_POWERED)
|
||||
{
|
||||
USBD_SetUsbState(USBD_STATE_SUSPENDED);
|
||||
|
||||
#if (SLAB_USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONSUSPEND)
|
||||
USBD_Suspend();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Handles USB port resume interrupt
|
||||
* @details Restore the device state to its previous value.
|
||||
******************************************************************************/
|
||||
static void handleUsbResumeInt(void)
|
||||
{
|
||||
USBD_SetUsbState(myUsbDevice.savedState);
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Handles transmit data phase on Endpoint 0
|
||||
******************************************************************************/
|
||||
static void handleUsbEp0Tx(void)
|
||||
{
|
||||
uint8_t count, count_snapshot, i;
|
||||
bool callback = myUsbDevice.ep0.misc.bits.callback;
|
||||
|
||||
// The number of bytes to send in the next packet must be less than or equal
|
||||
// to the maximum EP0 packet size.
|
||||
count = (myUsbDevice.ep0.remaining >= USB_EP0_SIZE) ?
|
||||
USB_EP0_SIZE : myUsbDevice.ep0.remaining;
|
||||
|
||||
// Save the packet size for future use.
|
||||
count_snapshot = count;
|
||||
|
||||
// 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,
|
||||
// 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 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)
|
||||
{
|
||||
USB_WriteFIFO(0, 2, myUsbDevice.ep0.buf, false);
|
||||
myUsbDevice.ep0.buf += 2;
|
||||
count -= 2;
|
||||
myUsbDevice.ep0String.encoding.init = false;
|
||||
}
|
||||
|
||||
// Insert a 0x00 between each character of the string.
|
||||
for (i = 0; i < count / 2; i++)
|
||||
{
|
||||
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
|
||||
// data normally.
|
||||
else
|
||||
{
|
||||
USB_WriteFIFO(0, count, myUsbDevice.ep0.buf, false);
|
||||
myUsbDevice.ep0.buf += count;
|
||||
}
|
||||
|
||||
myUsbDevice.ep0.misc.bits.inPacketPending = false;
|
||||
myUsbDevice.ep0.remaining -= count_snapshot;
|
||||
|
||||
// If the last packet of the transfer is exactly the maximum EP0 packet size,
|
||||
// we will have to send a ZLP (zero-length packet) after the last data packet
|
||||
// to signal to the host that the transfer is complete.
|
||||
// Check for the ZLP packet case here.
|
||||
if ((myUsbDevice.ep0.remaining == 0) && (count_snapshot != USB_EP0_SIZE))
|
||||
{
|
||||
USB_Ep0SetLastInPacketReady();
|
||||
myUsbDevice.ep0.state = D_EP_IDLE;
|
||||
myUsbDevice.ep0String.c = USB_STRING_DESCRIPTOR_UTF16LE;
|
||||
myUsbDevice.ep0.misc.c = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do not call USB_Ep0SetLastInPacketReady() because we still need to send
|
||||
// the ZLP.
|
||||
USB_Ep0SetInPacketReady();
|
||||
}
|
||||
// Make callback if requested
|
||||
if (callback == true)
|
||||
{
|
||||
USBD_XferCompleteCb(EP0, USB_STATUS_OK, count_snapshot, myUsbDevice.ep0.remaining);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Handles receive data phase on Endpoint 0
|
||||
******************************************************************************/
|
||||
void handleUsbEp0Rx(void)
|
||||
{
|
||||
uint8_t count;
|
||||
USB_Status_TypeDef status;
|
||||
bool callback = myUsbDevice.ep0.misc.bits.callback;
|
||||
|
||||
// Get the number of bytes received
|
||||
count = USB_Ep0GetCount();
|
||||
|
||||
// If the call to USBD_Read() did not give a large enough buffer to hold this
|
||||
// data, set the outPacketPending flag and signal an RX overrun.
|
||||
if (myUsbDevice.ep0.remaining < count)
|
||||
{
|
||||
myUsbDevice.ep0.state = D_EP_IDLE;
|
||||
myUsbDevice.ep0.misc.bits.outPacketPending = true;
|
||||
status = USB_STATUS_EP_RX_BUFFER_OVERRUN;
|
||||
}
|
||||
else
|
||||
{
|
||||
USB_ReadFIFO(0, count, myUsbDevice.ep0.buf);
|
||||
myUsbDevice.ep0.buf += count;
|
||||
myUsbDevice.ep0.remaining -= count;
|
||||
status = USB_STATUS_OK;
|
||||
|
||||
// If the last packet of the transfer is exactly the maximum EP0 packet
|
||||
// size, we will must wait to receive a ZLP (zero-length packet) after the
|
||||
// last data packet. This signals that the host has completed the transfer.
|
||||
// Check for the ZLP packet case here.
|
||||
if ((myUsbDevice.ep0.remaining == 0) && (count != USB_EP0_SIZE))
|
||||
{
|
||||
USB_Ep0SetLastOutPacketReady();
|
||||
myUsbDevice.ep0.state = D_EP_IDLE;
|
||||
myUsbDevice.ep0.misc.bits.callback = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do not call USB_Ep0SetLastOutPacketReady() until we get the ZLP.
|
||||
USB_Ep0ServicedOutPacketReady();
|
||||
}
|
||||
}
|
||||
|
||||
// Make callback if requested
|
||||
if (callback == true)
|
||||
{
|
||||
USBD_XferCompleteCb(EP0, status, count, myUsbDevice.ep0.remaining);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Send a procedural stall on Endpoint 0
|
||||
******************************************************************************/
|
||||
void SendEp0Stall(void)
|
||||
{
|
||||
USB_SetIndex(0);
|
||||
myUsbDevice.ep0.state = D_EP_STALL;
|
||||
USB_Ep0SendStall();
|
||||
}
|
||||
|
||||
// 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
|
||||
// and the ISR will not be present.
|
||||
void forceModuleLoad_usbint(void){}
|
File diff suppressed because it is too large
Load Diff
@ -1,232 +0,0 @@
|
||||
/**************************************************************************//**
|
||||
* Copyright (c) 2015 by Silicon Laboratories Inc. All rights reserved.
|
||||
*
|
||||
* http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt
|
||||
*****************************************************************************/
|
||||
|
||||
#include "usb_0.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/** @addtogroup usb_0_runtime USB0 Runtime API */
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Functions
|
||||
|
||||
// -------------------------------
|
||||
// Utility Functions
|
||||
|
||||
/**************************************************************************//**
|
||||
* @brief Reads a 16-bit indirect USB register value
|
||||
* @param regAddr
|
||||
* Address of high byte of 16-bit USB indirect register to read
|
||||
* @return 16-bit register value
|
||||
*****************************************************************************/
|
||||
static uint16_t USB_GetShortRegister(uint8_t regAddr)
|
||||
{
|
||||
uint16_t retVal;
|
||||
|
||||
USB_READ_BYTE(regAddr);
|
||||
retVal = (USB0DAT << 8);
|
||||
USB_READ_BYTE((regAddr - 1));
|
||||
retVal |= USB0DAT;
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// -------------------------------
|
||||
// USB0 Peripheral Driver Functions
|
||||
|
||||
void USB_SetIndex(uint8_t epsel)
|
||||
{
|
||||
USB_WRITE_BYTE(INDEX, epsel);
|
||||
}
|
||||
|
||||
uint8_t USB_GetCommonInts(void)
|
||||
{
|
||||
USB_READ_BYTE(CMINT);
|
||||
return USB0DAT;
|
||||
}
|
||||
|
||||
uint8_t USB_GetInInts(void)
|
||||
{
|
||||
USB_READ_BYTE(IN1INT);
|
||||
return USB0DAT;
|
||||
}
|
||||
|
||||
uint8_t USB_GetOutInts(void)
|
||||
{
|
||||
USB_READ_BYTE(OUT1INT);
|
||||
return USB0DAT;
|
||||
}
|
||||
|
||||
uint8_t USB_GetIndex(void)
|
||||
{
|
||||
USB_READ_BYTE(INDEX);
|
||||
return USB0DAT;
|
||||
}
|
||||
|
||||
bool USB_IsSuspended(void)
|
||||
{
|
||||
USB_READ_BYTE(POWER);
|
||||
return USB0DAT & POWER_SUSMD__SUSPENDED;
|
||||
}
|
||||
|
||||
bool USB_GetSetupEnd(void)
|
||||
{
|
||||
USB_READ_BYTE(E0CSR);
|
||||
return USB0DAT & E0CSR_SUEND__SET;
|
||||
}
|
||||
|
||||
bool USB_Ep0SentStall(void)
|
||||
{
|
||||
USB_READ_BYTE(E0CSR);
|
||||
return USB0DAT & E0CSR_STSTL__SET;
|
||||
}
|
||||
|
||||
bool USB_Ep0OutPacketReady(void)
|
||||
{
|
||||
USB_READ_BYTE(E0CSR);
|
||||
return USB0DAT & E0CSR_OPRDY__SET;
|
||||
}
|
||||
|
||||
bool USB_Ep0InPacketReady(void)
|
||||
{
|
||||
USB_READ_BYTE(E0CSR);
|
||||
return USB0DAT & E0CSR_INPRDY__SET;
|
||||
}
|
||||
|
||||
uint8_t USB_Ep0GetCount(void)
|
||||
{
|
||||
USB_READ_BYTE(E0CNT);
|
||||
return USB0DAT;
|
||||
}
|
||||
|
||||
bool USB_EpnInGetSentStall(void)
|
||||
{
|
||||
USB_READ_BYTE(EINCSRL);
|
||||
return (bool)(USB0DAT & EINCSRL_STSTL__SET);
|
||||
}
|
||||
|
||||
void USB_AbortInEp(uint8_t fifoNum)
|
||||
{
|
||||
USB_SetIndex(fifoNum);
|
||||
USB_EpnInFlush();
|
||||
USB_EpnInFlush();
|
||||
}
|
||||
|
||||
bool USB_EpnOutGetSentStall(void)
|
||||
{
|
||||
USB_READ_BYTE(EOUTCSRL);
|
||||
return (bool)(USB0DAT & EOUTCSRL_STSTL__SET);
|
||||
}
|
||||
|
||||
bool USB_EpnGetOutPacketReady(void)
|
||||
{
|
||||
USB_READ_BYTE(EOUTCSRL);
|
||||
return (bool)(USB0DAT & EOUTCSRL_OPRDY__SET);
|
||||
}
|
||||
|
||||
uint16_t USB_EpOutGetCount(void)
|
||||
{
|
||||
return USB_GetShortRegister(EOUTCNTH);
|
||||
}
|
||||
|
||||
void USB_AbortOutEp(uint8_t fifoNum)
|
||||
{
|
||||
USB_SetIndex(fifoNum);
|
||||
USB_EpnOutFlush();
|
||||
USB_EpnOutFlush();
|
||||
}
|
||||
|
||||
void USB_ActivateEp(uint8_t ep,
|
||||
uint16_t packetSize,
|
||||
bool inDir,
|
||||
bool splitMode,
|
||||
bool isoMode)
|
||||
{
|
||||
uint8_t CSRH_mask = 0;
|
||||
uint16_t fifoSize;
|
||||
|
||||
USB_SetIndex(ep);
|
||||
|
||||
// Determine the available fifoSize for a given endpoint based on the
|
||||
// splitMode setting
|
||||
fifoSize = (splitMode == true) ? (16 << ep) : (32 << ep);
|
||||
|
||||
if (packetSize <= fifoSize)
|
||||
{
|
||||
CSRH_mask |= EINCSRH_DBIEN__ENABLED;
|
||||
}
|
||||
|
||||
if (isoMode == true)
|
||||
{
|
||||
CSRH_mask |= EINCSRH_ISO__ENABLED;
|
||||
}
|
||||
|
||||
if (inDir == true)
|
||||
{
|
||||
CSRH_mask |= EINCSRH_DIRSEL__IN;
|
||||
|
||||
if (splitMode == true)
|
||||
{
|
||||
CSRH_mask |= EINCSRH_SPLIT__ENABLED;
|
||||
}
|
||||
USB_WRITE_BYTE(EINCSRL, EINCSRL_CLRDT__BMASK);
|
||||
USB_WRITE_BYTE(EINCSRH, CSRH_mask);
|
||||
}
|
||||
else // OUT
|
||||
{
|
||||
USB_WRITE_BYTE(EOUTCSRL, EOUTCSRL_CLRDT__BMASK);
|
||||
USB_WRITE_BYTE(EOUTCSRH, CSRH_mask);
|
||||
|
||||
if (splitMode == false)
|
||||
{
|
||||
USB_WRITE_BYTE(EINCSRH, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t USB_GetSofNumber(void)
|
||||
{
|
||||
return USB_GetShortRegister(FRAMEH);
|
||||
}
|
||||
|
||||
bool USB_GetIntsEnabled(void)
|
||||
{
|
||||
SFRPAGE = PG2_PAGE;
|
||||
return (bool)(EIE2 & EIE2_EUSB0__ENABLED);
|
||||
}
|
||||
|
||||
bool USB_IsPrefetchEnabled(void)
|
||||
{
|
||||
SFRPAGE = PG2_PAGE;
|
||||
return (bool)(PFE0CN & PFE0CN_PFEN__ENABLED);
|
||||
}
|
||||
|
||||
bool USB_IsRegulatorEnabled(void)
|
||||
{
|
||||
SFRPAGE = PG3_PAGE;
|
||||
return !(REG1CN & REG1CN_REG1ENB__DISABLED);
|
||||
}
|
||||
|
||||
void USB_SuspendOscillator(void)
|
||||
{
|
||||
uint8_t clkSelSave = CLKSEL & 0x7F;
|
||||
|
||||
CLKSEL = (CLKSEL_CLKDIV__SYSCLK_DIV_8 | CLKSEL_CLKSL__HFOSC0);
|
||||
SFRPAGE = LEGACY_PAGE;
|
||||
PCON1 |= PCON1_SUSPEND__SUSPEND;
|
||||
CLKSEL = clkSelSave;
|
||||
|
||||
// If the target frequency is over 24MHz, our write to CLKSEL will be ignored.
|
||||
// If this is the case we need to do two writes: one to 24 MHz followed by the
|
||||
// actual value.
|
||||
if ((CLKSEL & 0x7F) != clkSelSave)
|
||||
{
|
||||
CLKSEL = (CLKSEL_CLKDIV__SYSCLK_DIV_1 | CLKSEL_CLKSL__HFOSC0);
|
||||
CLKSEL = clkSelSave;
|
||||
}
|
||||
}
|
||||
|
||||
/** @} (end addtogroup usb_0_runtime USB0 Runtime API) */
|
@ -48,11 +48,11 @@
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc}""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/inc""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../efm32/inc""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../fido2""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../tinycbor/src""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../crypto/sha256""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../crypto/micro-ecc""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../crypto/tiny-AES-c""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../../fido2""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../../tinycbor/src""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../../crypto/sha256""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../../crypto/micro-ecc""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../../crypto/tiny-AES-c""/>
|
||||
<listOptionValue builtIn="false" value=""${StudioSdkPath}/hardware/kit/common/bsp""/>
|
||||
<listOptionValue builtIn="false" value=""${StudioSdkPath}/hardware/kit/common/drivers""/>
|
||||
<listOptionValue builtIn="false" value=""${StudioSdkPath}/platform/Device/SiliconLabs/EFM32JG1B/Include""/>
|
||||
|
@ -21,7 +21,7 @@
|
||||
<link>
|
||||
<name>crypto</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-1-PROJECT_LOC%7D/crypto</locationURI>
|
||||
<locationURI>PARENT-2-PROJECT_LOC/crypto</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>efm32</name>
|
||||
@ -31,7 +31,7 @@
|
||||
<link>
|
||||
<name>fido2</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-1-PROJECT_LOC%7D/fido2</locationURI>
|
||||
<locationURI>PARENT-2-PROJECT_LOC/fido2</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>CMSIS/EFM32JG1B/startup_gcc_efm32jg1b.s</name>
|
||||
|
Reference in New Issue
Block a user