diff --git a/Makefile b/Makefile
index 3006988..5b9d65d 100644
--- a/Makefile
+++ b/Makefile
@@ -22,6 +22,7 @@ all: main
test: testgcm
efm8prog:
+ flashefm8.exe -part EFM8UB10F8G -sn 440105518 -erase
flashefm8.exe -part EFM8UB10F8G -sn 440105518 -upload '.\efm8\Keil 8051 v9.53 - Debug\efm8.hex'
efm32prog:
diff --git a/efm32/.cproject b/efm32/.cproject
index 6cc2d33..02bf5c0 100644
--- a/efm32/.cproject
+++ b/efm32/.cproject
@@ -23,7 +23,7 @@
-
+
@@ -56,8 +56,8 @@
-
+
@@ -79,14 +79,15 @@
-
+
+
@@ -137,7 +138,7 @@
-
+
@@ -159,8 +160,8 @@
-
+
@@ -176,14 +177,15 @@
-
+
+
@@ -204,7 +206,7 @@
-
+
diff --git a/efm32/EFM32.hwconf b/efm32/EFM32.hwconf
index 15d21ae..4915d0a 100644
--- a/efm32/EFM32.hwconf
+++ b/efm32/EFM32.hwconf
@@ -22,6 +22,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -30,8 +55,19 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/efm32/src/InitDevice.c b/efm32/src/InitDevice.c
index 2574816..f8204b0 100644
--- a/efm32/src/InitDevice.c
+++ b/efm32/src/InitDevice.c
@@ -34,6 +34,7 @@ extern void enter_DefaultMode_from_RESET(void) {
EMU_enter_DefaultMode_from_RESET();
CMU_enter_DefaultMode_from_RESET();
USART0_enter_DefaultMode_from_RESET();
+ USART1_enter_DefaultMode_from_RESET();
CRYOTIMER_enter_DefaultMode_from_RESET();
PORTIO_enter_DefaultMode_from_RESET();
// [Config Calls]$
@@ -129,6 +130,9 @@ extern void CMU_enter_DefaultMode_from_RESET(void) {
/* Enable clock for USART0 */
CMU_ClockEnable(cmuClock_USART0, true);
+ /* Enable clock for USART1 */
+ CMU_ClockEnable(cmuClock_USART1, true);
+
/* Enable clock for GPIO by default */
CMU_ClockEnable(cmuClock_GPIO, true);
@@ -321,18 +325,85 @@ extern void USART1_enter_DefaultMode_from_RESET(void) {
// [USART_InitAsync]$
// $[USART_InitSync]
+ USART_InitSync_TypeDef initsync = USART_INITSYNC_DEFAULT;
+
+ initsync.enable = usartDisable;
+ initsync.baudrate = 100000;
+ initsync.databits = usartDatabits8;
+ initsync.master = 1;
+ initsync.msbf = 1;
+ initsync.clockMode = usartClockMode0;
+#if defined( USART_INPUT_RXPRS ) && defined( USART_TRIGCTRL_AUTOTXTEN )
+ initsync.prsRxEnable = 0;
+ initsync.prsRxCh = 0;
+ initsync.autoTx = 0;
+#endif
+
+ USART_InitSync(USART1, &initsync);
// [USART_InitSync]$
// $[USART_InitPrsTrigger]
+ USART_PrsTriggerInit_TypeDef initprs = USART_INITPRSTRIGGER_DEFAULT;
+
+ initprs.rxTriggerEnable = 0;
+ initprs.txTriggerEnable = 0;
+ initprs.prsTriggerChannel = usartPrsTriggerCh0;
+
+ USART_InitPrsTrigger(USART1, &initprs);
// [USART_InitPrsTrigger]$
// $[USART_InitIO]
+ /* Set up CLK pin */
+ USART1->ROUTELOC0 = (USART1->ROUTELOC0 & (~_USART_ROUTELOC0_CLKLOC_MASK))
+ | USART_ROUTELOC0_CLKLOC_LOC11;
+ USART1->ROUTEPEN = USART1->ROUTEPEN | USART_ROUTEPEN_CLKPEN;
+
+ /* Disable CS pin */
+ USART1->ROUTELOC0 = (USART1->ROUTELOC0 & (~_USART_ROUTELOC0_CSLOC_MASK))
+ | USART_ROUTELOC0_CSLOC_LOC0;
+ USART1->ROUTEPEN = USART1->ROUTEPEN & (~USART_ROUTEPEN_CSPEN);
+
+ /* Disable CTS pin */
+ USART1->ROUTELOC1 = (USART1->ROUTELOC1 & (~_USART_ROUTELOC1_CTSLOC_MASK))
+ | USART_ROUTELOC1_CTSLOC_LOC0;
+ USART1->ROUTEPEN = USART1->ROUTEPEN & (~USART_ROUTEPEN_CTSPEN);
+
+ /* Disable RTS pin */
+ USART1->ROUTELOC1 = (USART1->ROUTELOC1 & (~_USART_ROUTELOC1_RTSLOC_MASK))
+ | USART_ROUTELOC1_RTSLOC_LOC0;
+ USART1->ROUTEPEN = USART1->ROUTEPEN & (~USART_ROUTEPEN_RTSPEN);
+
+ /* Set up RX pin */
+ USART1->ROUTELOC0 = (USART1->ROUTELOC0 & (~_USART_ROUTELOC0_RXLOC_MASK))
+ | USART_ROUTELOC0_RXLOC_LOC11;
+ USART1->ROUTEPEN = USART1->ROUTEPEN | USART_ROUTEPEN_RXPEN;
+
+ /* Set up TX pin */
+ USART1->ROUTELOC0 = (USART1->ROUTELOC0 & (~_USART_ROUTELOC0_TXLOC_MASK))
+ | USART_ROUTELOC0_TXLOC_LOC11;
+ USART1->ROUTEPEN = USART1->ROUTEPEN | USART_ROUTEPEN_TXPEN;
+
// [USART_InitIO]$
// $[USART_Misc]
+ /* Disable CTS */
+ USART1->CTRLX = USART1->CTRLX & (~USART_CTRLX_CTSEN);
+ /* Set CTS active low */
+ USART1->CTRLX = USART1->CTRLX & (~USART_CTRLX_CTSINV);
+ /* Set RTS active low */
+ USART1->CTRLX = USART1->CTRLX & (~USART_CTRLX_RTSINV);
+ /* Set CS active low */
+ USART1->CTRL = USART1->CTRL & (~USART_CTRL_CSINV);
+ /* Set TX active high */
+ USART1->CTRL = USART1->CTRL & (~USART_CTRL_TXINV);
+ /* Set RX active high */
+ USART1->CTRL = USART1->CTRL & (~USART_CTRL_RXINV);
// [USART_Misc]$
// $[USART_Enable]
+
+ /* Enable USART if opted by user */
+ USART_Enable(USART1, usartEnable);
// [USART_Enable]$
}
@@ -526,6 +597,21 @@ extern void PORTIO_enter_DefaultMode_from_RESET(void) {
// [Port B Configuration]$
// $[Port C Configuration]
+
+ /* Pin PC6 is configured to Push-pull */
+ GPIO_PinModeSet(gpioPortC, 6, gpioModePushPull, 1);
+
+ /* Pin PC7 is configured to Input enabled with pull-up */
+ GPIO_PinModeSet(gpioPortC, 7, gpioModeInputPull, 1);
+
+ /* Pin PC8 is configured to Push-pull */
+ GPIO_PinModeSet(gpioPortC, 8, gpioModePushPull, 1);
+
+ /* Pin PC9 is configured to Input enabled with pull-up */
+ GPIO_PinModeSet(gpioPortC, 9, gpioModeInputPull, 1);
+
+ /* Pin PC10 is configured to Push-pull */
+ GPIO_PinModeSet(gpioPortC, 10, gpioModePushPull, 1);
// [Port C Configuration]$
// $[Port D Configuration]
diff --git a/efm32/src/device.c b/efm32/src/device.c
index b7b3d77..993dbfa 100644
--- a/efm32/src/device.c
+++ b/efm32/src/device.c
@@ -10,6 +10,7 @@
#include "em_chip.h"
#include "em_gpio.h"
+#include "em_usart.h"
#include "cbor.h"
#include "log.h"
@@ -61,7 +62,8 @@ int ctap_user_presence_test()
// data is HID_MESSAGE_SIZE long in bytes
void ctaphid_write_block(uint8_t * data)
{
- dump_hex(data, HID_MESSAGE_SIZE);
+ printf1(TAG_DUMP,"<< "); dump_hex1(TAG_DUMP, data, HID_MESSAGE_SIZE);
+ usbhid_send(data);
}
void heartbeat()
@@ -83,13 +85,37 @@ void usbhid_init()
}
+static int msgs_to_recv = 0;
+
int usbhid_recv(uint8_t * msg)
{
+ int i;
+ if (msgs_to_recv)
+ {
+ GPIO_PinOutClear(gpioPortC,10);
+ for (i = 0; i < 64; i++)
+ {
+ msg[i] = USART_SpiTransfer(USART1, 0);
+ delay(1);
+ }
+ msgs_to_recv--;
+// printf(">> ");
+// dump_hex(msg,64);
+ return 64;
+ }
+
return 0;
}
void usbhid_send(uint8_t * msg)
{
+ int i;
+ GPIO_PinOutSet(gpioPortC,10);
+ for (i = 0; i < HID_MESSAGE_SIZE; i++)
+ {
+ USART_SpiTransfer(USART1, *msg++);
+ }
+ GPIO_PinOutClear(gpioPortC,10);
}
void usbhid_close()
@@ -100,6 +126,29 @@ void main_loop_delay()
{
}
+void delay(int ms)
+{
+ int t1 = millis();
+ while(millis() - t1 < ms)
+ ;
+}
+
+void GPIO_ODD_IRQHandler()
+{
+ uint32_t flag = GPIO->IF;
+ GPIO->IFC = flag;
+ if (flag & (1<<9))
+ {
+// printf("pin 9 interrupt\r\n");
+ msgs_to_recv++;
+ }
+ else
+ {
+ printf1(TAG_ERR,"wrong pin int %x\r\n",flag);
+ }
+
+
+}
void device_init(void)
{
@@ -107,6 +156,7 @@ void device_init(void)
CHIP_Init();
enter_DefaultMode_from_RESET();
+ // status LEDS
GPIO_PinModeSet(gpioPortF,
4,
gpioModePushPull,
@@ -117,7 +167,15 @@ void device_init(void)
gpioModePushPull,
1);
+ // SPI R/W indicator
+ GPIO_PinModeSet(gpioPortC,
+ 10,
+ gpioModePushPull,
+ 0);
+ // USB message rdy ext int
+ GPIO_ExtIntConfig(gpioPortC, 9, 9, 1, 0,1);
+ NVIC_EnableIRQ(GPIO_ODD_IRQn);
printing_init();
@@ -127,5 +185,7 @@ void device_init(void)
cbor_encoder_init(&test, buf, 20, 0);
printf("Device init\r\n");
+ int i=0;
+
}
diff --git a/efm8/.cproject b/efm8/.cproject
index d20afd6..6a0550a 100644
--- a/efm8/.cproject
+++ b/efm8/.cproject
@@ -70,7 +70,7 @@
-
+
@@ -170,7 +170,7 @@
-
+
diff --git a/efm8/.settings/org.eclipse.cdt.codan.core.prefs b/efm8/.settings/org.eclipse.cdt.codan.core.prefs
new file mode 100644
index 0000000..2ead633
--- /dev/null
+++ b/efm8/.settings/org.eclipse.cdt.codan.core.prefs
@@ -0,0 +1,71 @@
+eclipse.preferences.version=1
+org.eclipse.cdt.codan.checkers.errnoreturn=Warning
+org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false}
+org.eclipse.cdt.codan.checkers.errreturnvalue=Error
+org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.checkers.nocommentinside=-Error
+org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.checkers.nolinecomment=-Error
+org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.checkers.noreturn=Error
+org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false}
+org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error
+org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error
+org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false}
+org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning
+org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},unknown\=>false,exceptions\=>()}
+org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error
+org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning
+org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},skip\=>true}
+org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error
+org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error
+org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error
+org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error
+org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error
+org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error
+org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error
+org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info
+org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},pattern\=>"^[a-z]",macro\=>true,exceptions\=>()}
+org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error
+org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error
+org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error
+org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning
+org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning
+org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>()}
+org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},paramNot\=>false}
+org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},else\=>false,afterelse\=>false}
+org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error
+org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true}
+org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true}
+org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>("@(\#)","$Id")}
+org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error
+org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+useParentScope=false
diff --git a/efm8/efm8.hwconf b/efm8/efm8.hwconf
index bab7c7b..7189f40 100644
--- a/efm8/efm8.hwconf
+++ b/efm8/efm8.hwconf
@@ -12,6 +12,9 @@
+
+
+
@@ -20,21 +23,20 @@
+
+
-
-
-
-
-
+
+
-
+
@@ -42,19 +44,17 @@
-
-
-
-
-
-
-
+
+
+
+
-
+
+
+
+
-
-
diff --git a/efm8/inc/InitDevice.h b/efm8/inc/InitDevice.h
index fa302f2..a326614 100644
--- a/efm8/inc/InitDevice.h
+++ b/efm8/inc/InitDevice.h
@@ -19,8 +19,8 @@ extern void enter_DefaultMode_from_RESET(void);
extern void WDT_0_enter_DefaultMode_from_RESET(void);
extern void PORTS_0_enter_DefaultMode_from_RESET(void);
extern void PORTS_1_enter_DefaultMode_from_RESET(void);
-extern void PORTS_2_enter_DefaultMode_from_RESET(void);
extern void PBCFG_0_enter_DefaultMode_from_RESET(void);
+extern void LFOSC_0_enter_DefaultMode_from_RESET(void);
extern void CIP51_0_enter_DefaultMode_from_RESET(void);
extern void CLOCK_0_enter_DefaultMode_from_RESET(void);
extern void TIMER01_0_enter_DefaultMode_from_RESET(void);
diff --git a/efm8/inc/app.h b/efm8/inc/app.h
index 436ee73..26363a3 100644
--- a/efm8/inc/app.h
+++ b/efm8/inc/app.h
@@ -8,9 +8,14 @@
#ifndef INC_APP_H_
#define INC_APP_H_
-#define USE_PRINTING
+//#define USE_PRINTING
void usb_transfer_complete();
void spi_transfer_complete();
+#define EFM32_RW_PIN P1_B2
+#define MSG_RDY_INT_PIN P1_B1
+
+void delay(int ms);
+
#endif /* INC_APP_H_ */
diff --git a/efm8/inc/eeprom.h b/efm8/inc/eeprom.h
new file mode 100644
index 0000000..deae867
--- /dev/null
+++ b/efm8/inc/eeprom.h
@@ -0,0 +1,19 @@
+#ifndef EEPROM_H_
+#define EEPROM_H_
+
+#include "app.h"
+
+void eeprom_init();
+
+void eeprom_read(uint16_t addr, uint8_t * buf, uint8_t len);
+
+void _eeprom_write(uint16_t addr, uint8_t * buf, uint8_t len, uint8_t flags);
+
+extern char __erase_mem[3];
+
+#define eeprom_write(a,b,l) _eeprom_write(a,b,l,0x1)
+#define eeprom_erase(a) _eeprom_write(a,__erase_mem,1,0x3)
+
+#define EEPROM_DATA_START 0xF800
+
+#endif /* EEPROM_H_ */
diff --git a/efm8/inc/printing.h b/efm8/inc/printing.h
index 25c0320..b57fe13 100644
--- a/efm8/inc/printing.h
+++ b/efm8/inc/printing.h
@@ -36,9 +36,11 @@
#define reboot() (RSTSRC = 1 << 4)
+#define millis() ((uint16_t)(TMR3L | (TMR3H << 8)))
+
void u2f_delay(uint32_t ms);
-void usb_write(uint8_t* buf, uint8_t len);
+void usb_write();
diff --git a/efm8/lib/c8051f380/efm8_assert/assert.c b/efm8/lib/c8051f380/efm8_assert/assert.c
new file mode 100644
index 0000000..b9a65c7
--- /dev/null
+++ b/efm8/lib/c8051f380/efm8_assert/assert.c
@@ -0,0 +1,12 @@
+/**************************************************************************//**
+ * 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()
+{
+ while ( 1 );
+}
+#endif
diff --git a/efm8/lib/c8051f380/efm8_assert/assert.h b/efm8/lib/c8051f380/efm8_assert/assert.h
new file mode 100644
index 0000000..5b951a5
--- /dev/null
+++ b/efm8/lib/c8051f380/efm8_assert/assert.h
@@ -0,0 +1,60 @@
+/******************************************************************************
+ * 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();
+ //Yes this is smaller than if(!expr){assert}
+ #define SLAB_ASSERT(expr) if(expr){}else{slab_Assert();}
+ #endif
+#endif
+
+#endif //!__ASSERT_H__
diff --git a/efm8/lib/c8051f380/efm8_usb/Readme.txt b/efm8/lib/c8051f380/efm8_usb/Readme.txt
new file mode 100644
index 0000000..8bcff83
--- /dev/null
+++ b/efm8/lib/c8051f380/efm8_usb/Readme.txt
@@ -0,0 +1,63 @@
+-------------------------------------------------------------------------------
+ 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, EFM8UB3, EFM8UB4, 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.
+
+Version 1.0.2
+ - Added ability to detect short OUT packet in Isochronous mode and
+ stuff the buffer with zeroes to keep isochronous stream in sync.
+
+Version 1.0.3
+ - Added support for EFM8UB3 and EFM8UB4 devices.
+
+-------------------------------------------------------------------------------
+ End Of File
+-------------------------------------------------------------------------------
diff --git a/efm8/lib/c8051f380/efm8_usb/inc/efm8_usb.h b/efm8/lib/c8051f380/efm8_usb/inc/efm8_usb.h
new file mode 100644
index 0000000..fe70a9c
--- /dev/null
+++ b/efm8/lib/c8051f380/efm8_usb/inc/efm8_usb.h
@@ -0,0 +1,2325 @@
+/***************************************************************************//**
+ * Copyright (c) 2015 by Silicon Laboratories Inc. All rights reserved.
+ *
+ * http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt
+ ******************************************************************************/
+
+#ifndef __SILICON_LABS_EFM8_USB_H__
+#define __SILICON_LABS_EFM8_USB_H__
+
+#include "si_toolchain.h"
+#include "usbconfig.h"
+#include
+#include
+#include
+#include
+
+/***************************************************************************//**
+ * @addtogroup Efm8_usb
+ * @brief USB Device Protocol Stack for EFM8 devices
+ * @{
+ *
+ * @section usb_device_contents Contents
+ *
+ * @li @ref usb_device_library_revision
+ * @li @ref usb_device_intro
+ * @li @ref usb_device_api
+ * @li @ref usb_device_conf
+ * @li @ref usb_device_powersave
+ * @li @ref usb_device_transfers
+ * @li @ref usb_device_pitfalls
+ *
+ * @n @section usb_device_library_revision EFM8 USB Library Revision
+ * Library Revision: 1.0.3
+ *
+ * @n @section usb_device_intro Introduction
+ *
+ * The USB device protocol stack provides an API which makes it possible to
+ * create USB devices with a minimum of effort. The device stack supports Control,
+ * Bulk, Interrupt, and Isochronous transfers.
+ *
+ * The stack is highly configurable to suit various needs and includes
+ * demonstration projects to get you started fast.
+ *
+ * We recommend that you read through this documentation, then proceed to build
+ * and test a few example projects before you start designing your own device.
+ *
+ * @n @section usb_library_architecture_diagram Library Architecture Diagram
+ *
+ * @image html USB_Library_Architecture.png
+ *
+ * @n @section usb_device_api The EFM8 USB Library API
+ *
+ * This section contains brief descriptions of the functions in the API. You will
+ * find detailed information on input and output parameters and return values by
+ * clicking on the hyper-linked function names. It is also a good idea to study
+ * the code in the USB demonstration projects.
+ *
+ * Your application code must include one header file: @em efm8_usb.h.
+ *
+ * All functions defined in the API can be called from within interrupt handlers.
+ *
+ * @subsection usb_device_api_functions API Functions
+ *
+ * @ref USBD_Init() @n
+ * This function is called to register your device and all its properties with
+ * the device stack. The application must fill in a @ref USBD_Init_TypeDef
+ * structure prior to calling. When this function has been called your device
+ * is ready to be enumerated by the USB host.
+ *
+ * @ref USBD_Read(), @ref USBD_Write() @n
+ * These functions initiate data transfers.
+ * @n @htmlonly USBD_Read() @endhtmlonly initiate a transfer of data @em
+ * from host @em to device (an @em OUT transfer in USB terminology).
+ * @n @htmlonly USBD_Write() @endhtmlonly initiate a transfer of data @em from
+ * device @em to host (an @em IN transfer).
+ *
+ * When the USB host actually performs the transfer, your application will be
+ * notified by means of a call to the @ref USBD_XferCompleteCb() callback
+ * function (optionally). Refer to @ref TransferCallback for details of the
+ * callback functionality.
+ *
+ * @ref USBD_AbortTransfer(), @ref USBD_AbortAllTransfers() @n
+ * These functions terminate transfers that are initiated with @htmlonly
+ * USBD_Read() or USBD_Write() @endhtmlonly but that have not completed yet.
+ * These functions will deactivate the transfer setup to make the USB device
+ * endpoint hardware ready for new (and potentially) different transfers.
+ *
+ * @ref USBD_Connect(), @ref USBD_Disconnect() @n
+ * These functions turn the data-line (D+ or D-) pull-up on or off. They can
+ * be used to force re-enumeration. It's good practice to delay at least one
+ * second between @htmlonly USBD_Disconnect() and USBD_Connect() @endhtmlonly
+ * to allow the USB host to unload the currently active device driver.
+ *
+ * @ref USBD_EpIsBusy() @n
+ * Checks if an endpoint is busy.
+ *
+ * @ref USBD_StallEp(), @ref USBD_UnStallEp() @n
+ * These functions stall or un-stall an endpoint. This functionality may not
+ * be needed by your application. They may be useful when implementing some
+ * USB classes, e.g. a mass storage devices use them extensively.
+ *
+ * @ref USBD_Stop() @n
+ * Removes the data-line (D+ or D-) pull-up and disables the USB block. The
+ * application should call @htmlonly USBD_Init() after calling
+ * USBD_Stop() @endhtmlonly to restart USB operation.
+ *
+ * @ref USBD_Suspend() @n
+ * Puts the device in its low-power suspend mode. This function will not exit
+ * until a wakeup event (resume signaling, VBUS attachment/removal, or remote
+ * wakeup source interrupt) occurs. The USB Library can be configured to
+ * automatically call this function by configuring @ref SLAB_USB_PWRSAVE_MODE.
+ *
+ * @ref USBD_RemoteWakeup() @n
+ * Used in SUSPENDED state (see @ref USB_Status_TypeDef) to signal resume to
+ * host. The function will be called automatically by the library if the
+ * @ref USBD_RemoteWakeupCb() function returns true. The function will
+ * also check that the host has sent a SET_FEATURE request to enable Remote
+ * Wakeup before issuing the resume.
+ *
+ * @ref USBD_GetUsbState() @n
+ * Returns the device USB state (see @ref USBD_State_TypeDef). Refer to
+ * Figure 9-1. "Device State Diagram" in the USB revision 2.0 specification.
+ *
+ * @ref USBD_Run() @n
+ * When @ref SLAB_USB_POLLED_MODE is set to 1, the USB interrupt is disabled
+ * and the application must periodically call @htmlonly USBD_Run()
+ * @endhtmlonly to handle USB events.
+ *
+ * @n @subsection usb_device_api_callback Callback Functions
+ *
+ * @subsubsection usb_device_api_mandatory_callbacks Mandatory Callback Functions
+ *
+ * @n @anchor TransferCallback
+ * @ref USBD_XferCompleteCb() is called each time a packet is sent or
+ * received. It is called with three parameters, the status of the transfer,
+ * the number of bytes transferred and the number of bytes remaining. The
+ * transfer complete callback can be enabled or disabled by setting the
+ * callback parameters of @ref USBD_Write() and @ref USBD_Read() to
+ * true or false.
+ * @note This callback is called from within the USB interrupt handler if
+ * @ref SLAB_USB_POLLED_MODE is set to 1. Otherwise, it is called from
+ * @ref USBD_Run().
+ *
+ * @n
+ * @subsubsection usb_device_api_optional_callbacks Optional Callback Functions
+ *
+ * @n These callbacks are all optional, and it is up to the application
+ * programmer to decide if the application needs the functionality they
+ * provide. Each callback is enabled or disabled by setting a constant in
+ * usbconfig.h.
+ * @note These callbacks are called from within the USB interrupt handler if
+ * @ref SLAB_USB_POLLED_MODE is set to 1. Otherwise, they are called
+ * from @ref USBD_Run().
+ *
+ * @n USBD_ResetCb() is called each time reset signaling is sensed on the USB
+ * wire.
+ *
+ * @n USBD_SofCb() is called with the frame number as a parameter on each SOF
+ * interrupt.
+ *
+ * @n USBD_DeviceStateChangeCb() is called whenever the device state changes.
+ * Some uses of this include detecting that a USB suspend has been issued
+ * in order to reduce current consumption or calling USBD_Read() after
+ * entering the Configured state. The USB HID keyboard example
+ * project has a good example on how to use this callback.
+ *
+ * @n USBD_IsSelfPoweredCb() is called by the device stack when host
+ * queries the device with a GET_STATUS command to check if the device is
+ * currently self-powered or bus-powered. This feature is only applicable on
+ * self-powered devices which can also operate when only bus power is
+ * available.
+ *
+ * @n USBD_SetupCmdCb() is called each time a setup command is received from
+ * the host. Use this callback to override or extend the default handling of
+ * standard setup commands, and to implement class- or vendor-specific setup
+ * commands. The USB HID keyboard example project has a good example of how
+ * to use this callback.
+ *
+ * @n @section usb_device_conf Configuring the Library
+ *
+ * Your application must provide a header file named @em usbconfig.h. This file
+ * must contain the following \#define's. See @ref usb_config for
+ * documentation of these constants.@n @n
+ * @code
+ * // -----------------------------------------------------------------------------
+ * // Specify bus- or self-powered
+ * // -----------------------------------------------------------------------------
+ * #define SLAB_USB_BUS_POWERED 0
+ *
+ * // -----------------------------------------------------------------------------
+ * // Specify USB speed
+ * // -----------------------------------------------------------------------------
+ * #define SLAB_USB_FULL_SPEED 1
+ *
+ * // -----------------------------------------------------------------------------
+ * // Enable or disable the clock recovery
+ * // -----------------------------------------------------------------------------
+ * #define SLAB_USB_CLOCK_RECOVERY_ENABLED 1
+ *
+ * // -----------------------------------------------------------------------------
+ * // Enable or disable remote wakeup
+ * // -----------------------------------------------------------------------------
+ * #define SLAB_USB_REMOTE_WAKEUP_ENABLED 0
+ *
+ * // -----------------------------------------------------------------------------
+ * // Specify number of interfaces and whether any interfaces support alternate
+ * // settings
+ * // -----------------------------------------------------------------------------
+ * #define SLAB_USB_NUM_INTERFACES 1
+ * #define SLAB_USB_SUPPORT_ALT_INTERFACES 0
+ *
+ * // -----------------------------------------------------------------------------
+ * // Enable or disable each endpoint
+ * // -----------------------------------------------------------------------------
+ * #define SLAB_USB_EP1IN_USED 1
+ * #define SLAB_USB_EP1OUT_USED 0
+ * #define SLAB_USB_EP2IN_USED 0
+ * #define SLAB_USB_EP2OUT_USED 0
+ * #define SLAB_USB_EP3IN_USED 0
+ * #define SLAB_USB_EP3OUT_USED 0
+ *
+ * // -----------------------------------------------------------------------------
+ * // Specify the maximum packet size for each endpoint
+ * // -----------------------------------------------------------------------------
+ * #define SLAB_USB_EP1IN_MAX_PACKET_SIZE 64
+ * #define SLAB_USB_EP1OUT_MAX_PACKET_SIZE 0
+ * #define SLAB_USB_EP2IN_MAX_PACKET_SIZE 0
+ * #define SLAB_USB_EP2OUT_MAX_PACKET_SIZE 0
+ * #define SLAB_USB_EP3IN_MAX_PACKET_SIZE 0
+ * #define SLAB_USB_EP3OUT_MAX_PACKET_SIZE 0
+ *
+ * // -----------------------------------------------------------------------------
+ * // Specify transfer type of each endpoint
+ * // -----------------------------------------------------------------------------
+ * #define SLAB_USB_EP1IN_TRANSFER_TYPE USB_EPTYPE_INTR
+ * #define SLAB_USB_EP1OUT_TRANSFER_TYPE USB_EPTYPE_BULK
+ * #define SLAB_USB_EP2IN_TRANSFER_TYPE USB_EPTYPE_INTR
+ * #define SLAB_USB_EP2OUT_TRANSFER_TYPE USB_EPTYPE_BULK
+ * #define SLAB_USB_EP3IN_TRANSFER_TYPE USB_EPTYPE_ISOC
+ * #define SLAB_USB_EP3OUT_TRANSFER_TYPE USB_EPTYPE_ISOC
+ *
+ * // -----------------------------------------------------------------------------
+ * // Enable or disable callback functions
+ * // -----------------------------------------------------------------------------
+ * #define SLAB_USB_RESET_CB 1
+ * #define SLAB_USB_SOF_CB 1
+ * #define SLAB_USB_STATE_CHANGE_CB 1
+ * #define SLAB_USB_IS_SELF_POWERED_CB 1
+ * #define SLAB_USB_SETUP_CMD_CB 1
+ * #define SLAB_USB_HANDLER_CB 0
+ *
+ * // -----------------------------------------------------------------------------
+ * // Specify number of languages supported by string descriptors
+ * // -----------------------------------------------------------------------------
+ * #define SLAB_USB_NUM_LANGUAGES 1
+ *
+ * // -----------------------------------------------------------------------------
+ * // If only one descriptor language is supported, specify that language here.
+ * // If multiple descriptor languages are supported, this value is ignored and
+ * // the supported languages must listed in the
+ * // myUsbStringTableLanguageIDsDescriptor structure.
+ * // -----------------------------------------------------------------------------
+ * #define SLAB_USB_LANGUAGE USB_LANGID_ENUS
+ *
+ * // -----------------------------------------------------------------------------
+ * // Enable use of UTF-8 strings for string descriptors.
+ * // If this option is enabled then packed string descriptors that are created
+ * // with UTF8_PACKED_STATIC_CONST_STRING_DESC() can be UTF-8 encoded and they
+ * // will be decoded into UCS-2 16-bit wide character format used for USB string
+ * // descriptors. If this feature is not needed then it can be disabled to save
+ * // some code memory space.
+ * // -----------------------------------------------------------------------------
+ * #define SLAB_USB_UTF8_STRINGS 1
+ *
+ * // -----------------------------------------------------------------------------
+ * // Set the power saving mode
+ * //
+ * // SLAB_USB_PWRSAVE_MODE configures when the device will automatically enter
+ * // the USB power-save mode. It is a bitmask constant with bit values:
+ * //
+ * // USB_PWRSAVE_MODE_OFF - No energy saving mode selected
+ * // USB_PWRSAVE_MODE_ONSUSPEND - Enter USB power-save mode on USB suspend
+ * // USB_PWRSAVE_MODE_ONVBUSOFF - Enter USB power-save mode when not attached
+ * // to the USB host.
+ * // USB_PWRSAVE_MODE_FASTWAKE - Exit USB power-save mode more quickly, but
+ * // consume more power while in USB power-save
+ * // mode.
+ * // While the device is in USB power-save mode
+ * // (typically during USB suspend), the
+ * // internal voltage regulator stays in normal
+ * // power mode instead of entering suspend
+ * // power mode.
+ * // This is an advanced feature that may be
+ * // useful in certain applications that support
+ * // remote wakeup.
+ * // -----------------------------------------------------------------------------
+ * #define SLAB_USB_PWRSAVE_MODE (USB_PWRSAVE_MODE_ONVBUSOFF \
+ * | USB_PWRSAVE_MODE_ONSUSPEND)
+ *
+ * // -----------------------------------------------------------------------------
+ * // Enable or disable polled mode
+ * //
+ * // When enabled, the application must call USBD_Run() periodically to process
+ * // USB events.
+ * // When disabled, USB events will be handled automatically by an interrupt
+ * // handler.
+ * // -----------------------------------------------------------------------------
+ * #define SLAB_USB_POLLED_MODE 0
+ * @endcode
+ *
+ * @n @section usb_device_powersave Energy-saving options
+ *
+ * The device stack provides built-in energy saving options.These options
+ * are configured by setting flags in @ref SLAB_USB_PWRSAVE_MODE in @em
+ * usbconfig.h. These flags are bitmasks and can be or'd together.@n@n
+ *
+ * Energy-Saving Option Flags:
+ *
+ * @ref USB_PWRSAVE_MODE_OFF@n The device will not automatically enter its
+ * low-power suspned mode after detecting a USB suspend. The application
+ * firmware may still call @ref USBD_Suspend() to manually enter suspend mode.
+ *
+ * @ref USB_PWRSAVE_MODE_ONSUSPEND@n Enter a low-power suspend mode
+ * when a USB suspend is detected. When resume signaling is detected,
+ * the stack will exit the low-power mode.
+ *
+ * @ref USB_PWRSAVE_MODE_ONVBUSOFF@n Enter the low-power suspend
+ * mode any time the device detects that VBUS is not present. When VBUS is
+ * attached, the stack will exit the low-power mode. The USB Specification
+ * does not define the state of the device when VBUS is not present, but it
+ * may be desirable for some applications to enter suspend mode when in this
+ * undefined state.
+ *
+ * @ref USB_PWRSAVE_MODE_FASTWAKE@n Keep the internal regulator at
+ * its normal operating state while in the low-power suspend state. This
+ * allows the device to wake from suspend more quickly than it would from its
+ * suspend state. This option can be useful in applications that support
+ * remote wakeup and need to exit suspend in time to recognize some external
+ * signal (i.e. a byte received on the UART). The device will still consume
+ * low enough power to meet the USB Suspend Current Specification, but it will
+ * be slightly higher than it would otherwise be.
+ *
+ * The USB HID Keyboard device example project demonstrates some of these
+ * energy-saving options.
+ *
+ * Example:
+ * Leave all energy saving to the stack, the device enters low-power mode on
+ * suspend and when detached from host. @n
+ * In usbconfig.h:
+ * @code
+ * #define SLAB_USB_PWRSAVE_MODE (USB_PWRSAVE_MODE_ONSUSPEND | USB_PWRSAVE_MODE_ONVBUSOFF)
+ * @endcode
+ *
+ * @n @section usb_device_transfers Transfer Operation
+ *
+ * @subsection usb_device_transfers_overview Overview
+ *
+ * A USB transfer consists of one or more packets. For an IN transfer, the
+ * packets are sent from the device to the host. For an OUT transfer, the
+ * packets are sent from the host to the device. @ref USBD_Write() initiates
+ * an IN transfer, while @ref USBD_Read() initiates an OUT transfer.
+ *
+ * @subsection usb_device_transfers_types Transfer Types
+ *
+ * There are four USB transfer types: @ref usb_device_transfer_types_control,
+ * @ref usb_device_transfer_types_bulk, @ref usb_device_transfer_types_interrupt,
+ * and @ref usb_device_transfer_types_isochronous.
+ *
+ * @subsubsection usb_device_transfer_types_control Control
+ *
+ * Control transfers are used to send configuration and status
+ * information, and also to send vendor-defined data. The USB Library only
+ * supports control transfers on Endpoint 0. @n @n
+ * The application firmware can handle control requests by looking at the
+ * contents of the setup packet in @ref USBD_SetupCmdCb(). If the application
+ * supports a particular request, it can call @ref USBD_Read() or @ref
+ * USBD_Write() with epAddr set to EP0 and return @ref
+ * USB_STATUS_OK. If it does not need to handle the request, it should return
+ * @ref USB_STATUS_REQ_UNHANDLED. This will notify the library that it should
+ * try to handle the setup command. The library will automatically service
+ * Standard (i.e. Chapter 9) requests, so @ref USBD_SetupCmdCb() should return
+ * @ref USB_STATUS_REQ_UNHANDLED unless it is a class- or vendor-specific
+ * request. If neither the library nor the application supports a setup
+ * request, the library will issue a stall.
+ *
+ * @subsubsection usb_device_transfer_types_bulk Bulk
+ *
+ * Bulk transfers are used to send large, non-periodic data. Examples include
+ * sending a file to a Mass Storage Device or a print-job to a printer. A bulk
+ * transfer may consist of one or more packets.
+ *
+ * Endpoints are configured for bulk mode in usbconfig.h. As an
+ * example: @code
+ * #define SLAB_USB_EP1OUT_TRANSFER_TYPE USB_EPTYPE_BULK@endcode
+ * configures Endpout 1 OUT transfers for bulk mode.
+ *
+ * The @ref byteCount parameter of @ref USBD_Write() and @ref USBD_Read()
+ * configures the maximum length for a given bulk transfer. The transfer will
+ * complete when the device sends or receives either:
+ * 1. A packet less than its maximum packet size
+ * 2. Exactly the number of bytes specified in @ref byteCount
+ * Note that @ref USBD_XferCompleteCb() will be called for each packet sent or
+ * received for the duration of a transfer.
+ *
+ * @subsubsection usb_device_transfer_types_interrupt Interrupt
+ *
+ * Interrupt transfers are used to send low-bandwidth, hight-latency data at
+ * a non-periodic rate. Examples include input devices, such as mice,
+ * keyboards, and joysticks. An interrupt transfer may consist of one or more
+ * packets.
+ *
+ * Endpoints are configured for interrupt mode in usbconfig.h. As an
+ * example: @code
+ * #define SLAB_USB_EP1OUT_TRANSFER_TYPE USB_EPTYPE_INTR@endcode
+ * configures Endpout 1 OUT transfers for interrupt mode.
+ *
+ * Interrupt transfers work identically to bulk transfer in the USB Library.
+ * Refer to @ref usb_device_transfer_types_bulk for more information.
+ *
+ * @subsubsection usb_device_transfer_types_isochronous Isochronous
+ *
+ * Isochronous transfers are used to send periodic, continuous data. Automatic
+ * error-checking is not included with isochronous transfers as it is with all
+ * other transfer types. Examples include streaming audio and video. As
+ * isochronous data is sent at a continuous rate, it typically consists of
+ * one IN and/or OUT packet per frame.
+ *
+ * Endpoint 3 is the only endpoint in the USB Library that supports
+ * isochronous transfers. Endpoints are configured for isochronous mode in
+ * usbconfig.h. As an example: @code
+ * #define SLAB_USB_EP3OUT_TRANSFER_TYPE USB_EPTYPE_ISOC@endcode
+ * configures Endpout 3 OUT transfers for isochronous mode.
+ *
+ * The library works differently for isochronous transfers. The application
+ * must define a circular buffer to hold isochronous data. When calling
+ * USBD_Read() or USBD_Write(), dat is the first address of this
+ * buffer and byteCount is its length. The library will read from or
+ * write to this buffer as soon as the host issues a request, so it is the
+ * responsibility of the application firmware to ensure that this buffer is
+ * fed or consumed at the correct rate to prevent an underrun/overrun
+ * condition.
+ *
+ * The parameters of @ref USBD_XferCompleteCb() take on a different meaning in
+ * isochronous mode. For OUT transfers, xferred is the number of
+ * bute received in the last packet and remaining is the current
+ * index into the circular buffer. For IN transfers, xferred is
+ * ignored, remaining is the current index into the circular buffer,
+ * and the return value is the number of bytes to transmit in the next
+ * packet.
+ *
+ * @n @section usb_device_pitfalls Pitfalls
+ *
+ * @subsection usb_device_pitfalls_nonreentrancy Non-Reentrancy
+ *
+ * Due to the non-reentrant architecture of the 8051, it is recommended
+ * that all calls to a particular API function be made from functions of the
+ * same interrupt priority (main loop, low priority, or high priority).
+ *
+ * The interrupt priority of the USB callback functions is determined by the
+ * constant @ref SLAB_USB_POLLED_MODE. When 0, the callbacks are called from
+ * the USB Interrupt Handler. When 1, the callbacks are called from
+ * USBD_Run(), which is typically called from the main loop.
+ * If an API function must be called from functions of differing interrupt
+ * priorities, there are a number of ways to ensure that the calls are made
+ * safely:
+ *
+ * 1. Disable the interrupt source of the higher-priority function before
+ * making the call. Restore the interrupt enable setting after the call
+ * returns:
+ *
+ * (Assuming @htmlonly USBD_Write() is called from main() and
+ * USBD_XferCompleteCb() @endhtmlonly, the call from main() should
+ * disable and restore the USB interrupt):
+ * @code
+ * bool usbIntsEnabled = USB_GetIntsEnabled();
+ *
+ * USB_DisableInts();
+ *
+ * USBD_Write(EP1IN, myBuf, 1, true);
+ *
+ * if (usbIntsEnabled)
+ * {
+ * USB_EnableInts();
+ * }
+ * @endcode
+ *
+ * 2. Add the compiler-specific reentrant keyword to the function
+ * definition(s) in efm8_usbd.c:
+ * @code
+ * int8_t USBD_AbortTransfer(uint8_t epAddr) reentrant
+ * @endcode
+ * and to the function prototype definition(s) in efm8_usb.h:
+ * @code
+ * int8_t USBD_AbortTransfer(uint8_t epAddr) reentrant;
+ * @endcode
+ * Using the reentrant keyword may require the application to provide
+ * a heap for local variable allocation. Additionally, it will reduce
+ * the performance and increase the code size of the modified function.
+ * 3. Make a copy of the function(s) and rename it. Call the original
+ * function in once context, and the renamed version in another.
+ *
+ * @subsection usb_device_pitfalls_buffer_allocation Buffer Allocation
+ *
+ * Dynamically allocated buffers passed to @ref USBD_Write() and @ref
+ * USBD_Read() must not be freed until the transfer completes.
+ *
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @addtogroup efm8_usb_constants Constants
+ * @{
+ ******************************************************************************/
+
+// -----------------------------------------------------------------------------
+// Global Constants
+
+// SETUP request, direction of data stage
+#define USB_SETUP_DIR_OUT 0 ///< Setup request data stage OUT direction value.
+#define USB_SETUP_DIR_IN 1 ///< Setup request data stage IN direction value.
+#define USB_SETUP_DIR_MASK 0x80 ///< Setup request data stage direction mask.
+#define USB_SETUP_DIR_D2H 0x80 ///< Setup request data stage IN direction mask.
+#define USB_SETUP_DIR_H2D 0x00 ///< Setup request data stage OUT direction mask.
+
+// SETUP request type
+#define USB_SETUP_TYPE_STANDARD 0 ///< Standard setup request value.
+#define USB_SETUP_TYPE_CLASS 1 ///< Class setup request value.
+#define USB_SETUP_TYPE_VENDOR 2 ///< Vendor setup request value.
+#define USB_SETUP_TYPE_STANDARD_MASK 0x00 ///< Standard setup request mask.
+#define USB_SETUP_TYPE_CLASS_MASK 0x20 ///< Class setup request mask.
+#define USB_SETUP_TYPE_VENDOR_MASK 0x40 ///< Vendor setup request mask.
+
+// SETUP request recipient
+#define USB_SETUP_RECIPIENT_DEVICE 0 ///< Setup request device recipient value.
+#define USB_SETUP_RECIPIENT_INTERFACE 1 ///< Setup request interface recipient value.
+#define USB_SETUP_RECIPIENT_ENDPOINT 2 ///< Setup request endpoint recipient value.
+#define USB_SETUP_RECIPIENT_OTHER 3 ///< Setup request other recipient value.
+
+// bmRequestType bitmasks
+#define USB_BMREQUESTTYPE_RECIPIENT 0x1F ///< Recipient is bmRequestType[4:0]
+#define USB_BMREQUESTTYPE_TYPE 0x60 ///< Type is bmRequestType[6:5]
+#define USB_BMREQUESTTYPE_DIRECTION 0x80 ///< Recipient is bmRequestType[7]
+
+// SETUP standard request codes for Full Speed devices
+#define GET_STATUS 0 ///< Standard setup request GET_STATUS.
+#define CLEAR_FEATURE 1 ///< Standard setup request CLEAR_FEATURE.
+#define SET_FEATURE 3 ///< Standard setup request SET_FEATURE.
+#define SET_ADDRESS 5 ///< Standard setup request SET_ADDRESS.
+#define GET_DESCRIPTOR 6 ///< Standard setup request GET_DESCRIPTOR.
+#define SET_DESCRIPTOR 7 ///< Standard setup request SET_DESCRIPTOR.
+#define GET_CONFIGURATION 8 ///< Standard setup request GET_CONFIGURATION.
+#define SET_CONFIGURATION 9 ///< Standard setup request SET_CONFIGURATION.
+#define GET_INTERFACE 10 ///< Standard setup request GET_INTERFACE.
+#define SET_INTERFACE 11 ///< Standard setup request SET_INTERFACE.
+#define SYNCH_FRAME 12 ///< Standard setup request SYNCH_FRAME.
+
+// SETUP class request codes
+#define USB_HID_GET_REPORT 0x01 ///< HID class setup request GET_REPORT.
+#define USB_HID_GET_IDLE 0x02 ///< HID class setup request GET_IDLE.
+#define USB_HID_SET_REPORT 0x09 ///< HID class setup request SET_REPORT.
+#define USB_HID_SET_IDLE 0x0A ///< HID class setup request SET_IDLE.
+#define USB_HID_SET_PROTOCOL 0x0B ///< HID class setup request SET_PROTOCOL.
+#define USB_CDC_SETLINECODING 0x20 ///< CDC class setup request SET_LINE_CODING.
+#define USB_CDC_GETLINECODING 0x21 ///< CDC class setup request GET_LINE_CODING.
+#define USB_CDC_SETCTRLLINESTATE 0x22 ///< CDC class setup request SET_CONTROL_LINE_STATE.
+#define USB_MSD_BOTRESET 0xFF ///< MSD class setup request Bulk only transfer reset.
+#define USB_MSD_GETMAXLUN 0xFE ///< MSD class setup request Get Max LUN.
+
+// SETUP command GET/SET_DESCRIPTOR descriptor types
+#define USB_DEVICE_DESCRIPTOR 1 ///< DEVICE descriptor value.
+#define USB_CONFIG_DESCRIPTOR 2 ///< CONFIGURATION descriptor value.
+#define USB_STRING_DESCRIPTOR 3 ///< STRING descriptor value.
+#define USB_INTERFACE_DESCRIPTOR 4 ///< INTERFACE descriptor value.
+#define USB_ENDPOINT_DESCRIPTOR 5 ///< ENDPOINT descriptor value.
+#define USB_DEVICE_QUALIFIER_DESCRIPTOR 6 ///< DEVICE_QUALIFIER descriptor value.
+#define USB_OTHER_SPEED_CONFIG_DESCRIPTOR 7 ///< OTHER_SPEED_CONFIGURATION descriptor value.
+#define USB_INTERFACE_POWER_DESCRIPTOR 8 ///< INTERFACE_POWER descriptor value.
+#define USB_HUB_DESCRIPTOR 0x29 ///< HUB descriptor value.
+#define USB_HID_DESCRIPTOR 0x21 ///< HID descriptor value.
+#define USB_HID_REPORT_DESCRIPTOR 0x22 ///< HID REPORT descriptor value.
+#define USB_CS_INTERFACE_DESCRIPTOR 0x24 ///< Audio Class-specific Descriptor Type.
+
+#define USB_DEVICE_DESCSIZE 18 ///< Device descriptor size.
+#define USB_CONFIG_DESCSIZE 9 ///< Configuration descriptor size.
+#define USB_INTERFACE_DESCSIZE 9 ///< Interface descriptor size.
+#define USB_ENDPOINT_DESCSIZE 7 ///< Endpoint descriptor size.
+#define USB_DEVICE_QUALIFIER_DESCSIZE 10 ///< Device qualifier descriptor size.
+#define USB_OTHER_SPEED_CONFIG_DESCSIZE 9 ///< Device other speed configuration descriptor size.
+#define USB_HID_DESCSIZE 9 ///< HID descriptor size.
+#define USB_CDC_HEADER_FND_DESCSIZE 5 ///< CDC Header functional descriptor size.
+#define USB_CDC_CALLMNG_FND_DESCSIZE 5 ///< CDC Call Management functional descriptor size.
+#define USB_CDC_ACM_FND_DESCSIZE 4 ///< CDC Abstract Control Management functional descriptor size.
+
+// String descriptor locations
+#define USB_STRING_DESCRIPTOR_ENCODING 0 ///< Denotes whether string descriptor is UTF-8 or binary
+#define USB_STRING_DESCRIPTOR_LENGTH 1 ///< Length of string descriptor
+#define USB_STRING_DESCRIPTOR_TYPE 2 ///< Type of string descriptor (USB_STRING_DESCRIPTOR)
+#define USB_STRING_DESCRIPTOR_NAME 3 ///< The string encoded as per USB_STRING_DESCRIPTOR_PACKED
+
+// String descriptor encoding types
+#define USB_STRING_DESCRIPTOR_UTF16LE 0 ///< The string is in UTF-16LE encoding
+#define USB_STRING_DESCRIPTOR_UTF16LE_PACKED 1 ///< The string is in packed UTF-16LE encoding (the 0x00
+ /// characters between ASCII characters are omitted)
+#define USB_STRING_DESCRIPTOR_UTF8 2 ///< The string is in UTF-8 encoding
+
+// Misc. USB definitions
+#define USB_FULL_EP0_SIZE 64 ///< The size of endpoint 0 at full speed.
+#define USB_FULL_INT_BULK_MAX_EP_SIZE 64 ///< The max size of any full speed bulk/interrupt endpoint.
+#define USB_FULL_ISOC_MAX_EP_SIZE 1023 ///< The max size of any full speed isochronous endpoint.
+#define USB_LOW_EP0_SIZE 8 ///< The size of endpoint 0 at low speed.
+#define USB_LOW_INT_BULK_MAX_EP_SIZE 8 ///< The max size of any low speed bulk/interrupt endpoint.
+#define USB_LOW_ISOC_MAX_EP_SIZE 0 ///< The max size of any low speed isochronous endpoint.
+#define USB_EPTYPE_CTRL 0 ///< Endpoint type control.
+#define USB_EPTYPE_ISOC 1 ///< Endpoint type isochronous.
+#define USB_EPTYPE_BULK 2 ///< Endpoint type bulk.
+#define USB_EPTYPE_INTR 3 ///< Endpoint type interrupt.
+#define USB_EP_DIR_IN 0x80 ///< Endpoint IN direction mask.
+#define USB_EP_DIR_OUT 0x00 ///< Endponit OUT direction mask.
+#define USB_SETUP_PKT_SIZE 8 ///< Setup request packet size.
+#define USB_EPNUM_MASK 0x0F ///< Endpoint number mask.
+#define USB_LANGID_ENUS 0x0409 ///< English-United States language id.
+#define USB_LANGID_NOBO 0x0414 ///< Norwegian-Bokmal language id.
+#define USB_MAX_DEVICE_ADDRESS 127 ///< Maximum allowable device address.
+#define MAX_USB_EP_NUM 15 ///< Limit imposed by the USB standard
+#define USB_VENDOR_ID_SILICON_LABS 0x10C4 ///< Silicon Labs VID
+
+#define CONFIG_DESC_BM_REMOTEWAKEUP 0x20 ///< Configuration descriptor attribute macro.
+#define CONFIG_DESC_BM_SELFPOWERED 0x40 ///< Configuration descriptor attribute macro.
+#define CONFIG_DESC_BM_RESERVED_D7 0x80 ///< Configuration descriptor attribute macro.
+#define CONFIG_DESC_BM_TRANSFERTYPE 0x03 ///< Configuration descriptor transfer type bitmask.
+#define CONFIG_DESC_MAXPOWER_mA(x) (((x)+1)/2) ///< Configuration descriptor power macro.
+
+#define DEVICE_IS_SELFPOWERED 0x0001 ///< Standard request GET_STATUS bitmask.
+#define REMOTE_WAKEUP_ENABLED 0x0002 ///< Standard request GET_STATUS bitmask.
+#define USB_FEATURE_ENDPOINT_HALT 0 ///< Standard request CLEAR/SET_FEATURE bitmask.
+#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 ///< Standard request CLEAR/SET_FEATURE bitmask.
+
+#define HUB_FEATURE_PORT_RESET 4 ///< HUB class request CLEAR/SET_PORT_FEATURE feature selector.
+#define HUB_FEATURE_PORT_POWER 8 ///< HUB class request CLEAR/SET_PORT_FEATURE feature selector.
+#define HUB_FEATURE_C_PORT_CONNECTION 16 ///< HUB class request CLEAR/SET_PORT_FEATURE feature selector.
+#define HUB_FEATURE_C_PORT_RESET 20 ///< HUB class request CLEAR/SET_PORT_FEATURE feature selector.
+#define HUB_FEATURE_PORT_INDICATOR 22 ///< HUB class request CLEAR/SET_PORT_FEATURE feature selector.
+
+#define USB_CLASS_CDC 2 ///< CDC device/interface class code.
+#define USB_CLASS_CDC_DATA 0x0A ///< CDC Data interface class code.
+#define USB_CLASS_CDC_ACM 2 ///< CDC Abstract Control Model interface subclass code.
+#define USB_CLASS_CDC_HFN 0 ///< CDC class Header Functional Descriptor subtype.
+#define USB_CLASS_CDC_CMNGFN 1 ///< CDC class Call Management Functional Descriptor subtype.
+#define USB_CLASS_CDC_ACMFN 2 ///< CDC class Abstract Control Management Functional Descriptor subtype.
+#define USB_CLASS_CDC_UNIONFN 6 ///< CDC class Union Functional Descriptor subtype.
+
+#define USB_CLASS_HID 3 ///< HID device/interface class code.
+#define USB_CLASS_HID_KEYBOARD 1 ///< HID keyboard interface protocol code.
+#define USB_CLASS_HID_MOUSE 2 ///< HID mouse interface protocol code.
+
+#define USB_CLASS_HUB 9 ///< HUB device/interface class code.
+
+#define USB_CLASS_MSD 8 ///< MSD device/interface class code.
+#define USB_CLASS_MSD_BOT_TRANSPORT 0x50 ///< MSD Bulk Only Transport protocol.
+#define USB_CLASS_MSD_SCSI_CMDSET 6 ///< MSD Subclass SCSI transparent command set.
+#define USB_CLASS_MSD_CSW_CMDPASSED 0 ///< MSD BOT Command status wrapper command passed code.
+#define USB_CLASS_MSD_CSW_CMDFAILED 1 ///< MSD BOT Command status wrapper command failed code.
+#define USB_CLASS_MSD_CSW_PHASEERROR 2 ///< MSD BOT Command status wrapper cmd phase error code.
+
+#define USB_CLASS_VENDOR_SPECIFIC 0xFF ///< Vendor Specific class
+#define USB_SUBCLASS_VENDOR_SPECIFIC 0xFF ///< Vendor Specific sub-class
+
+/// @brief USB power save modes
+#define USB_PWRSAVE_MODE_OFF 0 ///< No energy saving option selected.
+#define USB_PWRSAVE_MODE_ONSUSPEND 1 ///< Enter USB power-save mode on suspend.
+#define USB_PWRSAVE_MODE_ONVBUSOFF 2 ///< Enter USB power-save mode when not attached to the USB host.
+#define USB_PWRSAVE_MODE_FASTWAKE 4 ///< Exit USB power-save mode more quickly. This is useful for
+ ///< some applications that support remote wakeup.
+
+/// @brief Endpoint 0 packet size
+#if SLAB_USB_FULL_SPEED
+#define USB_EP0_SIZE USB_FULL_EP0_SIZE
+#else
+#define USB_EP0_SIZE USB_LOW_EP0_SIZE
+#endif // SLABS_USB_FULL_SPEED
+
+/// @brief Total number of USB endpoints used by the device
+#define SLAB_USB_NUM_EPS_USED (SLAB_USB_EP1IN_USED \
+ + SLAB_USB_EP1OUT_USED \
+ + SLAB_USB_EP2IN_USED \
+ + SLAB_USB_EP2OUT_USED \
+ + SLAB_USB_EP3IN_USED \
+ + SLAB_USB_EP3OUT_USED \
+ + 1)
+/** @} (end addtogroup efm8_usb_constants Constants) */
+
+/***************************************************************************//**
+ * @addtogroup efm8_usb_macros Macros
+ * @{
+ ******************************************************************************/
+
+// -----------------------------------------------------------------------------
+// Global Macros
+
+/// Macro for getting minimum value.
+#ifndef EFM8_MIN
+#define EFM8_MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+/// Macro for getting maximum value.
+#ifndef EFM8_MAX
+#define EFM8_MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef UNREFERENCED_ARGUMENT
+#if defined __C51__
+/// Macro for removing unreferenced arguments from compiler warnings
+#define UNREFERENCED_ARGUMENT(arg) (0, arg)
+#elif defined __ICC8051__
+/// Macro for removing unreferenced arguments from compiler warnings
+#define UNREFERENCED_ARGUMENT(arg) ((void)arg)
+#endif
+#endif
+
+/***************************************************************************//**
+ * @brief Macro for creating USB-compliant UTF-16LE UNICODE string
+ * descriptor from a C string.
+ * @details This macro should be used for ASCII strings in which all
+ * characters are represented by a single ASCII byte (i.e.
+ * U.S. English strings).
+ * The USB Library will expand variables created with this macro
+ * by inserting a 0x00 between each character. This allows the
+ * string to be stored in a "packed", or compressed, format.
+ * @n@n This example sends "Silicon Labs" as the Manufacturer String:
+ *
+ * #define MFR_STRING "Silicon Labs"
+ *
+ * UTF16LE_PACKED_STATIC_CONST_STRING_DESC(manufacturer[], \
+ * MFR_STRING);
+ * @param __name
+ * The name of the variable that holds the string descriptor
+ * @param __val
+ * The value of the string descriptor
+ ******************************************************************************/
+#define UTF16LE_PACKED_STATIC_CONST_STRING_DESC(__name, __val, __size) \
+ SI_SEGMENT_VARIABLE(__name, static const USB_StringDescriptor_TypeDef, SI_SEG_CODE) = \
+ { USB_STRING_DESCRIPTOR_UTF16LE_PACKED, __size * 2, USB_STRING_DESCRIPTOR, __val }
+
+/***************************************************************************//**
+ * @brief Macro for creating USB-compliant UTF-16LE UNICODE string
+ * descriptor from a UTF-8 string.
+ * @details This macro should be used for UTF-8 strings in which all
+ * characters are represented by a valid UTF-8 byte sequence
+ * of 1-3 bytes per character. The USB library will expand
+ * variables created with this macro by decoding the UTF-8
+ * sequence into 16-bit wide UCS-2 characters required for USB
+ * string descriptors.
+ * @n@n This example set an array named _manufacturer[]_ to a
+ * series of symbols: an anchor, a lightning bolt, and a
+ * fußball as the Manufacturer String:
+ *
+ * #define MFR_STRING "⚓⚡⚽"
+ *
+ * // This string has 3 Unicode characters so the __len
+ * // parameter is 3, even though it will take 3 bytes to
+ * // represent each character
+ * UTF8_PACKED_STATIC_CONST_STRING_DESC(manufacturer[], 3, \
+ * MFR_STRING);
+ * @param __name
+ * The name of the variable that holds the string descriptor
+ * @param __len
+ * Number of Unicode characters (or codepoints) in the string
+ * @param __val
+ * The value of the string descriptor
+ ******************************************************************************/
+#define UTF8_PACKED_STATIC_CONST_STRING_DESC(__name, __len, __val) \
+ SI_SEGMENT_VARIABLE(__name, static const USB_StringDescriptor_TypeDef, SI_SEG_CODE) = \
+ { USB_STRING_DESCRIPTOR_UTF8, (__len) * 2, USB_STRING_DESCRIPTOR, __val }
+
+/***************************************************************************//**
+ * @brief Macro for creating USB-compliant UTF-16LE UNICODE string
+ * descriptor from a UTF-8 string.
+ * @details This macro should be used for UTF-8 strings in which all
+ * characters are represented by a valid UTF-8 byte sequence
+ * of 1-3 bytes per character. The USB library will expand
+ * variables created with this macro by decoding the UTF-8
+ * sequence into 16-bit wide UCS-2 characters required for USB
+ * string descriptors.
+ * @n@n This example set an array named _manufacturer[]_ to a
+ * series of symbols: an anchor, a lightning bolt, and a
+ * fußball as the Manufacturer String:
+ *
+ * #define MFR_STRING "⚓⚡⚽"
+ *
+ * // This string has 3 Unicode characters so the __len
+ * // parameter is 3, even though it will take 3 bytes to
+ * // represent each character
+ * UTF8_PACKED_STATIC_CONST_STRING_DESC(manufacturer[], 3, \
+ * MFR_STRING);
+ * @param __name
+ * The name of the variable that holds the string descriptor
+ * @param __len
+ * Number of Unicode characters (or codepoints) in the string
+ * @param __val
+ * The value of the string descriptor
+ ******************************************************************************/
+#define UTF8_PACKED_STATIC_CONST_STRING_DESC(__name, __len, __val) \
+ SI_SEGMENT_VARIABLE(__name, static const USB_StringDescriptor_TypeDef, SI_SEG_CODE) = \
+ { USB_STRING_DESCRIPTOR_UTF8, (__len) * 2, USB_STRING_DESCRIPTOR, __val }
+
+/***************************************************************************//**
+ * @brief Macro for creating USB-compliant UTF-16LE UNICODE string
+ * descriptor from a C array initializer.
+ * @details This macro should be used for converting an array initializer
+ * into a string descriptor. Unlike @ref
+ * UTF16LE_PACKED_STATIC_CONST_STRING_DESC(), the library will not
+ * attempt to unpack variables created with this macro, so the
+ * array will be sent exactly as it is defined.
+ * @n@n This example sends "Mouse" as the Product String:
+ *
+ * #define PROD_STRING 'M',0,'o',0,'u',0,'s',0,'e',0
+ *
+ * ARRAY_STATIC_CONST_STRING_DESC(product[], \
+ * 10, \
+ * PROD_STRING);
+ * @param __name
+ * The name of the variable that holds the string descriptor
+ * @param __len
+ * Number of characters (including nulls) in the string to send
+ * @param __val
+ * The array initializer.
+ ******************************************************************************/
+#define ARRAY_STATIC_CONST_STRING_DESC(__name, __len, __val) \
+ SI_SEGMENT_VARIABLE(__name, static const USB_StringDescriptor_TypeDef, SI_SEG_CODE) = \
+ { USB_STRING_DESCRIPTOR_UTF16LE, __len + 2, USB_STRING_DESCRIPTOR, __val }
+
+/***************************************************************************//**
+ * @brief Macro for creating USB-compliant UTF-16LE UNICODE string
+ * descriptor from a UTF-16 C string.
+ * @details This macro should be used for strings which are already
+ * represented in UTF-16. This is an advanced option that should
+ * only be used for some foreign languages.
+ * @param __name
+ * The name of the variable that holds the string descriptor
+ * @param __val
+ * The value of the string descriptor
+ ******************************************************************************/
+#define UTF16LE_STATIC_CONST_STRING_DESC(__name, __val) \
+ SI_SEGMENT_VARIABLE(__name, static const USB_StringDescriptor_TypeDef, SI_SEG_CODE) = \
+ { USB_STRING_DESCRIPTOR_UTF16LE, sizeof(__val) + 2, USB_STRING_DESCRIPTOR, __val }
+
+/***************************************************************************//**
+ * @brief Macro for creating Language ID's String Descriptor (String
+ * Descriptor 0)
+ * @details This macro should be used to create the Language ID String
+ * Descriptor.
+ * @n@n This example USB device only support U.S. English:
+ *
+ * #define LANG_STRING htole16(SLAB_USB_LANGUAGE)
+ *
+ * LANGID_STATIC_CONST_STRING_DESC(langDesc[], LANG_STRING);
+ *
+ * This example USB device support Norwegian U.S. English:
+ *
+ * #define LANG_STRING htole16(USB_LANGID_NOBO), \
+ * htole16(USB_LANGID_ENUS)
+ *
+ * LANGID_STATIC_CONST_STRING_DESC(langDesc[], LANG_STRING);
+ *
+ * @param __name
+ * The name of the variable that holds the string descriptor
+ * @param __val
+ * The value of the string descriptor
+ ******************************************************************************/
+#define LANGID_STATIC_CONST_STRING_DESC(__name, __val) \
+ SI_SEGMENT_VARIABLE(__name, static const USB_LangId_StringDescriptor_Typedef, SI_SEG_CODE) = \
+ { htole16(((SLAB_USB_NUM_LANGUAGES * 2) + 2) + (USB_STRING_DESCRIPTOR << 8)), __val }
+
+/** @} (end addtogroup efm8_usb_macros Macros) */
+
+/***************************************************************************//**
+ * @addtogroup efm8_usb_typedefs Typedefs
+ * @{
+ ******************************************************************************/
+
+// -----------------------------------------------------------------------------
+// Typedefs
+
+/// @brief USB transfer status enumerator.
+typedef enum
+{
+ USB_STATUS_OK = 0, ///< No errors detected.
+ USB_STATUS_REQ_ERR = -1, ///< Setup request error.
+ USB_STATUS_EP_BUSY = -2, ///< Endpoint is busy.
+ USB_STATUS_REQ_UNHANDLED = -3, ///< Setup request not handled.
+ USB_STATUS_ILLEGAL = -4, ///< Illegal operation attempted.
+ USB_STATUS_EP_STALLED = -5, ///< Endpoint is stalled.
+ USB_STATUS_EP_ABORTED = -6, ///< Endpoint transfer was aborted.
+ USB_STATUS_EP_ERROR = -7, ///< Endpoint transfer error.
+ USB_STATUS_EP_NAK = -8, ///< Endpoint NAK'ed transfer request.
+ USB_STATUS_DEVICE_UNCONFIGURED = -9, ///< Device is unconfigured.
+ USB_STATUS_DEVICE_SUSPENDED = -10, ///< Device is suspended.
+ USB_STATUS_DEVICE_RESET = -11, ///< Device is/was reset.
+ USB_STATUS_TIMEOUT = -12, ///< Transfer timeout.
+ USB_STATUS_DEVICE_REMOVED = -13, ///< Device was removed.
+ USB_STATUS_EP_RX_BUFFER_OVERRUN = -14, ///< Not enough data in the Rx buffer to hold the
+ USB_STATUS_DATA_ERROR = -15, ///< OUT packet had CRC or bit-stuffing error
+ ///< last received packet
+} USB_Status_TypeDef;
+
+/// @brief USB device state enumerator.
+typedef enum
+{
+ USBD_STATE_NONE = 0, ///< Device state is undefined/unknown.
+ USBD_STATE_ATTACHED = 1, ///< Device state is ATTACHED.
+ USBD_STATE_POWERED = 2, ///< Device state is POWERED.
+ USBD_STATE_DEFAULT = 3, ///< Device state is DEFAULT.
+ USBD_STATE_ADDRESSED = 4, ///< Device state is ADDRESSED.
+ USBD_STATE_SUSPENDED = 5, ///< Device state is SUSPENDED.
+ USBD_STATE_CONFIGURED = 6, ///< Device state is CONFIGURED.
+ USBD_STATE_LASTMARKER = 7, ///< Device state enum end marker.
+} USBD_State_TypeDef;
+
+/// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
+/// @brief Endpoint states
+typedef enum
+{
+ D_EP_DISABLED = 0, ///< Endpoint is disabled
+ D_EP_IDLE = 1, ///< Endpoint is idle
+ D_EP_TRANSMITTING = 2, ///< Endpoint is transmitting data
+ D_EP_RECEIVING = 3, ///< Endpoint is receiving data
+ D_EP_STATUS = 4, ///< Endpoint is in status stage
+ D_EP_STALL = 5, ///< Endpoint is stalling
+ D_EP_HALT = 6, ///< Endpoint is halted
+ D_EP_LASTMARKER = 7 ///< End of EpState enum
+} USBD_EpState_TypeDef;
+/// @endcond DO_NOT_INCLUDE_WITH_DOXYGEN
+
+/// @brief Endpoint access address
+typedef enum
+{
+ EP0,
+#if (SLAB_USB_EP1IN_USED)
+ EP1IN,
+#endif
+#if (SLAB_USB_EP2IN_USED)
+ EP2IN,
+#endif
+#if (SLAB_USB_EP3IN_USED)
+ EP3IN,
+#endif
+#if (SLAB_USB_EP1OUT_USED)
+ EP1OUT,
+#endif
+#if (SLAB_USB_EP2OUT_USED)
+ EP2OUT,
+#endif
+#if (SLAB_USB_EP3OUT_USED)
+ EP3OUT,
+#endif
+} USB_EP_Index_TypeDef;
+
+/// @brief USB Setup type.
+typedef struct
+{
+ struct
+ {
+ uint8_t Recipient : 5; ///< Request recipient (device, interface, endpoint, other)
+ uint8_t Type : 2; ///< Request type (standard, class or vendor).
+ uint8_t Direction : 1; ///< Transfer direction of SETUP data phase.
+ } bmRequestType;
+
+ uint8_t bRequest;
+ uint16_t wValue;
+ uint16_t wIndex;
+ uint16_t wLength;
+} USB_Setup_TypeDef;
+
+/// @brief USB Setup Union type.
+typedef union
+{
+ USB_Setup_TypeDef setup;
+ uint8_t c[8];
+ uint16_t i[4];
+} USB_Setup_UnionDef;
+
+/// @brief USB Device Descriptor.
+typedef struct
+{
+ uint8_t bLength; ///< Size of this descriptor in bytes
+ uint8_t bDescriptorType; ///< Constant DEVICE Descriptor Type
+ uint16_t bcdUSB; ///< USB Specification Release Number in BCD
+ uint8_t bDeviceClass; ///< Class code (assigned by the USB-IF)
+ uint8_t bDeviceSubClass; ///< Subclass code (assigned by the USB-IF)
+ uint8_t bDeviceProtocol; ///< Protocol code (assigned by the USB-IF)
+ uint8_t bMaxPacketSize0; ///< Maximum packet size for endpoint zero
+ uint16_t idVendor; ///< Vendor ID (assigned by the USB-IF)
+ uint16_t idProduct; ///< Product ID (assigned by the manufacturer)
+ uint16_t bcdDevice; ///< Device release number in binary-coded decimal
+ uint8_t iManufacturer; ///< Index of string descriptor describing manufacturer
+ uint8_t iProduct; ///< Index of string descriptor describing product
+ uint8_t iSerialNumber; ///< Index of string descriptor describing the serial number
+ uint8_t bNumConfigurations; ///< Number of possible configurations
+} USB_DeviceDescriptor_TypeDef;
+
+
+/// @brief USB Configuration Descriptor.
+typedef struct
+{
+ uint8_t bLength; ///< Size of this descriptor in bytes
+ uint8_t bDescriptorType; ///< Constant CONFIGURATION Descriptor Type
+ uint16_t wTotalLength; ///< Total length of data returned for this
+ ///< configuration. Includes the combined length of all
+ ///< descriptors (configuration, interface, endpoint,
+ ///< and class- or vendor-specific) returned for this
+ ///< configuration.
+ uint8_t bNumInterfaces; ///< Number of interfaces supported by this
+ ///< configuration
+ uint8_t bConfigurationValue; ///< Value to use as an argument to the
+ ///< SetConfiguration request to select this
+ ///< configuration.
+ uint8_t iConfiguration; ///< Index of string descriptor describing this
+ ///< configuration.
+ uint8_t bmAttributes; ///< Configuration characteristics.
+ ///< @n D7: Reserved (set to one)
+ ///< @n D6: Self-powered
+ ///< @n D5: Remote Wakeup
+ ///< @n D4...0: Reserved (reset to zero)
+ uint8_t bMaxPower; ///< Maximum power consumption of the USB device, unit
+ ///< is 2mA per LSB
+} USB_ConfigurationDescriptor_TypeDef;
+
+
+/// @brief USB Interface Descriptor.
+typedef struct
+{
+ uint8_t bLength; ///< Size of this descriptor in bytes.
+ uint8_t bDescriptorType; ///< Constant INTERFACE Descriptor Type.
+ uint8_t bInterfaceNumber; ///< Number of this interface. Zero-based value
+ ///< identifying the index in the array of concurrent
+ ///< interfaces supported by this configuration.
+ uint8_t bAlternateSetting; ///< Value used to select this alternate setting for
+ ///< the interface identified in the prior field.
+ uint8_t bNumEndpoints; ///< Number of endpoints used by this interface
+ ///< (excluding endpoint zero). If this value is zero,
+ ///< this interface only uses the Default Control Pipe.
+ uint8_t bInterfaceClass; ///< Class code (assigned by the USB-IF). A value
+ ///< of zero is reserved for future standardization. If
+ ///< this field is set to FFH, the interface class is
+ ///< vendor-specific. All other values are reserved for
+ ///< assignment by the USB-IF.
+ uint8_t bInterfaceSubClass; ///< Subclass code (assigned by the USB-IF). These codes
+ ///< are qualified by the value of the bInterfaceClass
+ ///< field. If the bInterfaceClass field is reset to
+ ///< zero, this field must also be reset to zero. If
+ ///< the bInterfaceClass field is not set to FFH, all
+ ///< values are reserved for assignment by the USB-IF.
+ uint8_t bInterfaceProtocol; ///< Protocol code (assigned by the USB). These codes
+ ///< are qualified by the value of the bInterfaceClass
+ ///< and the bInterfaceSubClass fields. If an interface
+ ///< supports class-specific requests, this code
+ ///< identifies the protocols that the device uses as
+ ///< defined by the specification of the device class.
+ ///< If this field is reset to zero, the device does
+ ///< not use a class-specific protocol on this
+ ///< interface. If this field is set to FFH, the device
+ ///< uses a vendor-specific protocol for this interface
+ uint8_t iInterface; ///< Index of string descriptor describing this
+ ///< interface.
+} USB_InterfaceDescriptor_TypeDef;
+
+
+/// @brief USB Endpoint Descriptor.
+typedef struct
+{
+ uint8_t bLength; ///< Size of this descriptor in bytes
+ uint8_t bDescriptorType; ///< Constant ENDPOINT Descriptor Type
+ uint8_t bEndpointAddress; ///< The address of the endpoint
+ uint8_t bmAttributes; ///< This field describes the endpoint attributes
+ uint16_t wMaxPacketSize; ///< Maximum packet size for the endpoint
+ uint8_t bInterval; ///< Interval for polling EP for data transfers
+} USB_EndpointDescriptor_TypeDef;
+
+/// @brief USB String Descriptor.
+typedef uint8_t USB_StringDescriptor_TypeDef; ///< The string descriptor
+
+/// @brief USB Language ID String Descriptor.
+typedef uint16_t USB_LangId_StringDescriptor_Typedef; ///< The language ID string descriptor
+
+#if (SLAB_USB_NUM_LANGUAGES == 1)
+/// @brief USB String Table Structure.
+typedef SI_VARIABLE_SEGMENT_POINTER(, USB_StringDescriptor_TypeDef, SI_SEG_GENERIC) USB_StringTable_TypeDef;
+#elif (SLAB_USB_NUM_LANGUAGES > 1)
+typedef struct
+{
+ uint16_t *languageIDs;
+ USB_StringDescriptor_TypeDef * * *languageArray;
+} USB_StringTable_TypeDef;
+#endif // ( SLAB_USB_NUM_LANGUAGES == 1 )
+
+/// @brief USB Device stack initialization structure.
+/// @details This structure is passed to @ref USBD_Init() when starting up
+/// the device.
+typedef struct
+{
+ SI_VARIABLE_SEGMENT_POINTER(deviceDescriptor, USB_DeviceDescriptor_TypeDef, SI_SEG_GENERIC); ///< Pointer to the device descriptor
+ SI_VARIABLE_SEGMENT_POINTER(configDescriptor, USB_ConfigurationDescriptor_TypeDef, SI_SEG_GENERIC); ///< Pointer to the configuration descriptor
+ SI_VARIABLE_SEGMENT_POINTER(stringDescriptors, USB_StringTable_TypeDef, SI_SEG_GENERIC); ///< Pointer to an array of string descriptor pointers
+ uint8_t numberOfStrings; ///< Number of strings in string descriptor array
+} USBD_Init_TypeDef;
+
+/// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
+// Endpoint structure
+typedef struct
+{
+ SI_VARIABLE_SEGMENT_POINTER(buf, uint8_t, SI_SEG_GENERIC);
+ uint16_t remaining;
+ USBD_EpState_TypeDef state;
+ union
+ {
+ struct
+ {
+ uint8_t callback : 1;
+ uint8_t outPacketPending : 1;
+ uint8_t inPacketPending : 1;
+ uint8_t waitForRead : 1;
+ } bits;
+ uint8_t c;
+ } misc;
+} USBD_Ep_TypeDef;
+
+// USB Device structure
+typedef struct
+{
+ uint8_t configurationValue;
+#if SLAB_USB_REMOTE_WAKEUP_ENABLED
+ uint8_t remoteWakeupEnabled;
+#endif
+ uint8_t numberOfStrings;
+ USBD_State_TypeDef state;
+ USBD_State_TypeDef savedState;
+ USB_Setup_TypeDef setup;
+ union
+ {
+ struct
+ {
+ uint8_t type : 7;
+ uint8_t init : 1;
+ } encoding;
+ uint8_t c;
+ } ep0String;
+ USBD_Ep_TypeDef ep0;
+#if SLAB_USB_EP1IN_USED
+ USBD_Ep_TypeDef ep1in;
+#endif
+#if SLAB_USB_EP2IN_USED
+ USBD_Ep_TypeDef ep2in;
+#endif
+#if SLAB_USB_EP3IN_USED
+ USBD_Ep_TypeDef ep3in;
+#endif
+#if SLAB_USB_EP1OUT_USED
+ USBD_Ep_TypeDef ep1out;
+#endif
+#if SLAB_USB_EP2OUT_USED
+ USBD_Ep_TypeDef ep2out;
+#endif
+#if SLAB_USB_EP3OUT_USED
+ USBD_Ep_TypeDef ep3out;
+#endif
+#if ((SLAB_USB_EP3IN_USED) && (SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_ISOC))
+ uint16_t ep3inIsoIdx;
+#endif
+#if ((SLAB_USB_EP3OUT_USED) && (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC))
+ uint16_t ep3outIsoIdx;
+#endif
+#if SLAB_USB_SUPPORT_ALT_INTERFACES
+ uint8_t interfaceAltSetting[SLAB_USB_NUM_INTERFACES];
+#endif
+ SI_VARIABLE_SEGMENT_POINTER(deviceDescriptor, USB_DeviceDescriptor_TypeDef, SI_SEG_GENERIC);
+ SI_VARIABLE_SEGMENT_POINTER(configDescriptor, USB_ConfigurationDescriptor_TypeDef, SI_SEG_GENERIC);
+ SI_VARIABLE_SEGMENT_POINTER(stringDescriptors, USB_StringTable_TypeDef, SI_SEG_GENERIC);
+} USBD_Device_TypeDef;
+/// @endcond DO_NOT_INCLUDE_WITH_DOXYGEN
+
+/** @} (end addtogroup efm8_usb_typedefs Typedefs) */
+
+/***************************************************************************//**
+ * @addtogroup efm8_usb_constants Constants
+ * @{
+ ******************************************************************************/
+
+// -----------------------------------------------------------------------------
+// Compiler-specific memory segment definitions
+
+#ifndef MEM_MODEL_SEG
+
+// -----------------------------------------------------------------------------
+// Memory Model-Specific Location
+//
+// MEM_MODEL_SEG is the default memory segment used for a given
+// memory model. Some variables use this symbol in order to reduce the amount
+// of code space and number of cycles it takes to access them.
+// The user can override this value by defining it in his usbconfig.h file.
+// For example:
+//
+// #define MEM_MODEL_LOC SI_SEG_XDATA
+//
+// will place these variables in XRAM regardless of the memory model used to
+// build the project.
+// -----------------------------------------------------------------------------
+
+#if (defined SDCC) || (defined __SDCC)
+
+#if (__SDCC_MODEL_SMALL)
+#define MEM_MODEL_SEG SI_SEG_IDATA
+#elif defined __SDCC_MODEL_MEDIUM
+#define MEM_MODEL_SEG SI_SEG_PDATA
+#elif (defined __SDCC_MODEL_LARGE) || (defined __SDCC_MODEL_HUGE)
+#define MEM_MODEL_SEG SI_SEG_XDATA
+#else
+#error "Illegal memory model setting."
+#endif
+
+#elif defined __RC51__
+
+#if (__MEMORY_MODEL__ == 0) // TINY
+#define MEM_MODEL_SEG SI_SEG_IDATA
+#elif (__MEMORY_MODEL__ == 1) // SMALL
+#define MEM_MODEL_SEG SI_SEG_IDATA
+#elif (__MEMORY_MODEL__ == 2) // COMPACT
+#define MEM_MODEL_SEG SI_SEG_PDATA
+#elif (__MEMORY_MODEL__ == 3) // LARGE
+#define MEM_MODEL_SEG SI_SEG_XDATA
+#elif (__MEMORY_MODEL__ == 4) // HUGE
+#define MEM_MODEL_SEG SI_SEG_PDATA
+#else
+#error "Illegal memory model setting."
+#endif
+
+#elif defined __C51__
+
+#if (__MODEL__ == 0) // SMALL
+#define MEM_MODEL_SEG SI_SEG_IDATA
+#elif (__MODEL__ == 1) // COMPACT
+#define MEM_MODEL_SEG SI_SEG_PDATA
+#elif (__MODEL__ == 2) // LARGE
+#define MEM_MODEL_SEG SI_SEG_XDATA
+#else
+#error "Illegal memory model setting."
+#endif
+
+#elif defined _CC51
+
+#if (_MODEL == 's') // SMALL
+#define MEM_MODEL_SEG SI_SEG_IDATA
+#elif (_MODEL == 'a') // AUXPAGE
+#define MEM_MODEL_SEG SI_SEG_PDATA
+#elif (_MODEL == 'l') // LARGE
+#define MEM_MODEL_SEG SI_SEG_XDATA
+#elif (_MODEL == 'r') // REENTRANT
+#define MEM_MODEL_SEG SI_SEG_XDATA
+#else
+#error "Illegal memory model setting."
+#endif
+
+#elif defined __ICC8051__
+#if (__DATA_MODEL__ == 0) // TINY
+#define MEM_MODEL_SEG SI_SEG_IDATA
+#elif (__DATA_MODEL__ == 1) // SMALL
+#define MEM_MODEL_SEG SI_SEG_IDATA
+#elif (__DATA_MODEL__ == 2) // LARGE
+#define MEM_MODEL_SEG SI_SEG_XDATA
+#elif (__DATA_MODEL__ == 3) // GENERIC
+#define MEM_MODEL_SEG SI_SEG_XDATA
+#elif (__DATA_MODEL__ == 4) // FAR
+#define MEM_MODEL_SEG SI_SEG_XDATA
+#else
+#error "Illegal memory model setting."
+#endif
+
+#endif
+#endif // #ifndef MEM_MODEL_SEG
+
+/** @} (end addtogroup efm8_usb_constants Constants) */
+
+/// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
+void USBD_SetUsbState(USBD_State_TypeDef newState);
+USB_Status_TypeDef USBDCH9_SetupCmd(void);
+/// @endcond DO_NOT_INCLUDE_WITH_DOXYGEN
+
+// -----------------------------------------------------------------------------
+// Library Configuration Definitions
+
+/**************************************************************************//**
+ * @addtogroup efm8_usb_config Library Configuration
+ * @{
+ *
+ * @details Library configuration constants read from usbconfig.h.
+ *
+ * This library will look for configuration constants in **usbconfig.h**.
+ * This file is provided/written by the user and should be
+ * located in a directory that is part of the include path.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_BUS_POWERED
+ * @brief Configures the USB device for bus-powered or self-powered mode.
+ * @details
+ * When '1' the USB device is bus-powered.
+ * When '0' the USB device is self-powered.
+ *
+ * Default setting is '1' and may be overridden by defining in 'usbconfig.h'.
+ *
+ * @note The EFM8UB1, EFM8UB3, and EFM8UB4 devices can be configured to ignore
+ * the voltage on the VBUS pin and to instead use that pin as GPIO. If
+ * this feature is used, SLAB_USB_BUS_POWERED should be set to '1' even if
+ * the device is not drawing its power from the VBUS line.
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_FULL_SPEED
+ * @brief Configures the USB device for full-speed or low-speed operation.
+ * @details
+ * When '1' the USB device is full-speed
+ * When '0' the USB device is low-speed
+ *
+ * Default setting is '1' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_CLOCK_RECOVERY_ENABLED
+ * @brief Enables/disables the USB Clock Recovery
+ * @details USB Clock Recovery uses the incoming USB dat stream to adjust the
+ * internal oscillator. This allows the internal oscillator to meet the
+ * requirements for USB clock tolerance.
+ *
+ * When '1' the USB clock recovery is enabled
+ * When '0' the USB clock recovery is disabled
+ *
+ * Default setting is '1' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_REMOTE_WAKEUP_ENABLED
+ * @brief Enables/disables remote wakeup capability
+ * @details Remote wakeup allow the USB device to wake the host from suspend.
+ * When enabled, the library will call @ref USBD_RemoteWakeupCb() to determine
+ * if the remote wakeup source caused the device to wake up. If it did, the
+ * library will exit suspend mode and call @ref USBD_RemoteWakeup() to wake
+ * up the host.
+ *
+ * When '1' remote wakeup is enabled
+ * When '0' remote wakeup is disabled
+ *
+ * Default setting is '0' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_NUM_INTERFACES
+ * @brief The number of interfaces available in the configuration
+ * @details
+ * Default setting is '1' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_SUPPORT_ALT_INTERFACES
+ * @brief Enables/disables alternate interface settings
+ * @details If any of the interfaces support alternate settings, this should be
+ * set to '1'. Upon receiveing a SET_INTERFACE request, the library will call
+ * @ref USBD_SetInterfaceCb(), which should return @ref USB_STATUS_OK if the
+ * alternate setting is valid or @ref USB_STATUS_REQ_ERR if it is not.
+ *
+ * When '1' alternate inteface settings are supported
+ * When '0' alternate interface settings are not supported, and the library will
+ * respond to any SET_INTERFACE request with a procedural stall
+ *
+ * Default setting is '0' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_EP1IN_USED
+ * @brief Enables/disables Endpoint 1 IN
+ * @details
+ * When '1' Endpoint 1 IN is enabled
+ * When '0' Endpoint 1 IN is disabled
+ *
+ * Default setting is '0' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_EP1OUT_USED
+ * @brief Enables/disables Endpoint 1 OUT
+ * @details
+ * When '1' Endpoint 1 OUT is enabled
+ * When '0' Endpoint 1 OUT is disabled
+ *
+ * Default setting is '0' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_EP2IN_USED
+ * @brief Enables/disables Endpoint 2 IN
+ * @details
+ * When '1' Endpoint 2 IN is enabled
+ * When '0' Endpoint 2 IN is disabled
+ *
+ * Default setting is '0' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_EP2OUT_USED
+ * @brief Enables/disables Endpoint 2 OUT
+ * @details
+ * When '1' Endpoint 2 OUT is enabled
+ * When '0' Endpoint 2 OUT is disabled
+ *
+ * Default setting is '0' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_EP3IN_USED
+ * @brief Enables/disables Endpoint 3 IN
+ * @details
+ * When '1' Endpoint 3 IN is enabled
+ * When '0' Endpoint 3 IN is disabled
+ *
+ * Default setting is '0' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_EP3OUT_USED
+ * @brief Enables/disables Endpoint 3 OUT
+ * @details
+ * When '1' Endpoint 3 OUT is enabled
+ * When '0' Endpoint 3 OUT is disabled
+ *
+ * Default setting is '0' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_EP1IN_MAX_PACKET_SIZE
+ * @brief The maximum packet size that can be received on Endpoint 1 IN
+ * @details
+ * Default setting is '64' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_EP1OUT_MAX_PACKET_SIZE
+ * @brief The maximum packet size that can be transmitted on Endpoint 1 OUT
+ * @details
+ * Default setting is '64' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_EP2IN_MAX_PACKET_SIZE
+ * @brief The maximum packet size that can be received on Endpoint 2 IN
+ * @details
+ * Default setting is '64' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_EP2OUT_MAX_PACKET_SIZE
+ * @brief The maximum packet size that can be transmitted on Endpoint 2 OUT
+ * @details
+ * Default setting is '64' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_EP3IN_MAX_PACKET_SIZE
+ * @brief The maximum packet size that can be received on Endpoint 3 IN
+ * @details
+ * Default setting is '64' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_EP3OUT_MAX_PACKET_SIZE
+ * @brief The maximum packet size that can be transmitted on Endpoint 3 OUT
+ * @details
+ * Default setting is '64' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_EP1IN_TRANSFER_TYPE
+ * @brief Transfer type on Endpoint 1 IN
+ * @details
+ * May take one of the following values:
+ * USB_EPTYPE_INTR - Interrupt
+ * USB_EPTYPE_BULK - Bulk
+ *
+ * Default setting is @ref USB_EPTYPE_INTR and may be overridden by defining in
+ * 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_EP1OUT_TRANSFER_TYPE
+ * @brief Transfer type on Endpoint 1 OUT
+ * @details
+ * May take one of the following values:
+ * USB_EPTYPE_INTR - Interrupt
+ * USB_EPTYPE_BULK - Bulk
+ *
+ * Default setting is @ref USB_EPTYPE_INTR and may be overridden by defining in
+ * 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_EP2IN_TRANSFER_TYPE
+ * @brief Transfer type on Endpoint 2 IN
+ * @details
+ * May take one of the following values:
+ * USB_EPTYPE_INTR - Interrupt
+ * USB_EPTYPE_BULK - Bulk
+ *
+ * Default setting is @ref USB_EPTYPE_INTR and may be overridden by defining in
+ * 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_EP2OUT_TRANSFER_TYPE
+ * @brief Transfer type on Endpoint 2 OUT
+ * @details
+ * May take one of the following values:
+ * USB_EPTYPE_INTR - Interrupt
+ * USB_EPTYPE_BULK - Bulk
+ *
+ * Default setting is @ref USB_EPTYPE_INTR and may be overridden by defining in
+ * 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_EP3IN_TRANSFER_TYPE
+ * @brief Transfer type on Endpoint 3 IN
+ * @details
+ * May take one of the following values:
+ * USB_EPTYPE_INTR - Interrupt
+ * USB_EPTYPE_BULK - Bulk
+ * USB_EPTYPE_ISOC - Isochronous
+ *
+ * Default setting is @ref USB_EPTYPE_INTR and may be overridden by defining in
+ * 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_EP3OUT_TRANSFER_TYPE
+ * @brief Transfer type on Endpoint 3 OUT
+ * @details
+ * May take one of the following values:
+ * USB_EPTYPE_INTR - Interrupt
+ * USB_EPTYPE_BULK - Bulk
+ * USB_EPTYPE_ISOC - Isochronous
+ *
+ * Default setting is @ref USB_EPTYPE_INTR and may be overridden by defining in
+ * 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_RESET_CB
+ * @brief Enables/disables the USB Reset callback function
+ * @details
+ * When '1' @ref USBD_ResetCb() is called upon reception of a USB Reset
+ * When '0' @ref USBD_ResetCb() is not called upon reception of a USB Reset
+ *
+ * Default setting is '0' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_SOF_CB
+ * @brief Enables/disables the USB Start-Of-Frame callback function
+ * @details
+ * When '1' @ref USBD_SofCb() is called upon reception of a Start-of-Frame
+ * packet
+ * When '0' @ref USBD_SofCb() is not called upon reception of a Start-of-Frame
+ * packet
+ *
+ * Default setting is '0' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_STATE_CHANGE_CB
+ * @brief Enables/disables the USB State Change callback function
+ * @details
+ * When '1' @ref USBD_DeviceStateChangeCb() is called when the USB device state
+ * changes
+ * When '0' @ref USBD_DeviceStateChangeCb() is not called when the USB device
+ * state changes
+ *
+ * Default setting is '0' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_IS_SELF_POWERED_CB
+ * @brief Enables/disables the USB Self-Powered callback function
+ * @details
+ * When '1' @ref USBD_IsSelfPoweredCb() is called upon reception of a
+ * GET_STATUS (Self-Powered) request
+ * When '0' @ref USBD_IsSelfPoweredCb() is not called upon reception of a
+ * GET_STATUS (Self-Powered) request
+ *
+ * Default setting is '0' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_SETUP_CMD_CB
+ * @brief Enables/disables the USB Setup Command callback function
+ * @details
+ * When '1' @ref USBD_SetupCmdCb() is called upon reception of a Setup Request
+ * When '0' @ref USBD_SetupCmdCb() is not called upon reception of a Setup
+ * Request
+ *
+ * Default setting is '0' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_HANDLER_CB
+ * @brief Enables/disables the USB Handler Entry and Exit callback functions
+ * @details
+ * When '1' @ref USBD_EnterHandler() will be called before the USB handler
+ * executes and @ref USBD_ExitHandler() will be called after the USB handler
+ * completes
+ * When '0' @ref USBD_EnterHandler() and @ref USBD_ExitHandler() will not be
+ * called
+ *
+ * Default setting is '0' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_NUM_LANGUAGES
+ * @brief Number of languages supported by the USB string descriptors
+ * @details
+ * Default setting is '1' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_LANGUAGE
+ * @brief
+ * Defines the language of the USB string descriptors when
+ * @ref SLAB_USB_NUM_LANGUAGES is '1'.
+ *
+ * @details
+ * When @ref SLAB_USB_NUM_LANGUAGES is greater than '1', the supported languages
+ * must be defined in a separate table, and a structure of type
+ * @ref USB_StringDescriptor_TypeDef must be defined for each supported
+ * language
+ *
+ * Default setting is @ref USB_LANGID_ENUS and may be overridden by defining in
+ * 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_UTF8_STRINGS
+ * @brief
+ * Enables UTF-8 string decoding for USB string descriptors that are created
+ * using @ref UTF8_PACKED_STATIC_CONST_STRING_DESC.
+ *
+ * @details
+ * If this option is enabled, USB descriptor strings that are created using
+ * @ref UTF8_PACKED_STATIC_CONST_STRING_DESC can be encoded as UTF-8 which
+ * allows for Unicode characters (up to 16-bits wide) to be used for USB
+ * string descriptors. The UTF-8 strings will be decoded into UCS-2 16-bit
+ * wide character format required by USB. If this feature is not needed then
+ * this option can be disabled to save code memory space. If this option is
+ * disabled, then @ref UTF8_PACKED_STATIC_CONST_STRING_DESC should not be used.
+ *
+ * Default setting is '0' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_PWRSAVE_MODE
+ * @brief Configures the power-saving options supported by the device
+ *
+ * @details
+ * Default setting is @ref USB_PWRSAVE_MODE_ONSUSPEND and may be overridden by
+ * defining in 'usbconfig.h'.
+ *
+ * SLAB_USB_PWRSAVE_MODE configures when the device will automatically enter
+ * the USB power-save mode. It is a bitmask constant with bit values:
+ *
+ * @ref USB_PWRSAVE_MODE_OFF - No energy saving option selected
+ * @ref USB_PWRSAVE_MODE_ONSUSPEND - Enter USB power-save mode on USB suspend
+ * @ref USB_PWRSAVE_MODE_ONVBUSOFF - Enter USB power-save mode when not
+ * attached to the USB host.
+ * @ref USB_PWRSAVE_MODE_FASTWAKE - Exit USB power-save mode more quickly.
+ * This is useful for some applications that
+ * support remote wakeup.
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * @def SLAB_USB_POLLED_MODE
+ * @brief Enables/disables USB library polled mode
+ * @details
+ * When '1' the library will run in polled mode
+ * When '0' the library will run in interrupt mode
+ *
+ * Default setting is '0' and may be overridden by defining in 'usbconfig.h'.
+ *
+ *****************************************************************************/
+
+/** @} (end addtogroup efm8_usb_config Library Configuration) */
+
+// Set default USB library configurations if the value is not configured in
+// usbconfig.h
+
+#ifndef SLAB_USB_BUS_POWERED
+#define SLAB_USB_BUS_POWERED 1
+#endif
+
+#ifndef SLAB_USB_FULL_SPEED
+#define SLAB_USB_FULL_SPEED 1
+#endif
+
+#ifndef SLAB_USB_CLOCK_RECOVERY_ENABLED
+#define SLAB_USB_CLOCK_RECOVERY_ENABLED 1
+#endif
+
+#ifndef SLAB_USB_REMOTE_WAKEUP_ENABLED
+#define SLAB_USB_REMOTE_WAKEUP_ENABLED 0
+#endif
+
+#ifndef SLAB_USB_NUM_INTERFACES
+#define SLAB_USB_NUM_INTERFACES 1
+#endif
+
+#ifndef SLAB_USB_SUPPORT_ALT_INTERFACES
+#define SLAB_USB_SUPPORT_ALT_INTERFACES 0
+#endif
+
+#ifndef SLAB_USB_EP1IN_USED
+#define SLAB_USB_EP1IN_USED 0
+#endif
+
+#ifndef SLAB_USB_EP1OUT_USED
+#define SLAB_USB_EP1OUT_USED 0
+#endif
+
+#ifndef SLAB_USB_EP2IN_USED
+#define SLAB_USB_EP2IN_USED 0
+#endif
+
+#ifndef SLAB_USB_EP2OUT_USED
+#define SLAB_USB_EP2OUT_USED 0
+#endif
+
+#ifndef SLAB_USB_EP3IN_USED
+#define SLAB_USB_EP3IN_USED 0
+#endif
+
+#ifndef SLAB_USB_EP3OUT_USED
+#define SLAB_USB_EP3OUT_USED 0
+#endif
+
+#ifndef SLAB_USB_EP1IN_MAX_PACKET_SIZE
+#define SLAB_USB_EP1IN_MAX_PACKET_SIZE 64
+#endif
+
+#ifndef SLAB_USB_EP1OUT_MAX_PACKET_SIZE
+#define SLAB_USB_EP1OUT_MAX_PACKET_SIZE 64
+#endif
+
+#ifndef SLAB_USB_EP2IN_MAX_PACKET_SIZE
+#define SLAB_USB_EP2IN_MAX_PACKET_SIZE 64
+#endif
+
+#ifndef SLAB_USB_EP2OUT_MAX_PACKET_SIZE
+#define SLAB_USB_EP2OUT_MAX_PACKET_SIZE 64
+#endif
+
+#ifndef SLAB_USB_EP3IN_MAX_PACKET_SIZE
+#define SLAB_USB_EP3IN_MAX_PACKET_SIZE 64
+#endif
+
+#ifndef SLAB_USB_EP3OUT_MAX_PACKET_SIZE
+#define SLAB_USB_EP3OUT_MAX_PACKET_SIZE 64
+#endif
+
+#ifndef SLAB_USB_EP1IN_TRANSFER_TYPE
+#define SLAB_USB_EP1IN_TRANSFER_TYPE USB_EPTYPE_INTR
+#endif
+
+#ifndef SLAB_USB_EP1OUT_TRANSFER_TYPE
+#define SLAB_USB_EP1OUT_TRANSFER_TYPE USB_EPTYPE_INTR
+#endif
+
+#ifndef SLAB_USB_EP2IN_TRANSFER_TYPE
+#define SLAB_USB_EP2IN_TRANSFER_TYPE USB_EPTYPE_INTR
+#endif
+
+#ifndef SLAB_USB_EP2OUT_TRANSFER_TYPE
+#define SLAB_USB_EP2OUT_TRANSFER_TYPE USB_EPTYPE_INTR
+#endif
+
+#ifndef SLAB_USB_EP3IN_TRANSFER_TYPE
+#define SLAB_USB_EP3IN_TRANSFER_TYPE USB_EPTYPE_INTR
+#endif
+
+#ifndef SLAB_USB_EP3OUT_TRANSFER_TYPE
+#define SLAB_USB_EP3OUT_TRANSFER_TYPE USB_EPTYPE_INTR
+#endif
+
+#ifndef SLAB_USB_RESET_CB
+#define SLAB_USB_RESET_CB 0
+#endif
+
+#ifndef SLAB_USB_SOF_CB
+#define SLAB_USB_SOF_CB 0
+#endif
+
+#ifndef SLAB_USB_STATE_CHANGE_CB
+#define SLAB_USB_STATE_CHANGE_CB 0
+#endif
+
+#ifndef SLAB_USB_IS_SELF_POWERED_CB
+#define SLAB_USB_IS_SELF_POWERED_CB 0
+#endif
+
+#ifndef SLAB_USB_SETUP_CMD_CB
+#define SLAB_USB_SETUP_CMD_CB 0
+#endif
+
+#ifndef SLAB_USB_HANDLER_CB
+#define SLAB_USB_HANDLER_CB 0
+#endif
+
+#ifndef SLAB_USB_NUM_LANGUAGES
+#define SLAB_USB_NUM_LANGUAGES 1
+#endif
+
+#ifndef SLAB_USB_LANGUAGE
+#define SLAB_USB_LANGUAGE USB_LANGID_ENUS
+#endif
+
+#ifndef SLAB_USB_UTF8_STRINGS
+#define SLAB_USB_UTF8_STRINGS 0
+#endif
+
+#ifndef SLAB_USB_PWRSAVE_MODE
+#define SLAB_USB_PWRSAVE_MODE USB_PWRSAVE_MODE_ONSUSPEND
+#endif
+
+#ifndef SLAB_USB_POLLED_MODE
+#define SLAB_USB_POLLED_MODE 0
+#endif
+
+#if SLAB_USB_POLLED_MODE
+void usbIrqHandler(void);
+#endif
+
+/***************************************************************************//**
+ * @addtogroup efm8_api API Functions
+ * @{
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @brief
+ * Abort all pending transfers.
+ *
+ * @details
+ * Aborts transfers for all endpoints currently in use. Pending
+ * transfers on the default endpoint (EP0) are not aborted.
+ ******************************************************************************/
+void USBD_AbortAllTransfers(void);
+
+/***************************************************************************//**
+ * @brief
+ * Abort a pending transfer on a specific endpoint.
+ *
+ * @param epAddr
+ * The address of the endpoint to abort.
+ * @return
+ * @ref USB_STATUS_OK is the transfer aborted, @ref USB_STATUS_ILLEGAL
+ * otherwise
+ ******************************************************************************/
+int8_t USBD_AbortTransfer(uint8_t epAddr);
+
+/***************************************************************************//**
+ * @brief
+ * Start USB device operation.
+ *
+ * @details
+ * Device operation is started by connecting a pull-up resistor on the
+ * appropriate USB data line.
+ ******************************************************************************/
+void USBD_Connect(void);
+
+/***************************************************************************//**
+ * @brief
+ * Stop USB device operation.
+ *
+ * @details
+ * Device operation is stopped by disconnecting the pull-up resistor from the
+ * appropriate USB data line. Often referred to as a "soft" disconnect.
+ ******************************************************************************/
+void USBD_Disconnect(void);
+
+/***************************************************************************//**
+ * @brief
+ * Check if an endpoint is busy doing a transfer.
+ *
+ * @param epAddr
+ * The address of the endpoint to check.
+ *
+ * @return
+ * True if endpoint is busy, false otherwise.
+ ******************************************************************************/
+bool USBD_EpIsBusy(uint8_t epAddr);
+
+/***************************************************************************//**
+ * @brief
+ * Get current USB device state.
+ *
+ * @return
+ * Device USB state. See @ref USBD_State_TypeDef.
+ ******************************************************************************/
+USBD_State_TypeDef USBD_GetUsbState(void);
+
+/***************************************************************************//**
+ * @brief
+ * Initializes USB device hardware and internal protocol stack data structures,
+ * then connects the data-line (D+ or D-) pullup resistor to signal host that
+ * enumeration can begin.
+ *
+ * @note
+ * You may later use @ref USBD_Disconnect() and @ref USBD_Connect() to force
+ * reenumeration.
+ *
+ * @param p
+ * Pointer to device initialization struct. See @ref USBD_Init_TypeDef.
+ *
+ * @return
+ * @ref USB_STATUS_OK on success, else an appropriate error code.
+ ******************************************************************************/
+int8_t USBD_Init(SI_VARIABLE_SEGMENT_POINTER(p, const USBD_Init_TypeDef, SI_SEG_GENERIC));
+
+/***************************************************************************//**
+ * @brief
+ * Start a read (OUT) transfer on an endpoint.
+ *
+ * @note
+ * If it is possible that the host will send more data than your device
+ * expects, round buffer size up to the next multiple of maxpacket size.
+ *
+ * @param epAddr
+ * Endpoint address.
+ *
+ * @param dat
+ * Pointer to transfer data buffer.
+ *
+ * @param byteCount
+ * Transfer length.
+ *
+ * @param callback
+ * Boolean to determine if USB_XferCompleteCb should be called for this
+ * transfer.
+ *
+ * @return
+ * @ref USB_STATUS_OK on success, else an appropriate error code.
+ ******************************************************************************/
+int8_t USBD_Read(uint8_t epAddr,
+ SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC),
+ uint16_t byteCount,
+ bool callback);
+
+/***************************************************************************//**
+ * @brief
+ * Perform a remote wakeup signaling sequence.
+ *
+ * @note
+ * This function is typically called by the library if @ref
+ * USBD_RemoteWakeupCb() returns true, so it does not need to be called by
+ * application code.
+ *
+ * @return
+ * @ref USB_STATUS_OK on success, else an appropriate error code.
+ ******************************************************************************/
+int8_t USBD_RemoteWakeup(void);
+
+/***************************************************************************//**
+ * @brief
+ * Processes USB events when the library is configured for polled mode
+ *
+ * @details
+ * The USB library can be configured for interrupt (SLAB_USB_POLLED_MODE == 0)
+ * or polled (SLAB_USB_POLLED_MODE == 1) mode.
+ *
+ * When in interrupt mode, the USB interrupt handler will trigger
+ * when a USB event occurs. Callback functions will be called as needed.
+ *
+ * When in polled mode, the application must call USBD_Run() periodically to
+ * check for and process USB events. This may be useful in complex systems or
+ * when using an RTOS to perform all USB processing in the main loop instead
+ * of in the interrupt context.
+ *
+ ******************************************************************************/
+void USBD_Run(void);
+
+/***************************************************************************//**
+ * @brief
+ * Set an endpoint in the stalled (halted) state.
+ *
+ * @param epAddr
+ * The address of the endpoint to stall.
+ *
+ * @return
+ * @ref USB_STATUS_OK on success, else an appropriate error code.
+ ******************************************************************************/
+int8_t USBD_StallEp(uint8_t epAddr);
+
+/***************************************************************************//**
+ * @brief
+ * Stop USB device stack operation.
+ *
+ * @details
+ * The data-line pullup resistor is turned off, USB interrupts are disabled,
+ * and finally the USB pins are disabled.
+ ******************************************************************************/
+void USBD_Stop(void);
+
+/***************************************************************************//**
+ * @brief
+ * Enters USB suspend mode
+ *
+ * @details
+ * Disables USB transceiver, VDD Monitor, and prefetch engine. Suspends the
+ * internal regulator and internal oscillator.
+ * This function will not exit until the device recognizes resume signaling,
+ * VBUS attachment/removal, or a remote wakeup source interrupt.
+ * Before exiting, restores the states of the USB transceiver,
+ * VDD Monitor, prefetch engine, and internal regulator.
+ ******************************************************************************/
+void USBD_Suspend(void);
+
+/***************************************************************************//**
+ * @brief
+ * Reset stall state on a stalled (halted) endpoint.
+ *
+ * @param epAddr
+ * The address of the endpoint to un-stall.
+ *
+ * @return
+ * @ref USB_STATUS_OK on success, else an appropriate error code.
+ ******************************************************************************/
+int8_t USBD_UnStallEp(uint8_t epAddr);
+
+/***************************************************************************//**
+ * @brief
+ * Start a write (IN) transfer on an endpoint.
+ *
+ * @param epAddr
+ * Endpoint address.
+ *
+ * @param dat
+ * Pointer to transfer data buffer. This buffer must be WORD (4 byte) aligned.
+ *
+ * @param byteCount
+ * Transfer length.
+ *
+ * @param callback
+ * Boolean to determine if USB_XferCompleteCb should be called for this
+ * transfer.
+ *
+ * @return
+ * @ref USB_STATUS_OK on success, else an appropriate error code.
+ ******************************************************************************/
+int8_t USBD_Write(uint8_t epAddr,
+ SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC),
+ uint16_t byteCount,
+ bool callback);
+
+/** @} (end addtogroup efm8_api API Functions) */
+
+/***************************************************************************//**
+ * @addtogroup efm8_callbacks Callback Functions
+ * @{
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @brief
+ * USB Handler Entry callback function.
+ * @details
+ * Some systems may wish to be in a low-power state when between USB events.
+ * This low-power state may configure the system clock to a very low
+ * frequency. In order to reduce the execution time of the USB handler, this
+ * function is called before the handler executes to allow the system to switch
+ * to a higher clock source. When all USB processing is complete,
+ * @ref USBD_ExitHandler() will be called to allow the system to return
+ * to the low-power state.
+ * This callback function is optionally enabled by setting
+ * @ref SLAB_USB_HANDLER_CB to 1.
+ ******************************************************************************/
+void USBD_EnterHandler(void);
+
+/***************************************************************************//**
+ * @brief
+ * USB Handler Exit callback function.
+ * @details
+ * Some systems may wish to be in a low-power state when between USB events.
+ * This low-power state may configure the system clock to a very low
+ * frequency. This function is called after all USB processing is finished
+ * to allow a system that was previously configured by
+ * @ref USBD_EnterHandler() for high power to return to a low power state.
+ * This callback function is optionally enabled by setting
+ * @ref SLAB_USB_HANDLER_CB to 1.
+ ******************************************************************************/
+void USBD_ExitHandler(void);
+
+/***************************************************************************//**
+ * @brief
+ * USB Reset callback function.
+ * @details
+ * Called whenever USB reset signaling is detected on the USB port.
+ ******************************************************************************/
+void USBD_ResetCb(void);
+
+/***************************************************************************//**
+ * @brief
+ * USB Start Of Frame (SOF) interrupt callback function.
+ *
+ * @details
+ * Called at each SOF interrupt (if enabled),
+ *
+ * @param sofNr
+ * Current frame number. The value rolls over to 0 after 16383 (0x3FFF).
+ ******************************************************************************/
+void USBD_SofCb(uint16_t sofNr);
+
+/***************************************************************************//**
+ * @brief
+ * USB State change callback function.
+ *
+ * @details
+ * Called whenever the USB state of the device changes
+ *
+ * @param oldState
+ * The device USB state just left. See @ref USBD_State_TypeDef.
+ *
+ * @param newState
+ * New (the current) USB device state. See @ref USBD_State_TypeDef.
+ ******************************************************************************/
+void USBD_DeviceStateChangeCb(USBD_State_TypeDef oldState,
+ USBD_State_TypeDef newState);
+
+/***************************************************************************//**
+ * @brief
+ * USB power mode callback function.
+ *
+ * @details
+ * Called whenever the device stack needs to know if the device is currently
+ * self- or bus-powered. Typically when host has issued a @ref GET_STATUS
+ * setup command.
+ *
+ * @return
+ * True if self-powered, false otherwise.
+ ******************************************************************************/
+bool USBD_IsSelfPoweredCb(void);
+
+/***************************************************************************//**
+ * @brief
+ * USB setup request callback function.
+ *
+ * @details
+ * Called on each setup request received from host. This gives the system a
+ * possibility to extend or override standard requests, and to implement class
+ * or vendor specific requests. Return @ref USB_STATUS_OK if the request is
+ * handled, return @ref USB_STATUS_REQ_ERR if it is an illegal request or
+ * return @ref USB_STATUS_REQ_UNHANDLED to pass the request on to the default
+ * request handler.
+ *
+ * @param setup
+ * Pointer to a USB setup packet. See @ref USB_Setup_TypeDef.
+ *
+ * @return
+ * An appropriate status/error code. See @ref USB_Status_TypeDef.
+ ******************************************************************************/
+USB_Status_TypeDef USBD_SetupCmdCb(SI_VARIABLE_SEGMENT_POINTER(setup,
+ USB_Setup_TypeDef,
+ MEM_MODEL_SEG));
+
+/***************************************************************************//**
+ * @brief
+ * USB set interface callback function.
+ *
+ * @details
+ * Called each time the SET_INTERFACE request is made.
+ *
+ * @param interface
+ * Number of the interface to set.
+ *
+ * @param altSetting
+ * Alternate setting for the interface
+ *
+ * @return
+ * @ref USB_STATUS_OK if the alternate interface is valid and can be set,
+ * @ref USB_STATUS_REQ_ERR otherwise
+ ******************************************************************************/
+USB_Status_TypeDef USBD_SetInterfaceCb(uint8_t interface, uint8_t altSetting);
+
+/***************************************************************************//**
+ * @brief
+ * Queries the application to see if a remote wakeup occurred.
+ * @details
+ * If remote wakeup is enabled via @ref SLAB_USB_REMOTE_WAKEUP_ENABLED, the
+ * USB library will query the application after waking from suspend to see if
+ * the remote wakeup source was the reason for the wakeup. If this function
+ * returns True, the library will call @ref USBD_RemoteWakeup() to wake up the
+ * host and exit suspend mode.
+ * @return
+ * True if the remote wakeup source was the reason the device woke from
+ * suspend, false otherwise.
+ *
+ ******************************************************************************/
+bool USBD_RemoteWakeupCb(void);
+
+/***************************************************************************//**
+ * @brief
+ * Delays 10 - 15 ms while resume signaling is active during a remote
+ * wakeup event
+ *
+ ******************************************************************************/
+void USBD_RemoteWakeupDelay(void);
+
+/***************************************************************************//**
+ * @brief
+ * Processes USB events when the library is configured for polled mode
+ *
+ * @ details
+ * The USB library can be configured for interrupt
+ * (@ref SLAB_USB_POLLED_MODE == 0) or polled (@ref SLAB_USB_POLLED_MODE == 1)
+ * mode.
+ *
+ * When in interrupt mode, the USB interrupt handler will trigger
+ * when a USB event occurs. Callback functions will be called as needed.
+ *
+ * When in polled mode, the application must call USBD_Run() periodically to
+ * check for and process USB events. This may be useful in complex systems or
+ * when using an RTOS to perform all USB processing in the main loop instead
+ * of in the interrupt context.
+ *
+ ******************************************************************************/
+void USBD_Run(void);
+
+/***************************************************************************//**
+ * @brief
+ * USB transfer complete callback function.
+ *
+ * @details
+ * Called each time a packet is sent on an IN endpoint or received on an
+ * OUT endpoint.
+ *
+ * @param epAddr
+ * Endpoint on which the transfer occurred
+ *
+ * @param status
+ * Status of the endpoint
+ *
+ * @param xferred
+ * For bulk, interrupt, and control transfers:
+ * Number of bytes transferred since the last USBD_Write() or USBD_Read()
+ * call.
+ * For isochronous IN transfers:
+ * This parameter is not used
+ * For isochronous OUT transfers:
+ * the number of bytes received in the last packet
+ *
+ * @param remaining
+ * For bulk, interrupt, and control transfers:
+ * Number of bytes left to send or receive on the endpoint
+ * For isochronous transfers:
+ * The current index into the circular buffer holding isochronous data
+ *
+ * @return
+ * For bulk, interrupt, and control transfers:
+ * '0'
+ * For isochronous IN transfers:
+ * the number of bytes to transmit in the next packet
+ * For isochronous OUT ransfers:
+ * '0'
+ ******************************************************************************/
+uint16_t USBD_XferCompleteCb(uint8_t epAddr, \
+ USB_Status_TypeDef status, \
+ uint16_t xferred, \
+ uint16_t remaining);
+
+/** @} (end addtogroup efm8_callbacks Callback Functions) */
+
+/// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
+// -------------------- FIFO Access Functions ---------------------------------
+void USB_ReadFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC));
+void USB_WriteFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC), bool txPacket);
+/// @endcond DO_NOT_INCLUDE_WITH_DOXYGEN
+
+// -------------------- Include Files ------------------------------------------
+
+ // Error if peripheral driver not in use
+ #include "usb_0.h"
+
+/** @} (end addtogroup Efm8_usb) */
+
+#endif // __SILICON_LABS_EFM8_USB_H__
diff --git a/efm8/lib/c8051f380/efm8_usb/src/efm8_usbd.c b/efm8/lib/c8051f380/efm8_usb/src/efm8_usbd.c
new file mode 100644
index 0000000..34f94e4
--- /dev/null
+++ b/efm8/lib/c8051f380/efm8_usb/src/efm8_usbd.c
@@ -0,0 +1,780 @@
+/**************************************************************************//**
+ * 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
+
+// -----------------------------------------------------------------------------
+// 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)
+{
+ SI_VARIABLE_SEGMENT_POINTER(ep, USBD_Ep_TypeDef, MEM_MODEL_SEG);
+ int8_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)
+{
+ SI_VARIABLE_SEGMENT_POINTER(ep, USBD_Ep_TypeDef, MEM_MODEL_SEG);
+
+ // 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(SI_VARIABLE_SEGMENT_POINTER(p, const USBD_Init_TypeDef, SI_SEG_GENERIC))
+{
+ 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++)
+ {
+ *((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, MEM_MODEL_SEG))&myUsbDevice + i) = 0;
+ }
+
+ // Get the USB descriptors from p
+ myUsbDevice.deviceDescriptor = p->deviceDescriptor;
+ myUsbDevice.configDescriptor = 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,
+ SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC),
+ uint16_t byteCount,
+ bool callback)
+{
+ bool usbIntsEnabled;
+ SI_VARIABLE_SEGMENT_POINTER(ep, USBD_Ep_TypeDef, MEM_MODEL_SEG);
+
+ 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)
+{
+#if (!(SLAB_USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_FASTWAKE))
+ uint8_t i;
+#endif
+ bool regulatorEnabled, prefetchEnabled;
+#if SLAB_USB_REMOTE_WAKEUP_ENABLED
+ bool remoteWakeup = false;
+#endif
+
+ USB_SaveSfrPage();
+
+ // 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)
+ {
+ remoteWakeup = USBD_RemoteWakeupCb();
+ if (remoteWakeup == 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
+
+#if ((!(SLAB_USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF)) || \
+ (SLAB_USB_BUS_POWERED))
+ } while (USB_IsSuspended() == true);
+#else
+ } while ((USB_IsSuspended() == true) || (USB_IsVbusOn() == false));
+#endif
+ // Restore the internal regulator
+ if (regulatorEnabled == true)
+ {
+ USB_UnsuspendRegulator();
+ }
+
+ // Restore the prefetch engine
+ if (prefetchEnabled == true)
+ {
+ USB_EnablePrefetch();
+ }
+
+#if SLAB_USB_FULL_SPEED
+ // Restore the clock
+ USB_SetNormalClock();
+#endif
+ USB_EnableTransceiver();
+
+#if SLAB_USB_REMOTE_WAKEUP_ENABLED
+ // If the device woke from suspend due to a remote wakeup source, call
+ // USBD_RemoteWakeup() here to wake up the host.
+ if (remoteWakeup == true)
+ {
+ // Wake up the host
+ if (USBD_RemoteWakeup() == USB_STATUS_OK)
+ {
+ // If the remote wakeup succeeded, transition out of USB suspend state
+ USBD_SetUsbState(myUsbDevice.savedState);
+ }
+ }
+#endif
+ }
+
+ USB_RestoreSfrPage();
+}
+
+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,
+ SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC),
+ uint16_t byteCount,
+ bool callback)
+{
+ bool usbIntsEnabled;
+ SI_VARIABLE_SEGMENT_POINTER(ep, USBD_Ep_TypeDef, MEM_MODEL_SEG);
+
+ 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
+}
diff --git a/efm8/lib/c8051f380/efm8_usb/src/efm8_usbdch9.c b/efm8/lib/c8051f380/efm8_usb/src/efm8_usbdch9.c
new file mode 100644
index 0000000..6bb2a47
--- /dev/null
+++ b/efm8/lib/c8051f380/efm8_usb/src/efm8_usbdch9.c
@@ -0,0 +1,870 @@
+/**************************************************************************//**
+ * 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
+#include
+
+// -----------------------------------------------------------------------------
+// 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(SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC), uint16_t numBytes);
+
+// -----------------------------------------------------------------------------
+// Global Variables
+
+extern SI_SEGMENT_VARIABLE(myUsbDevice, USBD_Device_TypeDef, MEM_MODEL_SEG);
+const 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;
+ }
+
+ 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((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))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;
+ SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC);
+ 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 = (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))myUsbDevice.deviceDescriptor;
+ length = myUsbDevice.deviceDescriptor->bLength;
+ break;
+
+ case USB_CONFIG_DESCRIPTOR:
+ if (index != 0)
+ {
+ break;
+ }
+ dat = (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))myUsbDevice.configDescriptor;
+ length = le16toh(myUsbDevice.configDescriptor->wTotalLength);
+ break;
+
+ case USB_STRING_DESCRIPTOR:
+ #if (SLAB_USB_NUM_LANGUAGES == 1)
+
+ dat = (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))myUsbDevice.stringDescriptors[index];
+
+ // 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 = ((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))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 = ((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))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((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))&myUsbDevice.interfaceAltSetting[interface], 1);
+#else
+ // Alternate interfaces are not supported, so return 0x0000.
+ EP0_Write((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))&txZero, 1);
+#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((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))&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(SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC), uint16_t numBytes)
+{
+ if (myUsbDevice.ep0.state == D_EP_IDLE)
+ {
+ myUsbDevice.ep0.buf = dat;
+ myUsbDevice.ep0.remaining = numBytes;
+ myUsbDevice.ep0.state = D_EP_TRANSMITTING;
+ myUsbDevice.ep0.misc.c = 0;
+ }
+}
diff --git a/efm8/lib/c8051f380/efm8_usb/src/efm8_usbdep.c b/efm8/lib/c8051f380/efm8_usb/src/efm8_usbdep.c
new file mode 100644
index 0000000..2982658
--- /dev/null
+++ b/efm8/lib/c8051f380/efm8_usb/src/efm8_usbdep.c
@@ -0,0 +1,1028 @@
+/**************************************************************************//**
+ * 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
+#include
+
+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, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC), uint8_t fifoNum);
+static void USB_WriteFIFO_Generic(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC));
+
+#endif // #ifdef SI_GPTR
+
+#if (SLAB_USB_EP3OUT_USED && (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC))
+static void memclearXdata(SI_VARIABLE_SEGMENT_POINTER(s, uint8_t, SI_SEG_XDATA),
+ uint16_t n);
+#endif
+
+// -----------------------------------------------------------------------------
+// Functions
+
+/***************************************************************************//**
+ * @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, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC))
+{
+ 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, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC))
+{
+ 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.
+ ******************************************************************************/
+#if ((SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR))
+void handleUsbOut3Int(void)
+{
+ uint8_t count;
+ 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;
+ }
+ // 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;
+ }
+ else
+ {
+ USB_ReadFIFO(3, count, myUsbDevice.ep3out.buf);
+
+ myUsbDevice.ep3out.misc.bits.outPacketPending = false;
+ 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;
+ }
+
+ status = USB_STATUS_OK;
+ USB_EpnClearOutPacketReady();
+ }
+ if (myUsbDevice.ep3out.misc.bits.callback == true)
+ {
+ if (xferComplete == true)
+ {
+ myUsbDevice.ep3out.misc.bits.callback = false;
+ }
+
+ USBD_XferCompleteCb(EP3OUT, status, count, myUsbDevice.ep3out.remaining);
+ }
+ }
+}
+
+#elif (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC)
+void handleUsbOut3Int(void)
+{
+ uint16_t nextIdx;
+ uint16_t numZeroBytesFromCb;
+#if (SLAB_USB_EP3OUT_MAX_PACKET_SIZE > 255)
+ uint16_t count;
+#else
+ uint8_t count;
+#endif
+ USB_Status_TypeDef status = USB_STATUS_OK;
+ bool xferComplete = false;
+
+ USB_SetIndex(3);
+
+ if (USB_EpnOutGetSentStall())
+ {
+ USB_EpnOutClearSentStall();
+ }
+ else if (USB_EpnGetOutPacketReady())
+ {
+ count = USB_EpOutGetCount();
+
+ // If USBD_Read() has not been called, return an error
+ if (myUsbDevice.ep3out.state != D_EP_RECEIVING)
+ {
+ myUsbDevice.ep3out.misc.bits.outPacketPending = true;
+ status = USB_STATUS_EP_ERROR;
+ }
+ else
+ {
+ // DATERR bit set (i.e. CRC/bit-stuffing error)
+ if (USB_EpnGetDataError()
+ #ifdef SLAB_USB_ISOC_OUT_MIN_PACKET_SIZE
+ || (count < SLAB_USB_ISOC_OUT_MIN_PACKET_SIZE)
+ #endif
+ #ifdef SLAB_USB_ISOC_OUT_MAX_PACKET_SIZE
+ || (count > SLAB_USB_ISOC_OUT_MAX_PACKET_SIZE)
+ #endif
+ )
+ {
+ status = USB_STATUS_DATA_ERROR;
+ }
+
+#ifdef SLAB_USB_ISOC_OUT_PACKETSIZE_MOD2
+ if ((count % 2) != 0)
+ {
+ status = USB_STATUS_DATA_ERROR;
+ }
+#elif defined SLAB_USB_ISOC_OUT_PACKETSIZE_MOD4
+ if (( count % 4) != 0)
+ {
+ status = USB_STATUS_DATA_ERROR;
+ }
+#elif defined SLAB_USB_ISOC_OUT_PACKETSIZE_MOD6
+ if (count % 6) != 0)
+ {
+ status = USB_STATUS_DATA_ERROR;
+ }
+#endif
+
+ if (status == USB_STATUS_DATA_ERROR)
+ {
+ count = 0;
+ // Flush FIFO to get rid of bad packet
+ USB_EpnOutFlush();
+ myUsbDevice.ep3out.misc.bits.outPacketPending = false;
+ // Flush clears OPRDY, so no need to call USB_EpnClearOutPacketReady() now
+ }
+ else // No data error
+ {
+ nextIdx = count + myUsbDevice.ep3outIsoIdx;
+
+ // In isochronous mode, a circular buffer is used to hold the data
+ // If the next index into the circular buffer passes the end of the
+ // buffer, make two calls to USB_ReadFIFOIso()
+ if (nextIdx > myUsbDevice.ep3out.remaining)
+ {
+ USB_ReadFIFOIso(3, myUsbDevice.ep3out.remaining - myUsbDevice.ep3outIsoIdx, &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx]);
+ myUsbDevice.ep3outIsoIdx = nextIdx - myUsbDevice.ep3out.remaining;
+ USB_ReadFIFOIso(3, myUsbDevice.ep3outIsoIdx, myUsbDevice.ep3out.buf);
+ }
+ else
+ {
+ USB_ReadFIFOIso(3, count, &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx]);
+ myUsbDevice.ep3outIsoIdx = nextIdx;
+ }
+
+ myUsbDevice.ep3out.misc.bits.outPacketPending = false;
+ USB_EpnClearOutPacketReady();
+ }
+ }
+
+ if (myUsbDevice.ep3out.misc.bits.callback == true)
+ {
+ if (xferComplete == true)
+ {
+ myUsbDevice.ep3out.misc.bits.callback = false;
+ }
+
+ // In Isochronous mode, the meaning of the USBD_XferCompleteCb parameters changes:
+ // xferred is the number of bytes received in the last packet
+ // remaining is the current index into the circular buffer
+ numZeroBytesFromCb = USBD_XferCompleteCb(EP3OUT, status, count, myUsbDevice.ep3outIsoIdx);
+
+ // If data error occurred, the callback return value specifies how many zero-valued bytes to queue
+ if (numZeroBytesFromCb && (status == USB_STATUS_DATA_ERROR))
+ {
+ uint16_t numZeroBytesToWrite;
+ SI_SEGMENT_VARIABLE_SEGMENT_POINTER(bufPtr,
+ uint8_t,
+ SI_SEG_XDATA,
+ SI_SEG_DATA);
+
+ // Clear status after calling USBD_XferCompleteCb()
+ status = USB_STATUS_OK;
+
+ // Add the specified number of zero-value bytes
+ nextIdx = numZeroBytesFromCb + myUsbDevice.ep3outIsoIdx;
+
+ // Next index is past the end of the buffer (requires two writes)
+ if (nextIdx > myUsbDevice.ep3out.remaining)
+ {
+ // Write up to the end of the buffer
+ numZeroBytesToWrite = myUsbDevice.ep3out.remaining - myUsbDevice.ep3outIsoIdx;
+ bufPtr = &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx];
+ memclearXdata(bufPtr, numZeroBytesToWrite);
+
+ // Write the rest, starting at beginning of buffer
+ myUsbDevice.ep3outIsoIdx = nextIdx - myUsbDevice.ep3out.remaining;
+ numZeroBytesToWrite = myUsbDevice.ep3outIsoIdx;
+ bufPtr = &myUsbDevice.ep3out.buf[0];
+ memclearXdata(bufPtr, numZeroBytesToWrite);
+ }
+ // Next index is not past the end of the buffer
+ else
+ {
+ bufPtr = &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx];
+ memclearXdata(bufPtr, numZeroBytesFromCb);
+ myUsbDevice.ep3outIsoIdx = nextIdx;
+ }
+ }
+ }
+ }
+}
+
+/***************************************************************************//**
+ * @brief Sets all elements in a contiguous array of XDATA to zero
+ * @param s
+ * Pointer to the block of memory to fill
+ * @param n
+ * Number of bytes to be set to the value
+ ******************************************************************************/
+static void memclearXdata(SI_VARIABLE_SEGMENT_POINTER(s, uint8_t, SI_SEG_XDATA),
+ uint16_t n)
+{
+ while (n)
+ {
+ *s++ = 0;
+ n--;
+ }
+}
+
+#endif // #if ((SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR))
+#endif // EP3OUT_USED
+
+/***************************************************************************//**
+ * @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, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC))
+{
+ 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, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_IDATA))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, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_XDATA))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, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC), 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, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_IDATA))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, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_XDATA))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, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_CODE))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, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC), 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, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC))
+{
+ while (numBytes--)
+ {
+ USB_SetFIFOByte(*dat);
+ dat++;
+ }
+}
+
+#endif // #ifdef SI_GPTR
diff --git a/efm8/lib/c8051f380/efm8_usb/src/efm8_usbdint.c b/efm8/lib/c8051f380/efm8_usb/src/efm8_usbdint.c
new file mode 100644
index 0000000..39d744f
--- /dev/null
+++ b/efm8/lib/c8051f380/efm8_usb/src/efm8_usbdint.c
@@ -0,0 +1,687 @@
+/**************************************************************************//**
+ * 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
+#include
+
+// -----------------------------------------------------------------------------
+// Global variables
+
+extern SI_SEGMENT_VARIABLE(myUsbDevice, USBD_Device_TypeDef, MEM_MODEL_SEG);
+extern SI_SEGMENT_VARIABLE(txZero[2], const uint8_t, SI_SEG_CODE);
+
+// -----------------------------------------------------------------------------
+// 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);
+
+#if SLAB_USB_UTF8_STRINGS == 1
+static uint8_t decodeUtf8toUcs2(
+ const uint8_t *pUtf8in,
+ SI_VARIABLE_SEGMENT_POINTER(pUcs2out, uint16_t, MEM_MODEL_SEG));
+#endif
+
+// -----------------------------------------------------------------------------
+// Functions
+
+/***************************************************************************//**
+ * @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_Status_TypeDef retVal = USB_STATUS_REQ_UNHANDLED;
+
+ 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
+ retVal = USBD_SetupCmdCb(&myUsbDevice.setup);
+
+ if (retVal == USB_STATUS_REQ_UNHANDLED)
+ {
+#endif
+ if (myUsbDevice.setup.bmRequestType.Type == USB_SETUP_TYPE_STANDARD)
+ {
+ retVal = USBDCH9_SetupCmd();
+ }
+#if SLAB_USB_SETUP_CMD_CB
+ }
+#endif
+
+ // Reset index to 0 in case the call to USBD_SetupCmdCb() or
+ // USBDCH9_SetupCmd() changed it.
+ USB_SetIndex(0);
+
+ // Put the Enpoint 0 hardware into the correct state here.
+ if (retVal == USB_STATUS_OK)
+ {
+ // If wLength is 0, there is no Data Phase
+ // Set both the Serviced Out Packet Ready and Data End bits
+ if (myUsbDevice.setup.wLength == 0)
+ {
+ USB_Ep0SetLastOutPacketReady();
+ }
+ // If wLength is non-zero, there is a Data Phase.
+ // Set only the Serviced Out Packet Ready bit.
+ else
+ {
+ USB_Ep0ServicedOutPacketReady();
+
+#if SLAB_USB_SETUP_CMD_CB
+ // If OUT packet but callback didn't set up a USBD_Read and we are expecting a
+ // data byte then we need to wait for the read to be setup and NACK packets until
+ // USBD_Read is called.
+ if ((myUsbDevice.setup.bmRequestType.Direction == USB_SETUP_DIR_OUT)
+ && (myUsbDevice.ep0.state != D_EP_RECEIVING))
+ {
+ myUsbDevice.ep0.misc.bits.waitForRead = true;
+ }
+#endif
+ }
+ }
+ // If the setup transaction detected an error, send a stall
+ else
+ {
+ SendEp0Stall();
+ }
+ }
+ 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)
+{
+ SI_VARIABLE_SEGMENT_POINTER(ptr, uint16_t, MEM_MODEL_SEG) = (SI_VARIABLE_SEGMENT_POINTER(, uint16_t, MEM_MODEL_SEG))&myUsbDevice.setup;
+
+ USB_ReadFIFO(0, 8, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))ptr);
+
+ // 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 the device is bus-powered, always put it in the Default state.
+ // If the device is self-powered and VBUS is present, put the device in the
+ // Default state. Otherwise, put it in the Attached state.
+#if (!SLAB_USB_BUS_POWERED) && \
+ (!(SLAB_USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF))
+ if (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,
+ // unpack it by inserting a zero between each character in the string.
+ if ((myUsbDevice.ep0String.encoding.type == USB_STRING_DESCRIPTOR_UTF16LE_PACKED)
+#if SLAB_USB_UTF8_STRINGS == 1
+ || (myUsbDevice.ep0String.encoding.type == USB_STRING_DESCRIPTOR_UTF8)
+#endif
+ )
+ {
+ // If ep0String.encoding.init is true, this is the beginning of the string.
+ // The first two bytes of the string are the bLength and bDescriptorType
+ // fields. These are not packed like the reset of the string, so write them
+ // 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++)
+ {
+#if SLAB_USB_UTF8_STRINGS == 1
+ if (myUsbDevice.ep0String.encoding.type == USB_STRING_DESCRIPTOR_UTF8)
+ {
+ SI_SEGMENT_VARIABLE(ucs2, uint16_t, MEM_MODEL_SEG);
+ uint8_t utf8count;
+
+ // decode the utf8 into ucs2 for usb string
+ utf8count = decodeUtf8toUcs2(myUsbDevice.ep0.buf, &ucs2);
+
+ // if consumed utf8 bytes is 0, it means either null byte was
+ // input or bad utf8 byte sequence. Either way its an error and
+ // there's not much we can do. So just advance the input string
+ // by one character and keep going until count is expired.
+ if (utf8count == 0)
+ {
+ utf8count = 1;
+ }
+
+ // adjust to next char in utf8 byte sequence
+ myUsbDevice.ep0.buf += utf8count;
+ ucs2 = htole16(ucs2); // usb 16-bit chars are little endian
+ USB_WriteFIFO(0, 2, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))&ucs2, false);
+ }
+ else
+#endif
+ {
+ USB_WriteFIFO(0, 1, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))myUsbDevice.ep0.buf, false);
+ myUsbDevice.ep0.buf++;
+ USB_WriteFIFO(0, 1, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))&txZero, false);
+ }
+ }
+ }
+ // 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();
+}
+
+#if SLAB_USB_UTF8_STRINGS == 1
+/***************************************************************************//**
+ * Decodes UTF-8 to UCS-2 (16-bit) character encoding that is used
+ * for USB string descriptors.
+ *
+ * @param pUtf8in pointer to next character in UTF-8 string
+ * @param pUcs2out pointer to location for 16-bit character output
+ *
+ * Decodes a UTF-8 byte sequence into a single UCS-2 character. This
+ * will only decode up to 16-bit code point and will not handle the
+ * 21-bit case (4 bytes input).
+ *
+ * For valid cases, the UTF8 character sequence decoded into a 16-bit
+ * character and stored at the location pointed at by _pUcs2out_.
+ * The function will then return the number of input bytes that were
+ * consumed (1, 2, or 3). The caller can use the return value to find
+ * the start of the next character sequence in a utf-8 string.
+ *
+ * If either of the input pointers are NULL, then 0 is returned.
+ *
+ * If the first input character is NULL, then the output 16-bit value
+ * will be set to NULL and the function will return 0.
+ *
+ * If any other invalid sequence is detected, then the 16-bit output
+ * will be set to the equivalent of the question mark character (0x003F)
+ * and the return code will be 0.
+ *
+ * @return count of UTF8 bytes consumed
+ ******************************************************************************/
+static uint8_t decodeUtf8toUcs2(
+ const uint8_t *pUtf8in,
+ SI_VARIABLE_SEGMENT_POINTER(pUcs2out, uint16_t, MEM_MODEL_SEG))
+{
+ uint8_t ret = 0;
+
+ // check the input pointers
+ if (!pUtf8in || !pUcs2out)
+ {
+ return 0;
+ }
+
+ // set default decode to error '?';
+ *pUcs2out = '?';
+
+ // valid cases:
+ // 0xxxxxxx (7 bits)
+ // 110xxxxx 10xxxxxx (11 bits)
+ // 1110xxxx 10xxxxxx 10xxxxxx (16 bits)
+
+ // null input
+ if (pUtf8in[0] == 0)
+ {
+ *pUcs2out = 0;
+ ret = 0;
+ }
+
+ // 7-bit char
+ else if (pUtf8in[0] < 128)
+ {
+ *pUcs2out = pUtf8in[0];
+ ret = 1;
+ }
+
+ // 11-bit char
+ else if ((pUtf8in[0] & 0xE0) == 0xC0)
+ {
+ if ((pUtf8in[1] & 0xC0) == 0x80)
+ {
+ *pUcs2out = ((pUtf8in[0] & 0x1F) << 6) | (pUtf8in[1] & 0x3F);
+ ret = 2;
+ }
+ }
+
+ // 16-bit char
+ else if ((pUtf8in[0] & 0xF0) == 0xE0)
+ {
+ if ((pUtf8in[1] & 0xC0) == 0x80)
+ {
+ if ((pUtf8in[2] & 0xC0) == 0x80)
+ {
+ *pUcs2out = ((pUtf8in[0] & 0x0F) << 12)
+ | ((pUtf8in[1] & 0x3F) << 6)
+ | (pUtf8in[2] & 0x3F);
+ ret = 3;
+ }
+ }
+ }
+
+ return ret;
+}
+#endif // SLAB_USB_UTF8_STRINGS
+
+// This function is called from USBD_Init(). It forces the user project to pull
+// this module from the library so that the declared ISR can be seen and
+// included. If this is not done then this entire module by never be included
+// and the ISR will not be present.
+void forceModuleLoad_usbint(void){}
diff --git a/efm8/lib/c8051f380/efm8ub1/peripheralDrivers/inc/usb_0.h b/efm8/lib/c8051f380/efm8ub1/peripheralDrivers/inc/usb_0.h
new file mode 100644
index 0000000..d094fde
--- /dev/null
+++ b/efm8/lib/c8051f380/efm8ub1/peripheralDrivers/inc/usb_0.h
@@ -0,0 +1,2091 @@
+/***************************************************************************//**
+ * Copyright (c) 2015 by Silicon Laboratories Inc. All rights reserved.
+ *
+ * http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt
+ ******************************************************************************/
+
+#ifndef __SILICON_LABS_EFM8_USB_0_H__
+#define __SILICON_LABS_EFM8_USB_0_H__
+
+#include "SI_EFM8UB1_Register_Enums.h"
+#include
+#include
+
+/******************************************************************************/
+
+/**
+ *
+ * @addtogroup usb_0_group USB0 Driver
+ * @{
+ *
+ * @brief Peripheral driver for USB 0
+ *
+ * # Introduction #
+ *
+ * This module provides an API for using the USB0 peripheral.
+ * The API provides access to the USB hardware. A full-featured
+ * USB stack (EFM8 USB Library) is available in the SDK at "\lib\efm8_usb."
+ * The primary purpose of this USB peripheral driver is to abstract hardware
+ * accesses so that the EFM8 USB Library can run on multiple EFM8 devices
+ * (e.g. EFM8UB1, EFM8UB2). However, this driver can also be used to build
+ * custom USB stacks and applications in cases where greater optimization or
+ * performance than what the EFM8 USB Library provides is required.
+ *
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @addtogroup usb_0_runtime USB0 Runtime API
+ * @brief
+ * Functions and macros to access the USB hardware.
+ * @{
+ ******************************************************************************/
+
+// -------------------------------
+// Macros
+
+/***************************************************************************//**
+ * @brief Reads an indirect USB register
+ * @details Sets USB0ADR and polls on the busy bit.
+ * When the macro completes, the value can be read from USB0DAT.
+ * @param addr
+ * The address of the USB indirect register to read
+ * @return The value of the USB indirect register is held in USB0DAT.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern uint8_t USB_READ_BYTE(uint8_t addr);
+#else
+#define USB_READ_BYTE(addr) \
+ do \
+ { \
+ USB0ADR = (USB0ADR_BUSY__SET | (addr)); \
+ while (USB0ADR & USB0ADR_BUSY__SET) {} \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Writes an indirect USB register
+ * @details Sets USB0ADR, writes a value to USB0DAT, and waits for the busy
+ * bit to clear.
+ * @param addr
+ * The address of the USB indirect register to read
+ * @param dat
+ * The value to write to the USB indirect register
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_WRITE_BYTE(uint8_t addr, uint8_t dat);
+#else
+#define USB_WRITE_BYTE(addr, dat) \
+ do \
+ { \
+ USB0ADR = (addr); \
+ USB0DAT = (dat); \
+ while (USB0ADR & USB0ADR_BUSY__SET) {} \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Sets bits in an indirect USB register
+ * @details Sets the bits in the bitmask of the indirect USB register
+ * without disturbing the value of other bits in the indirect
+ * register.
+ * @param addr
+ * The address of the USB indirect register to write
+ * @param bitmask
+ * The bits to set
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SET_BITS(uint8_t addr, uint8_t bitmask);
+#else
+#define USB_SET_BITS(addr, bitmask) \
+ do \
+ { \
+ USB0ADR = (USB0ADR_BUSY__SET | (addr)); \
+ while (USB0ADR & USB0ADR_BUSY__SET) {} \
+ USB0DAT = (USB0DAT | (bitmask)); \
+ while (USB0ADR & USB0ADR_BUSY__SET) {} \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Clears bits in an indirect USB register
+ * @details Clears the bits in the bitmask of an indirect USB register
+ * without disturbing the value of other bits in the indirect
+ * register.
+ * @param addr
+ * The address of the USB indirect register to write
+ * @param bitmask
+ * The bits to clear
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_CLEAR_BITS(uint8_t addr, uint8_t bitmask);
+#else
+#define USB_CLEAR_BITS(addr, bitmask) \
+ do \
+ { \
+ USB0ADR = (USB0ADR_BUSY__SET | (addr)); \
+ while (USB0ADR & USB0ADR_BUSY__SET) {} \
+ USB0DAT = (USB0DAT & ~(bitmask)); \
+ while (USB0ADR & USB0ADR_BUSY__SET) {} \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables USB interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableInts(void);
+#else
+#define USB_EnableInts() \
+ do \
+ { \
+ SFRPAGE = PG2_PAGE; \
+ EIE2 |= EIE2_EUSB0__ENABLED; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables USB interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableInts(void);
+#else
+#define USB_DisableInts() \
+ do \
+ { \
+ SFRPAGE = PG2_PAGE; \
+ EIE2 &= ~EIE2_EUSB0__ENABLED; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Returns state of USB interrupt enabler
+ * @return TRUE if USB interrupts are enabled, FALSE otherwise.
+ ******************************************************************************/
+extern bool USB_GetIntsEnabled(void);
+
+/***************************************************************************//**
+ * @brief Enables VBUS detection
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_VbusDetectEnable(void);
+#else
+#define USB_VbusDetectEnable() \
+ do \
+ { \
+ SFRPAGE = PG3_PAGE; \
+ USB0CF |= USB0CF_VBUSEN__ENABLED; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables VBUS detection
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_VbusDetectDisable(void);
+#else
+#define USB_VbusDetectDisable() \
+ do \
+ { \
+ SFRPAGE = PG3_PAGE; \
+ USB0CF &= ~USB0CF_VBUSEN__ENABLED; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Check status of VBUS signal
+ * @return TRUE if VBUS signal is present, FALSE otherwise.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern bool USB_IsVbusOn(void);
+#else
+#define USB_IsVbusOn() ((bool) P3_B1)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables the USB pull-up resistor
+ * @details Enables either the D+ or the D- pull-up resistor, depending on
+ * whether @ref USB_SelectFullSpeed() or @ref USB_SelectLowSpeed()
+ * was previously called.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnablePullUpResistor(void);
+#else
+#define USB_EnablePullUpResistor() \
+ do \
+ { \
+ SFRPAGE = PG3_PAGE; \
+ USB0XCN |= USB0XCN_PREN__PULL_UP_ENABLED; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables the USB pull-up resistor
+ * @details Disables either the D+ or the D- pull-up resistor, depending on
+ * whether @ref USB_SelectFullSpeed() or @ref USB_SelectLowSpeed()
+ * was previously called.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisablePullUpResistor(void);
+#else
+#define USB_DisablePullUpResistor() \
+ do \
+ { \
+ SFRPAGE = PG3_PAGE; \
+ USB0XCN &= ~USB0XCN_PREN__PULL_UP_ENABLED; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables the USB transceiver
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableTransceiver(void);
+#else
+#define USB_EnableTransceiver() \
+ do \
+ { \
+ SFRPAGE = PG3_PAGE; \
+ USB0XCN |= USB0XCN_PHYEN__ENABLED; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables the USB transceiver
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableTransceiver(void);
+#else
+#define USB_DisableTransceiver() \
+ do \
+ { \
+ SFRPAGE = PG3_PAGE; \
+ USB0XCN &= ~USB0XCN_PHYEN__ENABLED; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Puts the USB in full-speed mode.
+ * @details Configures the USB to operate as a full-speed device by
+ * enabling the D+ pull-up resistor. After calling this
+ * function, the user must call @ref USB_EnablePullUpResistor().
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SelectFullSpeed(void);
+#else
+#define USB_SelectFullSpeed() \
+ do \
+ { \
+ SFRPAGE = PG3_PAGE; \
+ USB0XCN |= USB0XCN_SPEED__FULL_SPEED; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Puts the USB in low-speed mode.
+ * @details Configures the USB to operate as a low-speed device by
+ * enabling the D- pull-up resistor. After calling this
+ * function, the user must call @ref USB_EnablePullUpResistor().
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SelectLowSpeed(void);
+#else
+#define USB_SelectLowSpeed() \
+ do \
+ { \
+ SFRPAGE = PG3_PAGE; \
+ USB0XCN &= ~USB0XCN_SPEED__FULL_SPEED; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Suspends the transceiver
+ * @details Puts the USB transceiver in suspend mode.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SuspendTransceiver(void);
+#else
+#define USB_SuspendTransceiver() \
+ do \
+ { \
+ SFRPAGE = PG3_PAGE; \
+ USB0XCN &= ~(USB0XCN_PHYEN__ENABLED | USB0XCN_Dp__HIGH | USB0XCN_Dn__HIGH);\
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Selects the internal oscillator as the USB clock
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetClockIntOsc(void);
+#else
+#define USB_SetClockIntOsc() \
+ do \
+ { \
+ SFRPAGE = PG3_PAGE; \
+ USB0CF &= ~USB0CF_USBCLK__FMASK; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Selects the internal oscillator / 8 as the USB clock
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetClockIntOscDiv8(void);
+#else
+#define USB_SetClockIntOscDiv8() \
+ do \
+ { \
+ SFRPAGE = PG3_PAGE; \
+ USB0CF &= ~USB0CF_USBCLK__FMASK; \
+ USB0CF |= USB0CF_USBCLK__HFOSC1_DIV_8; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Selects the external oscillator as the USB clock
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetClockExtOsc(void);
+#else
+#define USB_SetClockExtOsc() \
+ do \
+ { \
+ SFRPAGE = PG3_PAGE; \
+ USB0CF &= ~USB0CF_USBCLK__FMASK; \
+ USB0CF |= USB0CF_USBCLK__EXTOSC; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Selects the external oscillator / 2 as the USB clock
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetClockExtOscDiv2(void);
+#else
+#define USB_SetClockExtOscDiv2() \
+ do \
+ { \
+ SFRPAGE = PG3_PAGE; \
+ USB0CF &= ~USB0CF_USBCLK__FMASK; \
+ USB0CF |= USB0CF_USBCLK__EXTOSC_DIV_2; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Selects the external oscillator / 3 as the USB clock
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetClockExtOscDiv3(void);
+#else
+#define USB_SetClockExtOscDiv3() \
+ do \
+ { \
+ SFRPAGE = PG3_PAGE; \
+ USB0CF &= ~USB0CF_USBCLK__FMASK; \
+ USB0CF |= USB0CF_USBCLK__EXTOSC_DIV_3; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Selects the external oscillator / 4 as the USB clock
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetClockExtOscDiv4(void);
+#else
+#define USB_SetClockExtOscDiv4() \
+ do \
+ { \
+ SFRPAGE = PG3_PAGE; \
+ USB0CF &= ~USB0CF_USBCLK__FMASK; \
+ USB0CF |= USB0CF_USBCLK__EXTOSC_DIV_4; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Selects the low-frequency oscillator as the USB clock
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetClockLfo(void);
+#else
+#define USB_SetClockLfo() \
+ do \
+ { \
+ SFRPAGE = PG3_PAGE; \
+ USB0CF &= ~USB0CF_USBCLK__FMASK; \
+ USB0CF |= USB0CF_USBCLK__LFOSC; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Selects the normal setting for the USB clock
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetNormalClock(void);
+#else
+#define USB_SetNormalClock() USB_SetClockIntOsc()
+#endif
+
+/***************************************************************************//**
+ * @brief Selects the low-power setting for the USB clock
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetSuspendClock(void);
+#else
+#define USB_SetSuspendClock() USB_SetClockIntOscDiv8()
+#endif
+
+/***************************************************************************//**
+ * @brief Suspends REG1
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SuspendRegulator(void);
+#else
+#define USB_SuspendRegulator() \
+ do \
+ { \
+ SFRPAGE = PG3_PAGE; \
+ REG1CN |= REG1CN_SUSEN__SUSPEND; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Does not use regulator low-power modes
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SuspendRegulatorFastWake(void);
+#else
+#define USB_SuspendRegulatorFastWake()
+#endif
+
+/***************************************************************************//**
+ * @brief Takes REG0 and REG1 out of suspend
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_UnsuspendRegulator(void);
+#else
+#define USB_UnsuspendRegulator() \
+ do \
+ { \
+ SFRPAGE = PG3_PAGE; \
+ REG1CN &= ~REG1CN_SUSEN__SUSPEND; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Determine if the internal regulator is enabled
+ * @return TRUE if the internal regulator is enabled, FALSE otherwise
+ ******************************************************************************/
+extern bool USB_IsRegulatorEnabled(void);
+
+/***************************************************************************//**
+ * @brief Disable the prefetch engine
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisablePrefetch(void);
+#else
+#define USB_DisablePrefetch() \
+ do \
+ { \
+ SFRPAGE = PG2_PAGE; \
+ PFE0CN &= ~(PFE0CN_PFEN__ENABLED | PFE0CN_FLRT__SYSCLK_BELOW_50_MHZ); \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Enable the prefetch engine
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnablePrefetch(void);
+#else
+#define USB_EnablePrefetch() \
+ do \
+ { \
+ SFRPAGE = PG2_PAGE; \
+ PFE0CN |= (PFE0CN_PFEN__ENABLED | PFE0CN_FLRT__SYSCLK_BELOW_50_MHZ); \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Determine if the prefetch engine is enabled
+ * @return TRUE if prefetch engine is enabled, FALSE otherwise.
+ ******************************************************************************/
+extern bool USB_IsPrefetchEnabled(void);
+
+/***************************************************************************//**
+ * @brief Suspends internal oscillator
+ ******************************************************************************/
+extern void USB_SuspendOscillator(void);
+
+/***************************************************************************//**
+ * @brief Enables clock recovery in full speed mode
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableFullSpeedClockRecovery(void);
+#else
+#define USB_EnableFullSpeedClockRecovery() \
+ USB_WRITE_BYTE(CLKREC, (CLKREC_CRE__ENABLED | 0x0F))
+#endif
+
+/***************************************************************************//**
+ * @brief Enables clock recovery in low speed mode
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableLowSpeedClockRecovery(void);
+#else
+#define USB_EnableLowSpeedClockRecovery() \
+ USB_WRITE_BYTE(CLKREC, \
+ (CLKREC_CRE__ENABLED \
+ | CLKREC_CRLOW__LOW_SPEED \
+ | 0x0F))
+#endif
+
+/***************************************************************************//**
+ * @brief Disables clock recovery
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableClockRecovery(void);
+#else
+#define USB_DisableClockRecovery() USB_WRITE_BYTE(CLKREC, 0x0F)
+#endif
+
+/***************************************************************************//**
+ * @brief Sets the USB function address
+ * @param addr
+ * USB Function Address value
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetAddress(uint8_t addr);
+#else
+#define USB_SetAddress(addr) \
+ USB_WRITE_BYTE(FADDR, (FADDR_UPDATE__SET | (addr)))
+#endif
+
+/***************************************************************************//**
+ * @brief Disable the USB Inhibit feature
+ * @details The USB block is inhibited after a power-on-reset or an
+ * asynchronous reset. Software should disable the inhibit bit
+ * after all USB and transceiver initialization is complete.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableInhibit(void);
+#else
+#define USB_DisableInhibit() \
+ USB_WRITE_BYTE(POWER, (POWER_USBINH__ENABLED | POWER_SUSEN__ENABLED))
+#endif
+
+/***************************************************************************//**
+ * @brief Forces a USB reset
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_ForceReset(void);
+#else
+#define USB_ForceReset() USB_WRITE_BYTE(POWER, POWER_USBRST__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Forces USB resume signaling
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_ForceResume(void);
+#else
+#define USB_ForceResume() \
+ USB_WRITE_BYTE(POWER, (POWER_RESUME__START | POWER_SUSEN__ENABLED))
+#endif
+
+/***************************************************************************//**
+ * @brief Clears USB resume signaling
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_ClearResume(void);
+#else
+#define USB_ClearResume() USB_WRITE_BYTE(POWER, POWER_SUSEN__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables USB suspend detection
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableSuspendDetection(void);
+#else
+#define USB_EnableSuspendDetection() USB_WRITE_BYTE(POWER, POWER_SUSEN__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables USB suspend detection
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableSuspendDetection(void);
+#else
+#define USB_DisableSuspendDetection() USB_WRITE_BYTE(POWER, 0)
+#endif
+
+/***************************************************************************//**
+ * @brief Setup End Serviced
+ * @details Software should call this function after servicing a Setup End
+ * event. Setup End is detected by calling usbGetSetupEnd
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_ServicedSetupEnd(void);
+#else
+#define USB_ServicedSetupEnd() \
+ USB_WRITE_BYTE(E0CSR, E0CSR_SSUEND__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Out Packet Ready Serviced
+ * @details Software should call this function after servicing a received
+ * Endpoint 0 packet.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_Ep0ServicedOutPacketReady(void);
+#else
+#define USB_Ep0ServicedOutPacketReady() \
+ USB_WRITE_BYTE(E0CSR, E0CSR_SOPRDY__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Sets In Packet Ready and Data End on Endpoint 0
+ * @details This should be called instead of @ref USB_Ep0SetInPacketReady()
+ * when sending the last packet of a setup data phase.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_Ep0SetLastInPacketReady(void);
+#else
+#define USB_Ep0SetLastInPacketReady() \
+ USB_WRITE_BYTE(E0CSR, (E0CSR_INPRDY__SET | E0CSR_DATAEND__SET))
+#endif
+
+/***************************************************************************//**
+ * @brief Sets In Packet Ready and Data End on Endpoint 0
+ * @details This should be called instead of @ref USB_Ep0SetInPacketReady()
+ * when sending a zero-length packet.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_Ep0SetZLPInPacketReady(void);
+#else
+#define USB_Ep0SetZLPInPacketReady() \
+ USB_WRITE_BYTE(E0CSR, (E0CSR_INPRDY__SET | E0CSR_DATAEND__SET))
+#endif
+
+/***************************************************************************//**
+ * @brief Serviced Out Packet Ready and Data End on Endpoint 0
+ * @details This should be called instead of @ref USB_ServicedSetupEnd()
+ * after servicing the last incoming data packet.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_Ep0SetLastOutPacketReady(void);
+#else
+#define USB_Ep0SetLastOutPacketReady() \
+ USB_WRITE_BYTE(E0CSR, (E0CSR_SOPRDY__SET | E0CSR_DATAEND__SET))
+#endif
+
+/***************************************************************************//**
+ * @brief Sends a stall on Endpoint 0
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_Ep0SendStall(void);
+#else
+#define USB_Ep0SendStall() \
+ USB_WRITE_BYTE(E0CSR, (E0CSR_SOPRDY__SET | E0CSR_SDSTL__SET))
+#endif
+
+/***************************************************************************//**
+ * @brief Clears sent stall condition on Endpoint 0
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_Ep0ClearSentStall(void);
+#else
+#define USB_Ep0ClearSentStall() USB_WRITE_BYTE(E0CSR, 0)
+#endif
+
+/***************************************************************************//**
+ * @brief Sets InPacketReady on Endpoint 0
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_Ep0SetInPacketReady(void);
+#else
+#define USB_Ep0SetInPacketReady() USB_WRITE_BYTE(E0CSR, E0CSR_INPRDY__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Returns state of USB Start-of-Frame Interrupt
+ * @param CMINT_snapshot
+ * Snapshot of the CMINT register taken previously with the
+ * @ref USB_GetCommonInts() function.
+ * @return TRUE if Start-of-Frame Interrupt is active, FALSE otherwise.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern bool USB_IsSofIntActive(uint8_t CMINT_snapshot);
+#else
+#define USB_IsSofIntActive(CMINT_snapshot) ((CMINT_snapshot) & CMINT_SOF__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Returns state of USB Reset Interrupt
+ * @param CMINT_snapshot
+ * Snapshot of the CMINT register taken previously with the
+ * @ref USB_GetCommonInts() function.
+ * @return TRUE if USB Reset Interrupt is active, FALSE otherwise.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern bool USB_IsResetIntActive(uint8_t CMINT_snapshot);
+#else
+#define USB_IsResetIntActive(CMINT_snapshot) \
+ ((CMINT_snapshot) & CMINT_RSTINT__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Returns state of USB Resume Interrupt
+ * @param CMINT_snapshot
+ * Snapshot of the CMINT register taken previously with the
+ * @ref USB_GetCommonInts() function.
+ * @return TRUE if USB Resume Interrupt is active, FALSE otherwise.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern bool USB_IsResumeIntActive(uint8_t CMINT_snapshot);
+#else
+#define USB_IsResumeIntActive(CMINT_snapshot) \
+ ((CMINT_snapshot) & CMINT_RSUINT__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Returns state of USB Suspend Interrupt
+ * @param CMINT_snapshot
+ * Snapshot of the CMINT register taken previously with the
+ * @ref USB_GetCommonInts() function.
+ * @return TRUE if USB Suspend Interrupt is active, FALSE otherwise.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern bool USB_IsSuspendIntActive(uint8_t CMINT_snapshot);
+#else
+#define USB_IsSuspendIntActive(CMINT_snapshot) \
+ ((CMINT_snapshot) & CMINT_SUSINT__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Returns state of USB Endpoint 0 Interrupt
+ * @param IN1INT_snapshot
+ * Snapshot of the IN1INT register taken previously with the
+ * @ref USB_GetInInts() function.
+ * @return TRUE if USB Endpoint 0 Interrupt is active, FALSE otherwise.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern bool USB_IsEp0IntActive(uint8_t IN1INT_snapshot);
+#else
+#define USB_IsEp0IntActive(IN1INT_snapshot) \
+ ((IN1INT_snapshot) & IN1INT_EP0__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Returns 1 if any USB IN Interrupt is active
+ * @param IN1INT_snapshot
+ * Snapshot of the IN1INT register taken previously with the
+ * @ref USB_GetInInts() function.
+ * @return TRUE if any USB IN Interrupt is active, FALSE otherwise.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern bool USB_IsInIntActive(uint8_t IN1INT_snapshot);
+#else
+#define USB_IsInIntActive(IN1INT_snapshot) \
+ ((IN1INT_snapshot) & (IN1INT_IN1__SET | IN1INT_IN2__SET | IN1INT_IN3__SET))
+#endif
+
+/***************************************************************************//**
+ * @brief Returns state of USB Endpoint 1 IN Interrupt
+ * @param IN1INT_snapshot
+ * Snapshot of the IN1INT register taken previously with the
+ * @ref USB_GetInInts() function.
+ * @return TRUE if USB Endpoint 1 IN Interrupt is active, FALSE otherwise.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern bool USB_IsIn1IntActive(uint8_t IN1INT_snapshot);
+#else
+#define USB_IsIn1IntActive(IN1INT_snapshot) \
+ ((IN1INT_snapshot) & IN1INT_IN1__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Returns state of USB Endpoint 2 IN Interrupt
+ * @param IN1INT_snapshot
+ * Snapshot of the IN1INT register taken previously with the
+ * @ref USB_GetInInts() function.
+ * @return TRUE if USB Endpoint 2 IN Interrupt is active, FALSE otherwise.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern bool USB_IsIn2IntActive(uint8_t IN1INT_snapshot);
+#else
+#define USB_IsIn2IntActive(IN1INT_snapshot) \
+ ((IN1INT_snapshot) & IN1INT_IN2__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Returns state of USB Endpoint 3 IN Interrupt
+ * @param IN1INT_snapshot
+ * Snapshot of the IN1INT register taken previously with the
+ * @ref USB_GetInInts() function.
+ * @return TRUE if USB Endpoint 3 IN Interrupt is active, FALSE otherwise.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern bool USB_IsIn3IntActive(uint8_t IN1INT_snapshot);
+#else
+#define USB_IsIn3IntActive(IN1INT_snapshot) \
+ ((IN1INT_snapshot) & IN1INT_IN3__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Returns 1 if any USB Endpoint OUT Interrupt is active
+ * @param OUT1INT_snapshot
+ * Snapshot of the OUT1INT register taken previously with the
+ * @ref USB_GetOutInts() function.
+ * @return TRUE if any USB OUT Interrupt is active, FALSE otherwise.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern bool USB_IsOutIntActive(uint8_t OUT1INT_snapshot);
+#else
+#define USB_IsOutIntActive(OUT1INT_snapshot) \
+ ((OUT1INT_snapshot) \
+ & (OUT1INT_OUT1__SET | OUT1INT_OUT2__SET | OUT1INT_OUT3__SET))
+#endif
+
+/***************************************************************************//**
+ * @brief Returns state of USB Endpoint 1 OUT Interrupt
+ * @param OUT1INT_snapshot
+ * Snapshot of the OUT1INT register taken previously with the
+ * @ref USB_GetOutInts() function.
+ * @return TRUE if USB Endpoint 1 OUT Interrupt is active,
+ * FALSE otherwise.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern bool USB_IsOut1IntActive(uint8_t OUT1INT_snapshot);
+#else
+#define USB_IsOut1IntActive(OUT1INT_snapshot) \
+ ((OUT1INT_snapshot) & OUT1INT_OUT1__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Returns state of USB Endpoint 2 OUT Interrupt
+ * @param OUT1INT_snapshot
+ * Snapshot of the OUT1INT register taken previously with the
+ * @ref USB_GetOutInts() function.
+ * @return TRUE if USB Endpoint 2 OUT Interrupt is active,
+ * FALSE otherwise.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern bool USB_IsOut2IntActive(uint8_t OUT1INT_snapshot);
+#else
+#define USB_IsOut2IntActive(OUT1INT_snapshot) \
+ ((OUT1INT_snapshot) & OUT1INT_OUT2__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Returns state of USB Endpoint 3 OUT Interrupt
+ * @param OUT1INT_snapshot
+ * Snapshot of the OUT1INT register taken previously with the
+ * @ref USB_GetOutInts() function.
+ * @return TRUE if USB Endpoint 3 OUT Interrupt is active,
+ * FALSE otherwise.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern bool USB_IsOut3IntActive(uint8_t OUT1INT_snapshot);
+#else
+#define USB_IsOut3IntActive(OUT1INT_snapshot) \
+ ((OUT1INT_snapshot) & OUT1INT_OUT3__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Sets the suspend interrupt flag to active
+ * @param CMINT_snapshot
+ * Snapshot of the CMINT register taken previously with the
+ * @ref USB_GetCommonInts() function.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetSuspendIntActive(uint8_t CMINT_snapshot);
+#else
+#define USB_SetSuspendIntActive(CMINT_snapshot) \
+ ((CMINT_snapshot) |= CMINT_SUSINT__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Sets the EP0 interrupt flag to active
+ * @param IN1INT_snapshot
+ * Snapshot of the IN1INT register taken previously with the
+ * @ref USB_GetInInts() function.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetEp0IntActive(uint8_t IN1INT_snapshot);
+#else
+#define USB_SetEp0IntActive(IN1INT_snapshot) \
+ ((IN1INT_snapshot) |= IN1INT_EP0__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Sets the IN 1 interrupt flag to active
+ * @param IN1INT_snapshot
+ * Snapshot of the IN1INT register taken previously with the
+ * @ref USB_GetInInts() function.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetIn1IntActive(uint8_t IN1INT_snapshot);
+#else
+#define USB_SetIn1IntActive(IN1INT_snapshot) \
+ ((IN1INT_snapshot) |= IN1INT_IN1__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Sets the IN 12interrupt flag to active
+ * @param IN1INT_snapshot
+ * Snapshot of the IN1INT register taken previously with the
+ * @ref USB_GetInInts() function.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetIn2IntActive(uint8_t IN1INT_snapshot);
+#else
+#define USB_SetIn2IntActive(IN1INT_snapshot) \
+ ((IN1INT_snapshot) |= IN1INT_IN2__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Sets the IN 3 interrupt flag to active
+ * @param IN1INT_snapshot
+ * Snapshot of the IN1INT register taken previously with the
+ * @ref USB_GetInInts() function.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetIn3IntActive(uint8_t IN1INT_snapshot);
+#else
+#define USB_SetIn3IntActive(IN1INT_snapshot) \
+ ((IN1INT_snapshot) |= IN1INT_IN3__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Sets the OUT 1 interrupt flag to active
+ * @param OUT1INT_snapshot
+ * Snapshot of the OUT1INT register taken previously with the
+ * @ref USB_GetOutInts() function.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetOut1IntActive(uint8_t OUT1INT_snapshot);
+#else
+#define USB_SetOut1IntActive(OUT1INT_snapshot) \
+ ((OUT1INT_snapshot) |= OUT1INT_OUT1__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Sets the OUT 2 interrupt flag to active
+ * @param OUT1INT_snapshot
+ * Snapshot of the OUT1INT register taken previously with the
+ * @ref USB_GetOutInts() function.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetOut2IntActive(uint8_t OUT1INT_snapshot);
+#else
+#define USB_SetOut2IntActive(OUT1INT_snapshot) \
+ ((OUT1INT_snapshot) |= OUT1INT_OUT2__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Sets the OUT 3 interrupt flag to active
+ * @param OUT1INT_snapshot
+ * Snapshot of the OUT1INT register taken previously with the
+ * @ref USB_GetOutInts() function.
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetOut3IntActive(uint8_t OUT1INT_snapshot);
+#else
+#define USB_SetOut3IntActive(OUT1INT_snapshot) \
+ ((OUT1INT_snapshot) |= OUT1INT_OUT3__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables USB Start-of-Frame, Reset, Resume, and
+ * Suspend Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableDeviceInts(void);
+#else
+#define USB_EnableDeviceInts() \
+ USB_WRITE_BYTE(CMIE, \
+ (CMIE_SOFE__ENABLED \
+ | CMIE_RSTINTE__ENABLED \
+ | CMIE_RSUINTE__ENABLED \
+ | CMIE_SUSINTE__ENABLED))
+#endif
+
+/***************************************************************************//**
+ * @brief Enables USB Start-of-Frame Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableSofInt(void);
+#else
+#define USB_EnableSofInt() USB_SET_BITS(CMIE, CMIE_SOFE__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables USB Start-of-Frame Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableSofInt(void);
+#else
+#define USB_DisableSofInt() USB_CLEAR_BITS(CMIE, CMIE_SOFE__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables USB Reset Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableResetInt(void);
+#else
+#define USB_EnableResetInt() USB_SET_BITS(CMIE, CMIE_RSTINTE__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables USB Reset Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableResetInt(void);
+#else
+#define USB_DisableResetInt() USB_CLEAR_BITS(CMIE, CMIE_RSTINTE__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables USB Resume Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableResumeInt(void);
+#else
+#define USB_EnableResumeInt() USB_SET_BITS(CMIE, CMIE_RSUINTE__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables USB Resume Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableResumeInt(void);
+#else
+#define USB_DisableResumeInt() USB_CLEAR_BITS(CMIE, CMIE_RSUINTE__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables USB Suspend Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableSuspendInt(void);
+#else
+#define USB_EnableSuspendInt() USB_SET_BITS(CMIE, CMIE_SUSINTE__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables USB Suspend Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableSuspendInt(void);
+#else
+#define USB_DisableSuspendInt() USB_CLEAR_BITS(CMIE, CMIE_SUSINTE__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables USB Endpoint 0 Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableEp0Int(void);
+#else
+#define USB_EnableEp0Int() USB_SET_BITS(IN1IE, IN1IE_EP0E__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables USB Endpoint 0 Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableEp0Int(void);
+#else
+#define USB_DisableEp0Int() USB_CLEAR_BITS(IN1IE, IN1IE_EP0E__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables USB Endpoint 1 IN Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableIn1Int(void);
+#else
+#define USB_EnableIn1Int() USB_SET_BITS(IN1IE, IN1IE_IN1E__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables USB Endpoint 1 IN Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableIn1Int(void);
+#else
+#define USB_DisableIn1Int() USB_CLEAR_BITS(IN1IE, IN1IE_IN1E__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables USB Endpoint 2 IN Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableIn2Int(void);
+#else
+#define USB_EnableIn2Int() USB_SET_BITS(IN1IE, IN1IE_IN2E__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables USB Endpoint 2 IN Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableIn2Int(void);
+#else
+#define USB_DisableIn2Int() USB_CLEAR_BITS(IN1IE, IN1IE_IN2E__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables USB Endpoint 3 IN Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableIn3Int(void);
+#else
+#define USB_EnableIn3Int() USB_SET_BITS(IN1IE, IN1IE_IN3E__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables USB Endpoint 3 IN Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableIn3Int(void);
+#else
+#define USB_DisableIn3Int() USB_CLEAR_BITS(IN1IE, IN1IE_IN3E__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables USB Endpoint 1 OUT Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableOut1Int(void);
+#else
+#define USB_EnableOut1Int() USB_SET_BITS(OUT1IE, OUT1IE_OUT1E__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables USB Endpoint 1 OUT Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableOut1Int(void);
+#else
+#define USB_DisableOut1Int() USB_CLEAR_BITS(OUT1IE, OUT1IE_OUT1E__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables USB Endpoint 2 OUT Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableOut2Int(void);
+#else
+#define USB_EnableOut2Int() USB_SET_BITS(OUT1IE, OUT1IE_OUT2E__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables USB Endpoint 2 OUT Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableOut2Int(void);
+#else
+#define USB_DisableOut2Int() USB_CLEAR_BITS(OUT1IE, OUT1IE_OUT2E__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables USB Endpoint 3 OUT Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableOut3Int(void);
+#else
+#define USB_EnableOut3Int() USB_SET_BITS(OUT1IE, OUT1IE_OUT3E__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables USB Endpoint 3 OUT Interrupts
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableOut3Int(void);
+#else
+#define USB_DisableOut3Int() USB_CLEAR_BITS(OUT1IE, OUT1IE_OUT3E__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables USB Endpoint 1
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableEp1(void);
+#else
+#define USB_EnableEp1() USB_SET_BITS(EENABLE, EENABLE_EEN1__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables USB Endpoint 1
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableEp1(void);
+#else
+#define USB_DisableEp1() USB_CLEAR_BITS(EENABLE, EENABLE_EEN1__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables USB Endpoint 2
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableEp2(void);
+#else
+#define USB_EnableEp2() USB_SET_BITS(EENABLE, EENABLE_EEN2__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables USB Endpoint 2
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableEp2(void);
+#else
+#define USB_DisableEp2() USB_CLEAR_BITS(EENABLE, EENABLE_EEN2__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables USB Endpoint 3
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableEp3(void);
+#else
+#define USB_EnableEp3() USB_SET_BITS(EENABLE, EENABLE_EEN3__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables USB Endpoint 3
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableEp3(void);
+#else
+#define USB_DisableEp3() USB_CLEAR_BITS(EENABLE, EENABLE_EEN3__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Configures Endpoint N for OUT
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnDirectionOut(void);
+#else
+#define USB_EpnDirectionOut() USB_CLEAR_BITS(EINCSRH, EINCSRH_DIRSEL__IN)
+#endif
+
+/***************************************************************************//**
+ * @brief Configures Endpoint N for IN
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnDirectionIn(void);
+#else
+#define USB_EpnDirectionIn() USB_SET_BITS(EINCSRH, EINCSRH_DIRSEL__IN)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables split mode on Endpoint N
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnEnableSplitMode(void);
+#else
+#define USB_EpnEnableSplitMode() \
+ USB_SET_BITS(EINCSRH, EINCSRH_SPLIT__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables split mode Endpoint N
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnDisableSplitMode(void);
+#else
+#define USB_EpnDisableSplitMode() \
+ USB_CLEAR_BITS(EINCSRH, EINCSRH_SPLIT__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Resets the IN endpoint data toggle to '0'
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnInClearDataToggle(void);
+#else
+#define USB_EpnInClearDataToggle() USB_SET_BITS(EINCSRL, EINCSRL_CLRDT__BMASK)
+#endif
+
+/***************************************************************************//**
+ * @brief Clears sent stall condition on Endpoint N IN
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnInClearSentStall(void);
+#else
+#define USB_EpnInClearSentStall() USB_WRITE_BYTE(EINCSRL, 0)
+#endif
+
+/***************************************************************************//**
+ * @brief Sends a stall for each IN token on Endpoint N
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnInStall(void);
+#else
+#define USB_EpnInStall() USB_WRITE_BYTE(EINCSRL, EINCSRL_SDSTL__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Stops stalling for each IN token on Endpoint N
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnInEndStall(void);
+#else
+#define USB_EpnInEndStall() USB_WRITE_BYTE(EINCSRL, 0)
+#endif
+
+/***************************************************************************//**
+ * @brief Stops stalling for each IN token on Endpoint N and clears
+ * the data toggle
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnInEndStallAndClearDataToggle(void);
+#else
+#define USB_EpnInEndStallAndClearDataToggle() \
+ USB_WRITE_BYTE(EINCSRL, EINCSRL_CLRDT__BMASK)
+#endif
+
+/***************************************************************************//**
+ * @brief Flushes In Endpoint N
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnInFlush(void);
+#else
+#define USB_EpnInFlush() \
+ do \
+ { \
+ USB_WRITE_BYTE(EINCSRL, EINCSRL_FLUSH__SET); \
+ do \
+ { \
+ USB_READ_BYTE(EINCSRL); \
+ } while (USB0DAT & EINCSRL_FLUSH__SET); \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Clears underrun condition on In Endpoint N
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnInClearUnderrun(void);
+#else
+#define USB_EpnInClearUnderrun() USB_CLEAR_BITS(EINCSRL, EINCSRL_UNDRUN__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Sets InPacketReady on In Endpoint N
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnSetInPacketReady(void);
+#else
+#define USB_EpnSetInPacketReady() USB_SET_BITS(EINCSRL, EINCSRL_INPRDY__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables double buffering on In Endpoint N
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnInEnableDoubleBuffer(void);
+#else
+#define USB_EpnInEnableDoubleBuffer() \
+ USB_SET_BITS(EINCSRH, EINCSRH_DBIEN__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables double buffering on In Endpoint N
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnInDisableDoubleBuffer(void);
+#else
+#define USB_EpnInDisableDoubleBuffer() \
+ USB_CLEAR_BITS(EINCSRH, EINCSRH_DBIEN__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Configures In Endpoint N for Interrupt/Bulk Mode
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnInEnableInterruptBulkMode(void);
+#else
+#define USB_EpnInEnableInterruptBulkMode() \
+ USB_CLEAR_BITS(EINCSRH, EINCSRH_ISO__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Configures In Endpoint N for Isochronous Mode
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnInEnableIsochronousMode(void);
+#else
+#define USB_EpnInEnableIsochronousMode() \
+ USB_SET_BITS(EINCSRH, EINCSRH_ISO__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables forced data toggle on In Endpoint N
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnInEnableForcedDataToggle(void);
+#else
+#define USB_EpnInEnableForcedDataToggle() \
+ USB_SET_BITS(EINCSRH, EINCSRH_FCDT__ALWAYS_TOGGLE)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables forced data toggle on In Endpoint N
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnInDisableForcedDataToggle(void);
+#else
+#define USB_EpnInDisableForcedDataToggle() \
+ USB_CLEAR_BITS(EINCSRH, EINCSRH_FCDT__ALWAYS_TOGGLE)
+#endif
+
+/***************************************************************************//**
+ * @brief Resets the OUT endpoint data toggle to '0'
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnOutClearDataToggle(void);
+#else
+#define USB_EpnOutClearDataToggle() \
+ USB_SET_BITS(EOUTCSRL, EOUTCSRL_CLRDT__BMASK)
+#endif
+
+/***************************************************************************//**
+ * @brief Clears sent stall condition on Endpoint N OUT
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnOutClearSentStall(void);
+#else
+#define USB_EpnOutClearSentStall() \
+ USB_CLEAR_BITS(EOUTCSRL, EOUTCSRL_STSTL__BMASK)
+#endif
+
+/***************************************************************************//**
+ * @brief Sends a stall for each OUT token on Endpoint N
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnOutStall(void);
+#else
+#define USB_EpnOutStall() \
+ USB_SET_BITS(EOUTCSRL, EOUTCSRL_SDSTL__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Stops stalling for each OUT token on Endpoint N
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnOutEndStall(void);
+#else
+#define USB_EpnOutEndStall() USB_CLEAR_BITS(EOUTCSRL, EOUTCSRL_SDSTL__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Stops stalling for each OUT token on Endpoint N and clears
+ * the data toggle
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnOutEndStallAndClearDataToggle(void);
+#else
+#define USB_EpnOutEndStallAndClearDataToggle() \
+ do \
+ { \
+ USB_READ_BYTE(EOUTCSRL); \
+ USB0DAT &= ~EOUTCSRL_SDSTL__SET; \
+ while (USB0ADR & USB0ADR_BUSY__SET) {} \
+ USB0DAT |= EOUTCSRL_CLRDT__BMASK; \
+ while (USB0ADR & USB0ADR_BUSY__SET) {} \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Flushes OUT Endpoint N
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnOutFlush(void);
+#else
+#define USB_EpnOutFlush() \
+ do \
+ { \
+ USB_WRITE_BYTE(EOUTCSRL, EOUTCSRL_FLUSH__SET); \
+ do \
+ { \
+ USB_READ_BYTE(EOUTCSRL); \
+ } while (USB0DAT & EOUTCSRL_FLUSH__SET); \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Clears overrun condition on OUT Endpoint N
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnOutClearOverrun(void);
+#else
+#define USB_EpnOutClearOverrun() USB_CLEAR_BITS(EOUTCSRL, EOUTCSRL_OVRUN__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Clears OutPacketReady on Endpoint N
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnClearOutPacketReady(void);
+#else
+#define USB_EpnClearOutPacketReady() \
+ USB_CLEAR_BITS(EOUTCSRL, EOUTCSRL_OPRDY__SET)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables double buffering on OUT Endpoint N
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnOutEnableDoubleBuffer(void);
+#else
+#define USB_EpnOutEnableDoubleBuffer() \
+ USB_SET_BITS(EOUTCSRH, EOUTCSRH_DBIEN__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables double buffering on OUT Endpoint N
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnOutDisableDoubleBuffer(void);
+#else
+#define USB_EpnOutDisableDoubleBuffer() \
+ USB_CLEAR_BITS(EOUTCSRH, EOUTCSRH_DBIEN__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Configures OUT Endpoint N for Interrupt/Bulk Mode
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnOutEnableInterruptBulkMode(void);
+#else
+#define USB_EpnOutEnableInterruptBulkMode() \
+ USB_CLEAR_BITS(EOUTCSRH, EOUTCSRH_ISO__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Configures OUT Endpoint N for Isochronous Mode
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EpnOutEnableIsochronousMode(void);
+#else
+#define USB_EpnOutEnableIsochronousMode() \
+ USB_SET_BITS(EOUTCSRH, EOUTCSRH_ISO__ENABLED)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables FIFO read
+ * @param fifoNum
+ * FIFO to read
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableReadFIFO(uint8_t fifoNum);
+#else
+#define USB_EnableReadFIFO(fifoNum) \
+ do \
+ { \
+ while (USB0ADR & USB0ADR_BUSY__SET) {} \
+ USB0ADR = (USB0ADR_BUSY__SET \
+ | USB0ADR_AUTORD__ENABLED \
+ | (FIFO0 | (fifoNum))); \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables FIFO read
+ * @param fifoNum
+ * FIFO that was read from
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableReadFIFO(uint8_t fifoNum);
+#else
+#define USB_DisableReadFIFO(fifoNum)
+#endif
+
+/***************************************************************************//**
+ * @brief Reads a byte from the FIFO
+ * @param readDat
+ * Memory location to write the byte read from the FIFO
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_GetFIFOByte(uint8_t *readDat);
+#else
+#define USB_GetFIFOByte(readDat) \
+ do \
+ { \
+ while (USB0ADR & USB0ADR_BUSY__SET) {} \
+ *(readDat) = USB0DAT; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Reads the last byte from the FIFO
+ * @details The last read must be done with the AUTORD bit cleared.
+ * This prevents the read from triggering another read
+ * immediately thereafter.
+ * @param readDat
+ * Memory location to write the byte read from the FIFO
+ * @param fifoNum
+ * FIFO to read
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_GetLastFIFOByte(uint8_t *readDat, uint8_t fifoNum);
+#else
+#define USB_GetLastFIFOByte(readDat, fifoNum) \
+ do \
+ { \
+ while (USB0ADR & USB0ADR_BUSY__SET) {} \
+ USB0ADR = (FIFO0 | (fifoNum));\
+ *(readDat) = USB0DAT; \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Enables FIFO write
+ * @param fifoNum
+ * FIFO to write
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_EnableWriteFIFO(uint8_t fifoNum);
+#else
+#define USB_EnableWriteFIFO(fifoNum) \
+ do \
+ { \
+ while (USB0ADR & USB0ADR_BUSY__SET) {} \
+ USB0ADR = (FIFO0 | (fifoNum)); \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Disables FIFO write
+ * @param fifoNum
+ * FIFO that was written to
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_DisableWriteFIFO(uint8_t fifoNum);
+#else
+#define USB_DisableWriteFIFO(fifoNum)
+#endif
+
+/***************************************************************************//**
+ * @brief Writes a byte to the FIFO
+ * @param writeDat
+ * Data to write to the FIFO
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SetFIFOByte(uint8_t writeDat);
+#else
+#define USB_SetFIFOByte(writeDat) \
+ do \
+ { \
+ while (USB0ADR & USB0ADR_BUSY__SET) {} \
+ USB0DAT = (writeDat); \
+ } while (0)
+#endif
+
+/***************************************************************************//**
+ * @brief Saves the current SFR page
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_SaveSfrPage();
+#else
+#define USB_SaveSfrPage() uint8_t SfrPageSave = SFRPAGE
+#endif
+
+/***************************************************************************//**
+ * @brief Restores the SFR page
+ * @note @ref USB_SaveSfrPage() must be called before calling this macro
+ * @note This function is implemented as a macro.
+ ******************************************************************************/
+#ifdef IS_DOXYGEN
+extern void USB_RestoreSfrPage();
+#else
+#define USB_RestoreSfrPage() SFRPAGE = SfrPageSave
+#endif
+
+// -------------------------------
+// Function Prototypes
+
+/***************************************************************************//**
+ * @brief Writes a value to INDEX
+ * @param epsel
+ * Endpoint index to target
+ ******************************************************************************/
+extern void USB_SetIndex(uint8_t epsel);
+
+/***************************************************************************//**
+ * @brief Reads the USB common interrupt register
+ * @return Value of CMINT
+ ******************************************************************************/
+extern uint8_t USB_GetCommonInts(void);
+
+/***************************************************************************//**
+ * @brief Reads the USB in interrupt register
+ * @return Value of IN1INT
+ ******************************************************************************/
+extern uint8_t USB_GetInInts(void);
+
+/***************************************************************************//**
+ * @brief Reads the out interrupt register
+ * @return Value of OUT1INT
+ ******************************************************************************/
+extern uint8_t USB_GetOutInts(void);
+
+/***************************************************************************//**
+ * @brief Reads the value in INDEX
+ * @return Value of INDEX
+ ******************************************************************************/
+extern uint8_t USB_GetIndex(void);
+
+/***************************************************************************//**
+ * @brief Determines if the USB is currently suspended
+ * @return TRUE if USB is in suspend mode
+ ******************************************************************************/
+extern bool USB_IsSuspended(void);
+
+/***************************************************************************//**
+ * @brief Gets Setup End state
+ * @return TRUE when a control transaction end before software has
+ * set the DATAEND bit.
+ ******************************************************************************/
+extern bool USB_GetSetupEnd(void);
+
+/***************************************************************************//**
+ * @brief Determines if STALL was send on Endpoint 0
+ * @return TRUE after a STALL was sent on Endpoint 0
+ ******************************************************************************/
+extern bool USB_Ep0SentStall(void);
+
+/***************************************************************************//**
+ * @brief Determines if Out Packet Ready is set on Endpoint 0
+ * @return TRUE if Out Packet Ready is set on Endpoint 0
+ ******************************************************************************/
+extern bool USB_Ep0InPacketReady(void);
+
+/***************************************************************************//**
+ * @brief Determines if In Packet Ready is set on Endpoint 0
+ * @return TRUE if In Packet Ready is set on Endpoint 0
+ ******************************************************************************/
+extern bool USB_Ep0OutPacketReady(void);
+
+/***************************************************************************//**
+ * @brief Gets Endpoint 0 data count
+ * @return Number of received data bytes in the Endpoint 0 FIFO
+ ******************************************************************************/
+extern uint8_t USB_Ep0GetCount(void);
+
+/***************************************************************************//**
+ * @brief Checks if stall was sent on IN Endpoint N
+ * @return TRUE if stall was sent on IN Endpoint N, FALSE otherwise
+ ******************************************************************************/
+extern bool USB_EpnInGetSentStall(void);
+
+/***************************************************************************//**
+ * @brief Checks if stall was sent on OUT Endpoint N
+ * @return TRUE if stall was sent on OUT Endpoint N, FALSE otherwise
+ ******************************************************************************/
+extern bool USB_EpnGetInPacketReady(void);
+
+/***************************************************************************//**
+ * @brief Checks if stall was sent on OUT Endpoint N
+ * @return TRUE if stall was sent on OUT Endpoint N, FALSE otherwise
+ ******************************************************************************/
+extern bool USB_EpnOutGetSentStall(void);
+
+/***************************************************************************//**
+ * @brief Gets OutPacketReady on OUT Endpoint N
+ * @return TRUE if OUTPacketReady is set, FALSE otherwise
+ ******************************************************************************/
+extern bool USB_EpnGetOutPacketReady(void);
+
+/***************************************************************************//**
+ * @brief Gets DataError on OUT Endpoint N
+ * @return TRUE if Data Error bit is set, FALSE otherwise
+ ******************************************************************************/
+extern bool USB_EpnGetDataError(void);
+
+/***************************************************************************//**
+ * @brief Gets number of bytes in the OUT FIFO
+ * OUT packet
+ * @return Number of bytes in the FIFO from the last received
+ * packet
+ ******************************************************************************/
+extern uint16_t USB_EpOutGetCount(void);
+
+/***************************************************************************//**
+ * @brief Reads the USB frame number
+ * @return The frame number on the most recent SOF packet
+ ******************************************************************************/
+extern uint16_t USB_GetSofNumber(void);
+
+/***************************************************************************//**
+ * @brief Aborts pending IN transactions on the selected endpoint
+ * @param fifoNum
+ * Endpoint to abort
+ ******************************************************************************/
+extern void USB_AbortInEp(uint8_t fifoNum);
+
+/***************************************************************************//**
+ * @brief Aborts pending OUT transactions on the selected endpoint
+ * @param fifoNum
+ * Endpoint to abort
+ ******************************************************************************/
+extern void USB_AbortOutEp(uint8_t fifoNum);
+
+/***************************************************************************//**
+ * @brief Activates the selected endpoint
+ * @param ep
+ * Endpoint to access
+ * @param packetSize
+ * Maximum packet size for endpoint
+ * @param inDir
+ * Set to 1 if endpoint is IN, 0 if it is OUT
+ * @param splitMode
+ * Set to 1 if endpoint is in split mode, 0 if it is not
+ * @param isoMode
+ * Set to 1 if endpoint is in isochronous mode, 0 if it is not
+ ******************************************************************************/
+extern void USB_ActivateEp(uint8_t ep,
+ uint16_t packetSize,
+ bool inDir,
+ bool splitMode,
+ bool isoMode);
+
+/** @} (end addtogroup usb_0_runtime USB0 Runtime API) */
+/** @} (end addtogroup usb_0_group USB0 Driver) */
+
+// -----------------------------------------------------------------------------
+// Error Checking
+
+// -------------------------------
+// Verify that the maximum packet size specified for an endpoint is not too
+// large for that endpoint
+
+#ifdef SLAB_USB_EP1IN_USED
+ #if SLAB_USB_EP1IN_USED
+ #if SLAB_USB_EP1IN_TRANSFER_TYPE == USB_EPTYPE_ISOC
+ #error Isochronous transfers are not supported on Endpoint 1.
+ #else // #if SLAB_USB_EP1IN_TRANSFER_TYPE == USB_EPTYPE_ISOC
+ #if SLAB_USB_EP1IN_MAX_PACKET_SIZE > 64
+ #error EP1IN packet size too large. Interrupt/Bulk packet size must be 64 bytes or less.
+ #endif // #if SLAB_USB_EP1IN_MAX_PACKET_SIZE > 64
+ #endif // #if SLAB_USB_EP1IN_TRANSFER_TYPE == USB_EPTYPE_ISOC
+ #endif // #if SLAB_USB_EP1IN_USED
+#endif // #ifdef SLAB_USB_EP1IN_USED
+
+#ifdef SLAB_USB_EP1OUT_USED
+ #if SLAB_USB_EP1OUT_USED
+ #if SLAB_USB_EP1OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC
+ #error Isochronous transfers are not supported on Endpoint 1.
+ #else // #if SLAB_USB_EP1OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC
+ #if SLAB_USB_EP1OUT_MAX_PACKET_SIZE > 64
+ #error EP1OUT packet size too large. Interrupt/Bulk packet size must be 64 bytes or less.
+ #endif // #if SLAB_USB_EP1OUT_MAX_PACKET_SIZE > 64
+ #endif // #if SLAB_USB_EP1OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC
+ #endif // #if SLAB_USB_EP1OUT_USED
+#endif // #ifdef SLAB_USB_EP1OUT_USED
+
+#ifdef SLAB_USB_EP2IN_USED
+ #if SLAB_USB_EP2IN_USED
+ #if SLAB_USB_EP2IN_TRANSFER_TYPE == USB_EPTYPE_ISOC
+ #error Isochronous transfers are not supported on Endpoint 2.
+ #else // #if SLAB_USB_EP2IN_TRANSFER_TYPE == USB_EPTYPE_ISOC
+ #if SLAB_USB_EP2IN_MAX_PACKET_SIZE > 64
+ #error EP2IN packet size too large. Interrupt/Bulk packet size must be 64 bytes or less.
+ #endif // #if SLAB_USB_EP2IN_MAX_PACKET_SIZE > 64
+ #endif // #if SLAB_USB_EP2IN_TRANSFER_TYPE == USB_EPTYPE_ISOC
+ #endif // #if SLAB_USB_EP2IN_USED
+#endif // #ifdef SLAB_USB_EP2IN_USED
+
+#ifdef SLAB_USB_EP2OUT_USED
+ #if SLAB_USB_EP2OUT_USED
+ #if SLAB_USB_EP2OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC
+ #error Isochronous transfers are not supported on Endpoint 2.
+ #else // #if SLAB_USB_EP2OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC
+ #if SLAB_USB_EP2OUT_MAX_PACKET_SIZE > 64
+ #error EP2OUT packet size too large. Interrupt/Bulk packet size must be 64 bytes or less.
+ #endif // #if SLAB_USB_EP2OUT_MAX_PACKET_SIZE > 64
+ #endif // #if SLAB_USB_EP2OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC
+ #endif // #if SLAB_USB_EP2OUT_USED
+#endif // #ifdef SLAB_USB_EP2OUT_USED
+
+#ifdef SLAB_USB_EP3IN_USED
+ #if SLAB_USB_EP3IN_USED
+ #if SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_ISOC
+ #if SLAB_USB_EP3OUT_USED
+ #if SLAB_USB_EP3IN_MAX_PACKET_SIZE > 256
+ #error EP3IN packet size too large. FIFO 3 split mode packet size must be 256 bytes or less.
+ #endif // #if SLAB_USB_EP3IN_MAX_PACKET_SIZE > 256
+ #else // #if SLAB_USB_EP3OUT_USED
+ #if SLAB_USB_EP3IN_MAX_PACKET_SIZE > 512
+ #error EP3IN packet size too large. FIFO 3 packet size must be 512 bytes or less.
+ #endif // #if SLAB_USB_EP3IN_MAX_PACKET_SIZE > 512
+ #endif // #if SLAB_USB_EP3OUT_USED
+ #else // #if SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_ISOC
+ #if SLAB_USB_EP3IN_MAX_PACKET_SIZE > 64
+ #error EP3IN packet size too large. Interrupt/Bulk packet size must be 64 bytes or less.
+ #endif // #if SLAB_USB_EP3IN_MAX_PACKET_SIZE > 64
+ #endif // #if SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_ISOC
+ #endif // #if SLAB_USB_EP3IN_USED
+#endif // #ifdef SLAB_USB_EP3IN_USED
+
+#ifdef SLAB_USB_EP3OUT_USED
+ #if SLAB_USB_EP3OUT_USED
+ #if SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC
+ #if SLAB_USB_EP3IN_USED
+ #if SLAB_USB_EP3OUT_MAX_PACKET_SIZE > 256
+ #error EP3OUT packet size too large. FIFO 3 split mode packet size must be 256 bytes or less.
+ #endif // #if SLAB_USB_EP3OUT_MAX_PACKET_SIZE > 256
+ #else // #if SLAB_USB_EP3IN_USED
+ #if SLAB_USB_EP3OUT_MAX_PACKET_SIZE > 512
+ #error EP3OUT packet size too large. FIFO 3 packet size must be 512 bytes or less.
+ #endif // #if SLAB_USB_EP3OUT_MAX_PACKET_SIZE > 512
+ #endif // #if SLAB_USB_EP3IN_USED
+ #else // #if SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC
+ #if SLAB_USB_EP3OUT_MAX_PACKET_SIZE > 64
+ #error EP3OUT packet size too large. Interrupt/Bulk packet size must be 64 bytes or less.
+ #endif // #if SLAB_USB_EP3OUT_MAX_PACKET_SIZE > 64
+ #endif // #if SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC
+ #endif // #if SLAB_USB_EP3OUT_USED
+#endif // #ifdef SLAB_USB_EP3OUT_USED
+
+#endif // __SILICON_LABS_EFM8_USB_0_H__
diff --git a/efm8/lib/c8051f380/efm8ub1/peripheralDrivers/src/usb_0.c b/efm8/lib/c8051f380/efm8ub1/peripheralDrivers/src/usb_0.c
new file mode 100644
index 0000000..91a03ea
--- /dev/null
+++ b/efm8/lib/c8051f380/efm8ub1/peripheralDrivers/src/usb_0.c
@@ -0,0 +1,238 @@
+/**************************************************************************//**
+ * 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
+#include
+
+/** @addtogroup usb_0_runtime USB0 Runtime API */
+
+// -----------------------------------------------------------------------------
+// Functions
+
+// -------------------------------
+// Utility Functions
+
+/**************************************************************************//**
+ * @brief Reads a 16-bit indirect USB register value
+ * @param [in] 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);
+}
+
+bool USB_EpnGetDataError(void)
+{
+ USB_READ_BYTE(EOUTCSRL);
+ return (bool)(USB0DAT & EOUTCSRL_DATERR__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) */
diff --git a/efm8/lib/efm8_assert/assert.c b/efm8/lib/efm8_assert/assert.c
index b9a65c7..e96edfd 100644
--- a/efm8/lib/efm8_assert/assert.c
+++ b/efm8/lib/efm8_assert/assert.c
@@ -3,10 +3,13 @@
*
* http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt
*****************************************************************************/
-
+
#ifndef NDEBUG
-void slab_Assert()
+void slab_Assert( const char * file, int line )
{
+ file = file;
+ line = line;
+
while ( 1 );
}
#endif
diff --git a/efm8/lib/efm8_assert/assert.h b/efm8/lib/efm8_assert/assert.h
index 5b951a5..d99ef84 100644
--- a/efm8/lib/efm8_assert/assert.h
+++ b/efm8/lib/efm8_assert/assert.h
@@ -51,9 +51,9 @@
#ifdef USER_ASSERT
#define SLAB_ASSERT(expr) ((expr) ? ((void)0) : USER_ASSERT( __FILE__, __LINE__ ))
#else
- void slab_Assert();
+ 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();}
+ #define SLAB_ASSERT(expr) if(expr){}else{slab_Assert( __FILE__, __LINE__ );}
#endif
#endif
diff --git a/efm8/lib/efm8_usb/Readme.txt b/efm8/lib/efm8_usb/Readme.txt
index 8bcff83..059e38b 100644
--- a/efm8/lib/efm8_usb/Readme.txt
+++ b/efm8/lib/efm8_usb/Readme.txt
@@ -20,7 +20,7 @@ Known Issues and Limitations:
Target and Tool Chain Information:
---------------------------------
-Target: EFM8UB1, EFM8UB2, EFM8UB3, EFM8UB4, C8051F320/1, C8051F326/7, C8051F34x, C8051F38x
+Target: EFM8UB1, EFM8UB2, C8051F320/1, C8051F326/7, C8051F34x, C8051F38x
Tool chain: Keil
File List:
@@ -51,13 +51,6 @@ Version 1.0.1
USB_PWRSAVE_MODE_FASTWAKE was enabled.
- Improved documentation of USB_PWRSAVE_MODE_FASTWAKE feature.
-Version 1.0.2
- - Added ability to detect short OUT packet in Isochronous mode and
- stuff the buffer with zeroes to keep isochronous stream in sync.
-
-Version 1.0.3
- - Added support for EFM8UB3 and EFM8UB4 devices.
-
-------------------------------------------------------------------------------
End Of File
-------------------------------------------------------------------------------
diff --git a/efm8/lib/efm8_usb/inc/efm8_usb.h b/efm8/lib/efm8_usb/inc/efm8_usb.h
index fe70a9c..2581ce3 100644
--- a/efm8/lib/efm8_usb/inc/efm8_usb.h
+++ b/efm8/lib/efm8_usb/inc/efm8_usb.h
@@ -21,7 +21,6 @@
*
* @section usb_device_contents Contents
*
- * @li @ref usb_device_library_revision
* @li @ref usb_device_intro
* @li @ref usb_device_api
* @li @ref usb_device_conf
@@ -29,9 +28,6 @@
* @li @ref usb_device_transfers
* @li @ref usb_device_pitfalls
*
- * @n @section usb_device_library_revision EFM8 USB Library Revision
- * Library Revision: 1.0.3
- *
* @n @section usb_device_intro Introduction
*
* The USB device protocol stack provides an API which makes it possible to
@@ -112,10 +108,11 @@
*
* @ref USBD_RemoteWakeup() @n
* Used in SUSPENDED state (see @ref USB_Status_TypeDef) to signal resume to
- * host. The function will be called automatically by the library if the
- * @ref USBD_RemoteWakeupCb() function returns true. The function will
- * also check that the host has sent a SET_FEATURE request to enable Remote
- * Wakeup before issuing the resume.
+ * host. It's the applications responsibility to adhere to the USB standard
+ * which states that a device can not signal resume before it has been
+ * SUSPENDED for at least 5 ms. The function will also check that the host
+ * has sent a SET_FEATURE request to enable Remote Wakeup before issuing the
+ * resume.
*
* @ref USBD_GetUsbState() @n
* Returns the device USB state (see @ref USBD_State_TypeDef). Refer to
@@ -263,16 +260,6 @@
* #define SLAB_USB_LANGUAGE USB_LANGID_ENUS
*
* // -----------------------------------------------------------------------------
- * // Enable use of UTF-8 strings for string descriptors.
- * // If this option is enabled then packed string descriptors that are created
- * // with UTF8_PACKED_STATIC_CONST_STRING_DESC() can be UTF-8 encoded and they
- * // will be decoded into UCS-2 16-bit wide character format used for USB string
- * // descriptors. If this feature is not needed then it can be disabled to save
- * // some code memory space.
- * // -----------------------------------------------------------------------------
- * #define SLAB_USB_UTF8_STRINGS 1
- *
- * // -----------------------------------------------------------------------------
* // Set the power saving mode
* //
* // SLAB_USB_PWRSAVE_MODE configures when the device will automatically enter
@@ -282,17 +269,9 @@
* // USB_PWRSAVE_MODE_ONSUSPEND - Enter USB power-save mode on USB suspend
* // USB_PWRSAVE_MODE_ONVBUSOFF - Enter USB power-save mode when not attached
* // to the USB host.
- * // USB_PWRSAVE_MODE_FASTWAKE - Exit USB power-save mode more quickly, but
- * // consume more power while in USB power-save
- * // mode.
- * // While the device is in USB power-save mode
- * // (typically during USB suspend), the
- * // internal voltage regulator stays in normal
- * // power mode instead of entering suspend
- * // power mode.
- * // This is an advanced feature that may be
- * // useful in certain applications that support
- * // remote wakeup.
+ * // USB_PWRSAVE_MODE_FASTWAKE - Exit USB power-save mode more quickly.
+ * // This is useful for some applications that
+ * // support remote wakeup.
* // -----------------------------------------------------------------------------
* #define SLAB_USB_PWRSAVE_MODE (USB_PWRSAVE_MODE_ONVBUSOFF \
* | USB_PWRSAVE_MODE_ONSUSPEND)
@@ -707,19 +686,14 @@
#endif
#ifndef UNREFERENCED_ARGUMENT
-#if defined __C51__
/// Macro for removing unreferenced arguments from compiler warnings
#define UNREFERENCED_ARGUMENT(arg) (0, arg)
-#elif defined __ICC8051__
-/// Macro for removing unreferenced arguments from compiler warnings
-#define UNREFERENCED_ARGUMENT(arg) ((void)arg)
-#endif
#endif
/***************************************************************************//**
* @brief Macro for creating USB-compliant UTF-16LE UNICODE string
* descriptor from a C string.
- * @details This macro should be used for ASCII strings in which all
+ * @details This macro should be used for UTF-8 strings in which all
* characters are represented by a single ASCII byte (i.e.
* U.S. English strings).
* The USB Library will expand variables created with this macro
@@ -736,71 +710,9 @@
* @param __val
* The value of the string descriptor
******************************************************************************/
-#define UTF16LE_PACKED_STATIC_CONST_STRING_DESC(__name, __val, __size) \
+#define UTF16LE_PACKED_STATIC_CONST_STRING_DESC(__name, __val) \
SI_SEGMENT_VARIABLE(__name, static const USB_StringDescriptor_TypeDef, SI_SEG_CODE) = \
- { USB_STRING_DESCRIPTOR_UTF16LE_PACKED, __size * 2, USB_STRING_DESCRIPTOR, __val }
-
-/***************************************************************************//**
- * @brief Macro for creating USB-compliant UTF-16LE UNICODE string
- * descriptor from a UTF-8 string.
- * @details This macro should be used for UTF-8 strings in which all
- * characters are represented by a valid UTF-8 byte sequence
- * of 1-3 bytes per character. The USB library will expand
- * variables created with this macro by decoding the UTF-8
- * sequence into 16-bit wide UCS-2 characters required for USB
- * string descriptors.
- * @n@n This example set an array named _manufacturer[]_ to a
- * series of symbols: an anchor, a lightning bolt, and a
- * fußball as the Manufacturer String:
- *
- * #define MFR_STRING "⚓⚡⚽"
- *
- * // This string has 3 Unicode characters so the __len
- * // parameter is 3, even though it will take 3 bytes to
- * // represent each character
- * UTF8_PACKED_STATIC_CONST_STRING_DESC(manufacturer[], 3, \
- * MFR_STRING);
- * @param __name
- * The name of the variable that holds the string descriptor
- * @param __len
- * Number of Unicode characters (or codepoints) in the string
- * @param __val
- * The value of the string descriptor
- ******************************************************************************/
-#define UTF8_PACKED_STATIC_CONST_STRING_DESC(__name, __len, __val) \
- SI_SEGMENT_VARIABLE(__name, static const USB_StringDescriptor_TypeDef, SI_SEG_CODE) = \
- { USB_STRING_DESCRIPTOR_UTF8, (__len) * 2, USB_STRING_DESCRIPTOR, __val }
-
-/***************************************************************************//**
- * @brief Macro for creating USB-compliant UTF-16LE UNICODE string
- * descriptor from a UTF-8 string.
- * @details This macro should be used for UTF-8 strings in which all
- * characters are represented by a valid UTF-8 byte sequence
- * of 1-3 bytes per character. The USB library will expand
- * variables created with this macro by decoding the UTF-8
- * sequence into 16-bit wide UCS-2 characters required for USB
- * string descriptors.
- * @n@n This example set an array named _manufacturer[]_ to a
- * series of symbols: an anchor, a lightning bolt, and a
- * fußball as the Manufacturer String:
- *
- * #define MFR_STRING "⚓⚡⚽"
- *
- * // This string has 3 Unicode characters so the __len
- * // parameter is 3, even though it will take 3 bytes to
- * // represent each character
- * UTF8_PACKED_STATIC_CONST_STRING_DESC(manufacturer[], 3, \
- * MFR_STRING);
- * @param __name
- * The name of the variable that holds the string descriptor
- * @param __len
- * Number of Unicode characters (or codepoints) in the string
- * @param __val
- * The value of the string descriptor
- ******************************************************************************/
-#define UTF8_PACKED_STATIC_CONST_STRING_DESC(__name, __len, __val) \
- SI_SEGMENT_VARIABLE(__name, static const USB_StringDescriptor_TypeDef, SI_SEG_CODE) = \
- { USB_STRING_DESCRIPTOR_UTF8, (__len) * 2, USB_STRING_DESCRIPTOR, __val }
+ { USB_STRING_DESCRIPTOR_UTF16LE_PACKED, sizeof(__val) * 2, USB_STRING_DESCRIPTOR, __val }
/***************************************************************************//**
* @brief Macro for creating USB-compliant UTF-16LE UNICODE string
@@ -867,8 +779,8 @@
* The value of the string descriptor
******************************************************************************/
#define LANGID_STATIC_CONST_STRING_DESC(__name, __val) \
- SI_SEGMENT_VARIABLE(__name, static const USB_LangId_StringDescriptor_Typedef, SI_SEG_CODE) = \
- { htole16(((SLAB_USB_NUM_LANGUAGES * 2) + 2) + (USB_STRING_DESCRIPTOR << 8)), __val }
+ SI_SEGMENT_VARIABLE(__name, static const USB_LangId_StringDescriptor_Typedef, __code) = \
+ { (((SLAB_USB_NUM_LANGUAGES * 2) + 2) << 8) + USB_STRING_DESCRIPTOR, __val }
/** @} (end addtogroup efm8_usb_macros Macros) */
@@ -897,8 +809,7 @@ typedef enum
USB_STATUS_DEVICE_RESET = -11, ///< Device is/was reset.
USB_STATUS_TIMEOUT = -12, ///< Transfer timeout.
USB_STATUS_DEVICE_REMOVED = -13, ///< Device was removed.
- USB_STATUS_EP_RX_BUFFER_OVERRUN = -14, ///< Not enough data in the Rx buffer to hold the
- USB_STATUS_DATA_ERROR = -15, ///< OUT packet had CRC or bit-stuffing error
+ USB_STATUS_EP_RX_BUFFER_OVERRUN = -14 ///< Not enough data in the Rx buffer to hold the
///< last received packet
} USB_Status_TypeDef;
@@ -952,7 +863,7 @@ typedef enum
#if (SLAB_USB_EP3OUT_USED)
EP3OUT,
#endif
-} USB_EP_Index_TypeDef;
+}USB_EP_Index_TypeDef;
/// @brief USB Setup type.
typedef struct
@@ -1083,7 +994,7 @@ typedef uint16_t USB_LangId_StringDescriptor_Typedef; ///< The language ID strin
#if (SLAB_USB_NUM_LANGUAGES == 1)
/// @brief USB String Table Structure.
-typedef SI_VARIABLE_SEGMENT_POINTER(, USB_StringDescriptor_TypeDef, SI_SEG_GENERIC) USB_StringTable_TypeDef;
+typedef USB_StringDescriptor_TypeDef * *USB_StringTable_TypeDef;
#elif (SLAB_USB_NUM_LANGUAGES > 1)
typedef struct
{
@@ -1097,17 +1008,17 @@ typedef struct
/// the device.
typedef struct
{
- SI_VARIABLE_SEGMENT_POINTER(deviceDescriptor, USB_DeviceDescriptor_TypeDef, SI_SEG_GENERIC); ///< Pointer to the device descriptor
- SI_VARIABLE_SEGMENT_POINTER(configDescriptor, USB_ConfigurationDescriptor_TypeDef, SI_SEG_GENERIC); ///< Pointer to the configuration descriptor
- SI_VARIABLE_SEGMENT_POINTER(stringDescriptors, USB_StringTable_TypeDef, SI_SEG_GENERIC); ///< Pointer to an array of string descriptor pointers
- uint8_t numberOfStrings; ///< Number of strings in string descriptor array
+ USB_DeviceDescriptor_TypeDef *deviceDescriptor; ///< Pointer to the device descriptor
+ uint8_t *configDescriptor; ///< Pointer to the configuration descriptor
+ USB_StringTable_TypeDef *stringDescriptors; ///< Pointer to an array of string descriptor pointers
+ uint8_t numberOfStrings; ///< Number of strings in string descriptor array
} USBD_Init_TypeDef;
/// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
// Endpoint structure
typedef struct
{
- SI_VARIABLE_SEGMENT_POINTER(buf, uint8_t, SI_SEG_GENERIC);
+ uint8_t *buf;
uint16_t remaining;
USBD_EpState_TypeDef state;
union
@@ -1171,9 +1082,9 @@ typedef struct
#if SLAB_USB_SUPPORT_ALT_INTERFACES
uint8_t interfaceAltSetting[SLAB_USB_NUM_INTERFACES];
#endif
- SI_VARIABLE_SEGMENT_POINTER(deviceDescriptor, USB_DeviceDescriptor_TypeDef, SI_SEG_GENERIC);
- SI_VARIABLE_SEGMENT_POINTER(configDescriptor, USB_ConfigurationDescriptor_TypeDef, SI_SEG_GENERIC);
- SI_VARIABLE_SEGMENT_POINTER(stringDescriptors, USB_StringTable_TypeDef, SI_SEG_GENERIC);
+ USB_DeviceDescriptor_TypeDef *deviceDescriptor;
+ USB_ConfigurationDescriptor_TypeDef *configDescriptor;
+ USB_StringTable_TypeDef *stringDescriptors;
} USBD_Device_TypeDef;
/// @endcond DO_NOT_INCLUDE_WITH_DOXYGEN
@@ -1307,10 +1218,6 @@ USB_Status_TypeDef USBDCH9_SetupCmd(void);
*
* Default setting is '1' and may be overridden by defining in 'usbconfig.h'.
*
- * @note The EFM8UB1, EFM8UB3, and EFM8UB4 devices can be configured to ignore
- * the voltage on the VBUS pin and to instead use that pin as GPIO. If
- * this feature is used, SLAB_USB_BUS_POWERED should be set to '1' even if
- * the device is not drawing its power from the VBUS line.
*****************************************************************************/
/**************************************************************************//**
@@ -1343,9 +1250,9 @@ USB_Status_TypeDef USBDCH9_SetupCmd(void);
* @brief Enables/disables remote wakeup capability
* @details Remote wakeup allow the USB device to wake the host from suspend.
* When enabled, the library will call @ref USBD_RemoteWakeupCb() to determine
- * if the remote wakeup source caused the device to wake up. If it did, the
- * library will exit suspend mode and call @ref USBD_RemoteWakeup() to wake
- * up the host.
+ * if the remote wakeup source caused the device to wake up. If it was, the
+ * library will exit suspend mode and the application should call
+ * @ref USBD_RemoteWakeup() to wake up the host.
*
* When '1' remote wakeup is enabled
* When '0' remote wakeup is disabled
@@ -1673,25 +1580,6 @@ USB_Status_TypeDef USBDCH9_SetupCmd(void);
*
*****************************************************************************/
-/**************************************************************************//**
- * @def SLAB_USB_UTF8_STRINGS
- * @brief
- * Enables UTF-8 string decoding for USB string descriptors that are created
- * using @ref UTF8_PACKED_STATIC_CONST_STRING_DESC.
- *
- * @details
- * If this option is enabled, USB descriptor strings that are created using
- * @ref UTF8_PACKED_STATIC_CONST_STRING_DESC can be encoded as UTF-8 which
- * allows for Unicode characters (up to 16-bits wide) to be used for USB
- * string descriptors. The UTF-8 strings will be decoded into UCS-2 16-bit
- * wide character format required by USB. If this feature is not needed then
- * this option can be disabled to save code memory space. If this option is
- * disabled, then @ref UTF8_PACKED_STATIC_CONST_STRING_DESC should not be used.
- *
- * Default setting is '0' and may be overridden by defining in 'usbconfig.h'.
- *
- *****************************************************************************/
-
/**************************************************************************//**
* @def SLAB_USB_PWRSAVE_MODE
* @brief Configures the power-saving options supported by the device
@@ -1856,10 +1744,6 @@ USB_Status_TypeDef USBDCH9_SetupCmd(void);
#define SLAB_USB_LANGUAGE USB_LANGID_ENUS
#endif
-#ifndef SLAB_USB_UTF8_STRINGS
-#define SLAB_USB_UTF8_STRINGS 0
-#endif
-
#ifndef SLAB_USB_PWRSAVE_MODE
#define SLAB_USB_PWRSAVE_MODE USB_PWRSAVE_MODE_ONSUSPEND
#endif
@@ -1956,7 +1840,7 @@ USBD_State_TypeDef USBD_GetUsbState(void);
* @return
* @ref USB_STATUS_OK on success, else an appropriate error code.
******************************************************************************/
-int8_t USBD_Init(SI_VARIABLE_SEGMENT_POINTER(p, const USBD_Init_TypeDef, SI_SEG_GENERIC));
+int8_t USBD_Init(const USBD_Init_TypeDef *p);
/***************************************************************************//**
* @brief
@@ -1982,8 +1866,8 @@ int8_t USBD_Init(SI_VARIABLE_SEGMENT_POINTER(p, const USBD_Init_TypeDef, SI_SEG_
* @return
* @ref USB_STATUS_OK on success, else an appropriate error code.
******************************************************************************/
-int8_t USBD_Read(uint8_t epAddr,
- SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC),
+int8_t USBD_Read(uint8_t epAddr,
+ uint8_t *dat,
uint16_t byteCount,
bool callback);
@@ -1992,9 +1876,10 @@ int8_t USBD_Read(uint8_t epAddr,
* Perform a remote wakeup signaling sequence.
*
* @note
- * This function is typically called by the library if @ref
- * USBD_RemoteWakeupCb() returns true, so it does not need to be called by
- * application code.
+ * It is the responsibility of the application to ensure that remote wakeup
+ * is not attempted before the device has been suspended for at least 5
+ * miliseconds. This function should not be called from within an interrupt
+ * handler.
*
* @return
* @ref USB_STATUS_OK on success, else an appropriate error code.
@@ -2030,7 +1915,7 @@ void USBD_Run(void);
* @return
* @ref USB_STATUS_OK on success, else an appropriate error code.
******************************************************************************/
-int8_t USBD_StallEp(uint8_t epAddr);
+int8_t USBD_StallEp(int8_t epAddr);
/***************************************************************************//**
* @brief
@@ -2089,7 +1974,7 @@ int8_t USBD_UnStallEp(uint8_t epAddr);
* @ref USB_STATUS_OK on success, else an appropriate error code.
******************************************************************************/
int8_t USBD_Write(uint8_t epAddr,
- SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC),
+ uint8_t *dat,
uint16_t byteCount,
bool callback);
@@ -2228,8 +2113,8 @@ USB_Status_TypeDef USBD_SetInterfaceCb(uint8_t interface, uint8_t altSetting);
* If remote wakeup is enabled via @ref SLAB_USB_REMOTE_WAKEUP_ENABLED, the
* USB library will query the application after waking from suspend to see if
* the remote wakeup source was the reason for the wakeup. If this function
- * returns True, the library will call @ref USBD_RemoteWakeup() to wake up the
- * host and exit suspend mode.
+ * returns True, the library will exit suspend mode and the application should
+ * call @ref USBD_RemoteWakeup() to wake up the host.
* @return
* True if the remote wakeup source was the reason the device woke from
* suspend, false otherwise.
@@ -2311,8 +2196,8 @@ uint16_t USBD_XferCompleteCb(uint8_t epAddr, \
/// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
// -------------------- FIFO Access Functions ---------------------------------
-void USB_ReadFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC));
-void USB_WriteFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC), bool txPacket);
+void USB_ReadFIFO(uint8_t fifoNum, uint8_t numBytes, uint8_t *dat);
+void USB_WriteFIFO(uint8_t fifoNum, uint8_t numBytes, uint8_t *dat, bool txPacket);
/// @endcond DO_NOT_INCLUDE_WITH_DOXYGEN
// -------------------- Include Files ------------------------------------------
diff --git a/efm8/lib/efm8_usb/src/efm8_usbd.c b/efm8/lib/efm8_usb/src/efm8_usbd.c
index 34f94e4..24e2d8d 100644
--- a/efm8/lib/efm8_usb/src/efm8_usbd.c
+++ b/efm8/lib/efm8_usb/src/efm8_usbd.c
@@ -6,9 +6,9 @@
#include "si_toolchain.h"
#include "efm8_usb.h"
-#include "assert.h"
+//#include "assert.h"
#include
-
+#define SLAB_ASSERT(x)
// -----------------------------------------------------------------------------
// Global Variables
@@ -65,8 +65,8 @@ void USBD_AbortAllTransfers(void)
int8_t USBD_AbortTransfer(uint8_t epAddr)
{
- SI_VARIABLE_SEGMENT_POINTER(ep, USBD_Ep_TypeDef, MEM_MODEL_SEG);
- int8_t retVal = USB_STATUS_OK;
+ USBD_Ep_TypeDef MEM_MODEL_SEG *ep;
+ uint8_t retVal = USB_STATUS_OK;
bool usbIntsEnabled;
USB_SaveSfrPage();
@@ -150,7 +150,7 @@ void USBD_Disconnect(void)
bool USBD_EpIsBusy(uint8_t epAddr)
{
- SI_VARIABLE_SEGMENT_POINTER(ep, USBD_Ep_TypeDef, MEM_MODEL_SEG);
+ USBD_Ep_TypeDef MEM_MODEL_SEG *ep;
// Verify this is a valid endpoint address
if (epAddr >= SLAB_USB_NUM_EPS_USED)
@@ -174,7 +174,7 @@ USBD_State_TypeDef USBD_GetUsbState(void)
return myUsbDevice.state;
}
-int8_t USBD_Init(SI_VARIABLE_SEGMENT_POINTER(p, const USBD_Init_TypeDef, SI_SEG_GENERIC))
+int8_t USBD_Init(const USBD_Init_TypeDef *p)
{
uint8_t i;
@@ -190,12 +190,12 @@ int8_t USBD_Init(SI_VARIABLE_SEGMENT_POINTER(p, const USBD_Init_TypeDef, SI_SEG_
// Zero out the myUsbDevice struct, then initialize all non-zero members
for (i = 0; i < sizeof(myUsbDevice); i++)
{
- *((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, MEM_MODEL_SEG))&myUsbDevice + i) = 0;
+ *((uint8_t MEM_MODEL_SEG *)&myUsbDevice + i) = 0;
}
// Get the USB descriptors from p
myUsbDevice.deviceDescriptor = p->deviceDescriptor;
- myUsbDevice.configDescriptor = p->configDescriptor;
+ myUsbDevice.configDescriptor = (USB_ConfigurationDescriptor_TypeDef *)p->configDescriptor;
myUsbDevice.stringDescriptors = p->stringDescriptors;
myUsbDevice.numberOfStrings = p->numberOfStrings;
@@ -246,12 +246,12 @@ int8_t USBD_Init(SI_VARIABLE_SEGMENT_POINTER(p, const USBD_Init_TypeDef, SI_SEG_
}
int8_t USBD_Read(uint8_t epAddr,
- SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC),
+ uint8_t *dat,
uint16_t byteCount,
bool callback)
{
bool usbIntsEnabled;
- SI_VARIABLE_SEGMENT_POINTER(ep, USBD_Ep_TypeDef, MEM_MODEL_SEG);
+ USBD_Ep_TypeDef MEM_MODEL_SEG *ep;
USB_SaveSfrPage();
@@ -432,13 +432,8 @@ void USBD_Stop(void)
void USBD_Suspend(void)
{
-#if (!(SLAB_USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_FASTWAKE))
uint8_t i;
-#endif
bool regulatorEnabled, prefetchEnabled;
-#if SLAB_USB_REMOTE_WAKEUP_ENABLED
- bool remoteWakeup = false;
-#endif
USB_SaveSfrPage();
@@ -494,9 +489,8 @@ void USBD_Suspend(void)
// wakeup event occurred. If so, exit USBD_Suspend().
if (USB_IsSuspended() == true)
{
- remoteWakeup = USBD_RemoteWakeupCb();
- if (remoteWakeup == true)
- {
+ if (USBD_RemoteWakeupCb() == true)
+ {
break;
}
}
@@ -510,13 +504,8 @@ void USBD_Suspend(void)
break;
}
#endif
-
-#if ((!(SLAB_USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF)) || \
- (SLAB_USB_BUS_POWERED))
} while (USB_IsSuspended() == true);
-#else
- } while ((USB_IsSuspended() == true) || (USB_IsVbusOn() == false));
-#endif
+
// Restore the internal regulator
if (regulatorEnabled == true)
{
@@ -534,20 +523,6 @@ void USBD_Suspend(void)
USB_SetNormalClock();
#endif
USB_EnableTransceiver();
-
-#if SLAB_USB_REMOTE_WAKEUP_ENABLED
- // If the device woke from suspend due to a remote wakeup source, call
- // USBD_RemoteWakeup() here to wake up the host.
- if (remoteWakeup == true)
- {
- // Wake up the host
- if (USBD_RemoteWakeup() == USB_STATUS_OK)
- {
- // If the remote wakeup succeeded, transition out of USB suspend state
- USBD_SetUsbState(myUsbDevice.savedState);
- }
- }
-#endif
}
USB_RestoreSfrPage();
@@ -624,12 +599,12 @@ int8_t USBD_UnStallEp(uint8_t epAddr)
}
int8_t USBD_Write(uint8_t epAddr,
- SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC),
+ uint8_t *dat,
uint16_t byteCount,
bool callback)
{
bool usbIntsEnabled;
- SI_VARIABLE_SEGMENT_POINTER(ep, USBD_Ep_TypeDef, MEM_MODEL_SEG);
+ USBD_Ep_TypeDef MEM_MODEL_SEG *ep;
USB_SaveSfrPage();
diff --git a/efm8/lib/efm8_usb/src/efm8_usbdch9.c b/efm8/lib/efm8_usb/src/efm8_usbdch9.c
index 6bb2a47..c0afa23 100644
--- a/efm8/lib/efm8_usb/src/efm8_usbdch9.c
+++ b/efm8/lib/efm8_usb/src/efm8_usbdch9.c
@@ -22,13 +22,14 @@ static USB_Status_TypeDef SetConfiguration(void);
static USB_Status_TypeDef SetFeature(void);
static USB_Status_TypeDef SetInterface(void);
static void USBD_ActivateAllEps(bool forceIdle);
-static void EP0_Write(SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC), uint16_t numBytes);
+static void EP0_Write(uint8_t *dat, uint16_t numBytes);
+void SendEp0Stall(void);
// -----------------------------------------------------------------------------
// Global Variables
extern SI_SEGMENT_VARIABLE(myUsbDevice, USBD_Device_TypeDef, MEM_MODEL_SEG);
-const SI_SEGMENT_VARIABLE(txZero[2], uint8_t, SI_SEG_CODE);
+SI_SEGMENT_VARIABLE(txZero[2], uint8_t, SI_SEG_CODE);
// -----------------------------------------------------------------------------
// Static Global Variables
@@ -91,6 +92,15 @@ USB_Status_TypeDef USBDCH9_SetupCmd(void)
break;
}
+ // Reset index to 0 in case one of the above commands modified it
+ USB_SetIndex(0);
+
+ // If the command resulted in an error, send a procedural stall
+ if (status == USB_STATUS_REQ_ERR)
+ {
+ SendEp0Stall();
+ }
+
return status;
}
@@ -228,7 +238,7 @@ static USB_Status_TypeDef GetConfiguration(void)
{
if (myUsbDevice.state == USBD_STATE_ADDRESSED)
{
- EP0_Write((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))txZero, 1);
+ EP0_Write(txZero, 1);
retVal = USB_STATUS_OK;
}
else if (myUsbDevice.state == USBD_STATE_CONFIGURED)
@@ -257,7 +267,7 @@ static USB_Status_TypeDef GetDescriptor(void)
uint8_t index;
uint16_t length = 0;
- SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC);
+ uint8_t *dat;
USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
if (*((uint8_t *)&myUsbDevice.setup.bmRequestType) ==
@@ -272,7 +282,7 @@ static USB_Status_TypeDef GetDescriptor(void)
{
break;
}
- dat = (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))myUsbDevice.deviceDescriptor;
+ dat = (uint8_t *)myUsbDevice.deviceDescriptor;
length = myUsbDevice.deviceDescriptor->bLength;
break;
@@ -281,14 +291,14 @@ static USB_Status_TypeDef GetDescriptor(void)
{
break;
}
- dat = (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))myUsbDevice.configDescriptor;
+ dat = (uint8_t *)myUsbDevice.configDescriptor;
length = le16toh(myUsbDevice.configDescriptor->wTotalLength);
break;
case USB_STRING_DESCRIPTOR:
#if (SLAB_USB_NUM_LANGUAGES == 1)
- dat = (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))myUsbDevice.stringDescriptors[index];
+ dat = (uint8_t *)myUsbDevice.stringDescriptors[index];
// Index 0 is the language string. If SLAB_USB_NUM_LANGUAGES == 1, we
// know the length will be 4 and the format will be UTF16LE.
@@ -317,7 +327,7 @@ static USB_Status_TypeDef GetDescriptor(void)
// Index 0 is the language.
if (index == 0)
{
- dat = ((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))myUsbDevice.stringDescriptors->languageArray[0][index]);
+ dat = ((uint8_t *)myUsbDevice.stringDescriptors->languageArray[0][index]);
length = *((uint8_t *)dat);
myUsbDevice.ep0String.encoding.type = USB_STRING_DESCRIPTOR_UTF16LE;
}
@@ -335,7 +345,7 @@ static USB_Status_TypeDef GetDescriptor(void)
}
if ((langSupported == true) && (index < myUsbDevice.numberOfStrings))
{
- dat = ((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))myUsbDevice.stringDescriptors->languageArray[lang][index]);
+ dat = ((uint8_t *)myUsbDevice.stringDescriptors->languageArray[lang][index]);
length = *(dat + USB_STRING_DESCRIPTOR_LENGTH);
myUsbDevice.ep0String.encoding.type = *(dat + USB_STRING_DESCRIPTOR_ENCODING);
dat += USB_STRING_DESCRIPTOR_LENGTH;
@@ -393,10 +403,10 @@ static USB_Status_TypeDef GetInterface(void)
{
#if (SLAB_USB_SUPPORT_ALT_INTERFACES)
// Return the alternate setting for the specified interface
- EP0_Write((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))&myUsbDevice.interfaceAltSetting[interface], 1);
+ EP0_Write(&myUsbDevice.interfaceAltSetting[interface], 1);
#else
// Alternate interfaces are not supported, so return 0x0000.
- EP0_Write((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))&txZero, 1);
+ EP0_Write(&txZero, 1);
#endif
retVal = USB_STATUS_OK;
}
@@ -531,7 +541,7 @@ static USB_Status_TypeDef GetStatus(void)
// If the command was valid, send the requested status.
if (retVal == USB_STATUS_OK)
{
- EP0_Write((SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))&pStatus, 2);
+ EP0_Write((uint8_t *)&pStatus, 2);
}
}
@@ -858,11 +868,11 @@ static void USBD_ActivateAllEps(bool forceIdle)
* @param numBytes
* Number of bytes to transmit on Endpoint 0
******************************************************************************/
-static void EP0_Write(SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC), uint16_t numBytes)
+static void EP0_Write(uint8_t *dat, uint16_t numBytes)
{
if (myUsbDevice.ep0.state == D_EP_IDLE)
{
- myUsbDevice.ep0.buf = dat;
+ myUsbDevice.ep0.buf = (uint8_t *)dat;
myUsbDevice.ep0.remaining = numBytes;
myUsbDevice.ep0.state = D_EP_TRANSMITTING;
myUsbDevice.ep0.misc.c = 0;
diff --git a/efm8/lib/efm8_usb/src/efm8_usbdep.c b/efm8/lib/efm8_usb/src/efm8_usbdep.c
index 2982658..ec8721a 100644
--- a/efm8/lib/efm8_usb/src/efm8_usbdep.c
+++ b/efm8/lib/efm8_usb/src/efm8_usbdep.c
@@ -40,16 +40,11 @@ static void USB_WriteFIFO_Code(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat
// -------------------------------
// Generic FIFO access functions
-static void USB_ReadFIFO_Generic(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC), uint8_t fifoNum);
-static void USB_WriteFIFO_Generic(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC));
+static void USB_ReadFIFO_Generic(uint8_t numBytes, uint8_t *dat, uint8_t fifoNum);
+static void USB_WriteFIFO_Generic(uint8_t numBytes, uint8_t *dat);
#endif // #ifdef SI_GPTR
-#if (SLAB_USB_EP3OUT_USED && (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC))
-static void memclearXdata(SI_VARIABLE_SEGMENT_POINTER(s, uint8_t, SI_SEG_XDATA),
- uint16_t n);
-#endif
-
// -----------------------------------------------------------------------------
// Functions
@@ -67,7 +62,7 @@ static void memclearXdata(SI_VARIABLE_SEGMENT_POINTER(s, uint8_t, SI_SEG_XDATA),
// If Isochronous mode is enabled and the max packet size is greater than 255,
// break the FIFO reads up into multiple reads of 255 or less bytes.
// ----------------------------------------------------------------------------
-void USB_ReadFIFOIso(uint8_t fifoNum, uint16_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC))
+void USB_ReadFIFOIso(uint8_t fifoNum, uint16_t numBytes, uint8_t *dat)
{
uint8_t numBytesRead;
@@ -99,7 +94,7 @@ void USB_ReadFIFOIso(uint8_t fifoNum, uint16_t numBytes, SI_VARIABLE_SEGMENT_POI
// If Isochronous mode is enabled and the max packet size is greater than 255,
// break the FIFO writes up into multiple writes of 255 or less bytes.
// ----------------------------------------------------------------------------
-void USB_WriteFIFOIso(uint8_t fifoNum, uint16_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC))
+void USB_WriteFIFOIso(uint8_t fifoNum, uint16_t numBytes, uint8_t *dat)
{
uint8_t numBytesWrite;
@@ -322,6 +317,7 @@ void handleUsbIn3Int(void)
void handleUsbOut1Int(void)
{
uint8_t count;
+
USB_Status_TypeDef status;
bool xferComplete = false;
@@ -361,7 +357,6 @@ void handleUsbOut1Int(void)
myUsbDevice.ep1out.state = D_EP_IDLE;
xferComplete = true;
}
-
status = USB_STATUS_OK;
USB_EpnClearOutPacketReady();
}
@@ -371,7 +366,6 @@ void handleUsbOut1Int(void)
{
myUsbDevice.ep1out.misc.bits.callback = false;
}
-
USBD_XferCompleteCb(EP1OUT, status, count, myUsbDevice.ep1out.remaining);
}
}
@@ -387,6 +381,7 @@ void handleUsbOut1Int(void)
void handleUsbOut2Int(void)
{
uint8_t count;
+
USB_Status_TypeDef status;
bool xferComplete = false;
@@ -451,10 +446,19 @@ void handleUsbOut2Int(void)
* @note This function takes no parameters, but it uses the EP3OUT status
* variables stored in @ref myUsbDevice.ep3out.
******************************************************************************/
-#if ((SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR))
void handleUsbOut3Int(void)
{
+#if (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC)
+ uint16_t nextIdx;
+#if (SLAB_USB_EP3OUT_MAX_PACKET_SIZE > 255)
+ uint16_t count;
+#else
uint8_t count;
+#endif // ( SLAB_USB_EP3OUT_MAX_PACKET_SIZE > 255 )
+#else
+ uint8_t count;
+#endif // ( SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC )
+
USB_Status_TypeDef status;
bool xferComplete = false;
@@ -474,6 +478,7 @@ void handleUsbOut3Int(void)
myUsbDevice.ep3out.misc.bits.outPacketPending = true;
status = USB_STATUS_EP_ERROR;
}
+#if ((SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR))
// Check for overrun of user buffer
else if (myUsbDevice.ep3out.remaining < count)
{
@@ -481,11 +486,12 @@ void handleUsbOut3Int(void)
myUsbDevice.ep3out.misc.bits.outPacketPending = true;
status = USB_STATUS_EP_RX_BUFFER_OVERRUN;
}
+#endif
else
{
+#if ((SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR))
USB_ReadFIFO(3, count, myUsbDevice.ep3out.buf);
- myUsbDevice.ep3out.misc.bits.outPacketPending = false;
myUsbDevice.ep3out.remaining -= count;
myUsbDevice.ep3out.buf += count;
@@ -494,7 +500,26 @@ void handleUsbOut3Int(void)
myUsbDevice.ep3out.state = D_EP_IDLE;
xferComplete = true;
}
+#elif (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC)
+ nextIdx = count + myUsbDevice.ep3outIsoIdx;
+ // In isochronous mode, a circular buffer is used to hold the data
+ // If the next index into the circular buffer passes the end of the
+ // buffer, make two calls to USB_ReadFIFOIso()
+ if (nextIdx > myUsbDevice.ep3out.remaining)
+ {
+ USB_ReadFIFOIso(3, myUsbDevice.ep3out.remaining - myUsbDevice.ep3outIsoIdx, &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx]);
+ myUsbDevice.ep3outIsoIdx = nextIdx - myUsbDevice.ep3out.remaining;
+ USB_ReadFIFOIso(3, myUsbDevice.ep3outIsoIdx, myUsbDevice.ep3out.buf);
+ }
+ else
+ {
+ USB_ReadFIFOIso(3, count, &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx]);
+ myUsbDevice.ep3outIsoIdx = nextIdx;
+ }
+#endif // ( ( SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK ) || ( SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR ) )
+
+ myUsbDevice.ep3out.misc.bits.outPacketPending = false;
status = USB_STATUS_OK;
USB_EpnClearOutPacketReady();
}
@@ -505,175 +530,18 @@ void handleUsbOut3Int(void)
myUsbDevice.ep3out.misc.bits.callback = false;
}
+#if ((SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR))
USBD_XferCompleteCb(EP3OUT, status, count, myUsbDevice.ep3out.remaining);
- }
- }
-}
-
#elif (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC)
-void handleUsbOut3Int(void)
-{
- uint16_t nextIdx;
- uint16_t numZeroBytesFromCb;
-#if (SLAB_USB_EP3OUT_MAX_PACKET_SIZE > 255)
- uint16_t count;
-#else
- uint8_t count;
-#endif
- USB_Status_TypeDef status = USB_STATUS_OK;
- bool xferComplete = false;
-
- USB_SetIndex(3);
-
- if (USB_EpnOutGetSentStall())
- {
- USB_EpnOutClearSentStall();
- }
- else if (USB_EpnGetOutPacketReady())
- {
- count = USB_EpOutGetCount();
-
- // If USBD_Read() has not been called, return an error
- if (myUsbDevice.ep3out.state != D_EP_RECEIVING)
- {
- myUsbDevice.ep3out.misc.bits.outPacketPending = true;
- status = USB_STATUS_EP_ERROR;
- }
- else
- {
- // DATERR bit set (i.e. CRC/bit-stuffing error)
- if (USB_EpnGetDataError()
- #ifdef SLAB_USB_ISOC_OUT_MIN_PACKET_SIZE
- || (count < SLAB_USB_ISOC_OUT_MIN_PACKET_SIZE)
- #endif
- #ifdef SLAB_USB_ISOC_OUT_MAX_PACKET_SIZE
- || (count > SLAB_USB_ISOC_OUT_MAX_PACKET_SIZE)
- #endif
- )
- {
- status = USB_STATUS_DATA_ERROR;
- }
-
-#ifdef SLAB_USB_ISOC_OUT_PACKETSIZE_MOD2
- if ((count % 2) != 0)
- {
- status = USB_STATUS_DATA_ERROR;
- }
-#elif defined SLAB_USB_ISOC_OUT_PACKETSIZE_MOD4
- if (( count % 4) != 0)
- {
- status = USB_STATUS_DATA_ERROR;
- }
-#elif defined SLAB_USB_ISOC_OUT_PACKETSIZE_MOD6
- if (count % 6) != 0)
- {
- status = USB_STATUS_DATA_ERROR;
- }
-#endif
-
- if (status == USB_STATUS_DATA_ERROR)
- {
- count = 0;
- // Flush FIFO to get rid of bad packet
- USB_EpnOutFlush();
- myUsbDevice.ep3out.misc.bits.outPacketPending = false;
- // Flush clears OPRDY, so no need to call USB_EpnClearOutPacketReady() now
- }
- else // No data error
- {
- nextIdx = count + myUsbDevice.ep3outIsoIdx;
-
- // In isochronous mode, a circular buffer is used to hold the data
- // If the next index into the circular buffer passes the end of the
- // buffer, make two calls to USB_ReadFIFOIso()
- if (nextIdx > myUsbDevice.ep3out.remaining)
- {
- USB_ReadFIFOIso(3, myUsbDevice.ep3out.remaining - myUsbDevice.ep3outIsoIdx, &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx]);
- myUsbDevice.ep3outIsoIdx = nextIdx - myUsbDevice.ep3out.remaining;
- USB_ReadFIFOIso(3, myUsbDevice.ep3outIsoIdx, myUsbDevice.ep3out.buf);
- }
- else
- {
- USB_ReadFIFOIso(3, count, &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx]);
- myUsbDevice.ep3outIsoIdx = nextIdx;
- }
-
- myUsbDevice.ep3out.misc.bits.outPacketPending = false;
- USB_EpnClearOutPacketReady();
- }
- }
-
- if (myUsbDevice.ep3out.misc.bits.callback == true)
- {
- if (xferComplete == true)
- {
- myUsbDevice.ep3out.misc.bits.callback = false;
- }
// In Isochronous mode, the meaning of the USBD_XferCompleteCb parameters changes:
// xferred is the number of bytes received in the last packet
// remaining is the current index into the circular buffer
- numZeroBytesFromCb = USBD_XferCompleteCb(EP3OUT, status, count, myUsbDevice.ep3outIsoIdx);
-
- // If data error occurred, the callback return value specifies how many zero-valued bytes to queue
- if (numZeroBytesFromCb && (status == USB_STATUS_DATA_ERROR))
- {
- uint16_t numZeroBytesToWrite;
- SI_SEGMENT_VARIABLE_SEGMENT_POINTER(bufPtr,
- uint8_t,
- SI_SEG_XDATA,
- SI_SEG_DATA);
-
- // Clear status after calling USBD_XferCompleteCb()
- status = USB_STATUS_OK;
-
- // Add the specified number of zero-value bytes
- nextIdx = numZeroBytesFromCb + myUsbDevice.ep3outIsoIdx;
-
- // Next index is past the end of the buffer (requires two writes)
- if (nextIdx > myUsbDevice.ep3out.remaining)
- {
- // Write up to the end of the buffer
- numZeroBytesToWrite = myUsbDevice.ep3out.remaining - myUsbDevice.ep3outIsoIdx;
- bufPtr = &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx];
- memclearXdata(bufPtr, numZeroBytesToWrite);
-
- // Write the rest, starting at beginning of buffer
- myUsbDevice.ep3outIsoIdx = nextIdx - myUsbDevice.ep3out.remaining;
- numZeroBytesToWrite = myUsbDevice.ep3outIsoIdx;
- bufPtr = &myUsbDevice.ep3out.buf[0];
- memclearXdata(bufPtr, numZeroBytesToWrite);
- }
- // Next index is not past the end of the buffer
- else
- {
- bufPtr = &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx];
- memclearXdata(bufPtr, numZeroBytesFromCb);
- myUsbDevice.ep3outIsoIdx = nextIdx;
- }
- }
+ USBD_XferCompleteCb(EP3OUT, status, count, myUsbDevice.ep3outIsoIdx);
+#endif
}
}
}
-
-/***************************************************************************//**
- * @brief Sets all elements in a contiguous array of XDATA to zero
- * @param s
- * Pointer to the block of memory to fill
- * @param n
- * Number of bytes to be set to the value
- ******************************************************************************/
-static void memclearXdata(SI_VARIABLE_SEGMENT_POINTER(s, uint8_t, SI_SEG_XDATA),
- uint16_t n)
-{
- while (n)
- {
- *s++ = 0;
- n--;
- }
-}
-
-#endif // #if ((SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR))
#endif // EP3OUT_USED
/***************************************************************************//**
@@ -685,7 +553,7 @@ static void memclearXdata(SI_VARIABLE_SEGMENT_POINTER(s, uint8_t, SI_SEG_XDATA),
* @param dat
* Pointer to buffer to hold data read from the FIFO
******************************************************************************/
-void USB_ReadFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC))
+void USB_ReadFIFO(uint8_t fifoNum, uint8_t numBytes, uint8_t *dat)
{
if (numBytes > 0)
{
@@ -699,7 +567,7 @@ void USB_ReadFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER
switch (((SI_GEN_PTR_t *)&dat)->gptr.memtype)
{
case SI_GPTR_MTYPE_IDATA:
- USB_ReadFIFO_Idata(numBytes, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_IDATA))dat, fifoNum);
+ USB_ReadFIFO_Idata(numBytes, dat, fifoNum);
break;
// For some compilers, IDATA and DATA are treated the same.
@@ -712,7 +580,7 @@ void USB_ReadFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER
#endif
case SI_GPTR_MTYPE_XDATA:
- USB_ReadFIFO_Xdata(numBytes, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_XDATA))dat, fifoNum);
+ USB_ReadFIFO_Xdata(numBytes, dat, fifoNum);
break;
// For some compilers, XDATA and PDATA are treated the same.
@@ -750,7 +618,7 @@ void USB_ReadFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER
* If FALSE, the packet will be stored in the FIFO and the
* transmission must be started at a later time
******************************************************************************/
-void USB_WriteFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC), bool txPacket)
+void USB_WriteFIFO(uint8_t fifoNum, uint8_t numBytes, uint8_t *dat, bool txPacket)
{
USB_EnableWriteFIFO(fifoNum);
@@ -762,7 +630,7 @@ void USB_WriteFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTE
switch (((SI_GEN_PTR_t *)&dat)->gptr.memtype)
{
case SI_GPTR_MTYPE_IDATA:
- USB_WriteFIFO_Idata(numBytes, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_IDATA))dat);
+ USB_WriteFIFO_Idata(numBytes, dat);
break;
// For some compilers, IDATA and DATA are treated the same.
@@ -775,7 +643,7 @@ void USB_WriteFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTE
#endif
case SI_GPTR_MTYPE_XDATA:
- USB_WriteFIFO_Xdata(numBytes, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_XDATA))dat);
+ USB_WriteFIFO_Xdata(numBytes, dat);
break;
// For some compilers, XDATA and PDATA are treated the same.
@@ -788,7 +656,7 @@ void USB_WriteFIFO(uint8_t fifoNum, uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTE
#endif
case SI_GPTR_MTYPE_CODE:
- USB_WriteFIFO_Code(numBytes, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_CODE))dat);
+ USB_WriteFIFO_Code(numBytes, dat);
break;
default:
@@ -944,10 +812,10 @@ static void USB_ReadFIFO_Data(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat,
{
while (--numBytes)
{
- USB_GetFIFOByte(dat);
+ USB_GetFIFOByte(*dat);
dat++;
}
- USB_GetLastFIFOByte(dat, fifoNum);
+ USB_GetLastFIFOByte(*dat, fifoNum);
}
/***************************************************************************//**
@@ -997,14 +865,14 @@ static void USB_WriteFIFO_Code(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat
* @param fifoNum
* USB FIFO to read
******************************************************************************/
-static void USB_ReadFIFO_Generic(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC), uint8_t fifoNum)
+static void USB_ReadFIFO_Generic(uint8_t numBytes, uint8_t *dat, uint8_t fifoNum)
{
while (--numBytes)
{
- USB_GetFIFOByte(dat);
+ USB_GetFIFOByte(*dat);
dat++;
}
- USB_GetLastFIFOByte(dat, fifoNum);
+ USB_GetLastFIFOByte(*dat, fifoNum);
}
/***************************************************************************//**
@@ -1016,7 +884,7 @@ static void USB_ReadFIFO_Generic(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(d
* @param dat
* Pointer to generic buffer holding data to write to the FIFO
******************************************************************************/
-static void USB_WriteFIFO_Generic(uint8_t numBytes, SI_VARIABLE_SEGMENT_POINTER(dat, uint8_t, SI_SEG_GENERIC))
+static void USB_WriteFIFO_Generic(uint8_t numBytes, uint8_t *dat)
{
while (numBytes--)
{
diff --git a/efm8/lib/efm8_usb/src/efm8_usbdint.c b/efm8/lib/efm8_usb/src/efm8_usbdint.c
index 39d744f..f00c9ed 100644
--- a/efm8/lib/efm8_usb/src/efm8_usbdint.c
+++ b/efm8/lib/efm8_usb/src/efm8_usbdint.c
@@ -13,7 +13,7 @@
// Global variables
extern SI_SEGMENT_VARIABLE(myUsbDevice, USBD_Device_TypeDef, MEM_MODEL_SEG);
-extern SI_SEGMENT_VARIABLE(txZero[2], const uint8_t, SI_SEG_CODE);
+extern SI_SEGMENT_VARIABLE(txZero[2], uint8_t, SI_SEG_CODE);
// -----------------------------------------------------------------------------
// Function prototypes
@@ -48,12 +48,6 @@ void handleUsbOut3Int(void);
void SendEp0Stall(void);
-#if SLAB_USB_UTF8_STRINGS == 1
-static uint8_t decodeUtf8toUcs2(
- const uint8_t *pUtf8in,
- SI_VARIABLE_SEGMENT_POINTER(pUcs2out, uint16_t, MEM_MODEL_SEG));
-#endif
-
// -----------------------------------------------------------------------------
// Functions
@@ -218,8 +212,6 @@ void usbIrqHandler(void)
******************************************************************************/
static void handleUsbEp0Int(void)
{
- USB_Status_TypeDef retVal = USB_STATUS_REQ_UNHANDLED;
-
USB_SetIndex(0);
if (USB_Ep0SentStall() || USB_GetSetupEnd())
@@ -242,55 +234,32 @@ static void handleUsbEp0Int(void)
// Vendor unique, Class or Standard setup commands override?
#if SLAB_USB_SETUP_CMD_CB
- retVal = USBD_SetupCmdCb(&myUsbDevice.setup);
-
- if (retVal == USB_STATUS_REQ_UNHANDLED)
+ if (USBD_SetupCmdCb(&myUsbDevice.setup) == USB_STATUS_REQ_UNHANDLED)
{
#endif
- if (myUsbDevice.setup.bmRequestType.Type == USB_SETUP_TYPE_STANDARD)
- {
- retVal = USBDCH9_SetupCmd();
- }
-#if SLAB_USB_SETUP_CMD_CB
- }
-#endif
-
- // Reset index to 0 in case the call to USBD_SetupCmdCb() or
- // USBDCH9_SetupCmd() changed it.
- USB_SetIndex(0);
-
- // Put the Enpoint 0 hardware into the correct state here.
- if (retVal == USB_STATUS_OK)
+ if (myUsbDevice.setup.bmRequestType.Type == USB_SETUP_TYPE_STANDARD)
{
- // If wLength is 0, there is no Data Phase
- // Set both the Serviced Out Packet Ready and Data End bits
- if (myUsbDevice.setup.wLength == 0)
- {
- USB_Ep0SetLastOutPacketReady();
- }
- // If wLength is non-zero, there is a Data Phase.
- // Set only the Serviced Out Packet Ready bit.
- else
- {
- USB_Ep0ServicedOutPacketReady();
-
-#if SLAB_USB_SETUP_CMD_CB
- // If OUT packet but callback didn't set up a USBD_Read and we are expecting a
- // data byte then we need to wait for the read to be setup and NACK packets until
- // USBD_Read is called.
- if ((myUsbDevice.setup.bmRequestType.Direction == USB_SETUP_DIR_OUT)
- && (myUsbDevice.ep0.state != D_EP_RECEIVING))
- {
- myUsbDevice.ep0.misc.bits.waitForRead = true;
- }
-#endif
- }
+ USBDCH9_SetupCmd();
}
- // If the setup transaction detected an error, send a stall
else
{
SendEp0Stall();
}
+#if SLAB_USB_SETUP_CMD_CB
+ }
+ else
+ {
+ // If in-packet but callback didn't setup a USBD_Read and we are expecting a data byte then
+ // we need to wait for the read to be setup and nack packets till USBD_Read is called.
+ if ((myUsbDevice.setup.bmRequestType.Direction == USB_SETUP_DIR_OUT)
+ && (myUsbDevice.ep0.state != D_EP_RECEIVING)
+ && (myUsbDevice.setup.wLength)
+ )
+ {
+ myUsbDevice.ep0.misc.bits.waitForRead = true;
+ }
+ }
+#endif
}
else if (myUsbDevice.ep0.state == D_EP_RECEIVING)
{
@@ -312,9 +281,11 @@ static void handleUsbEp0Int(void)
******************************************************************************/
static void USB_ReadFIFOSetup(void)
{
- SI_VARIABLE_SEGMENT_POINTER(ptr, uint16_t, MEM_MODEL_SEG) = (SI_VARIABLE_SEGMENT_POINTER(, uint16_t, MEM_MODEL_SEG))&myUsbDevice.setup;
+ uint16_t MEM_MODEL_SEG *ptr = &myUsbDevice.setup;
- USB_ReadFIFO(0, 8, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))ptr);
+ USB_ReadFIFO(0, 8, (uint8_t *)ptr);
+
+ USB_Ep0ServicedOutPacketReady();
// Modify for Endian-ness of the compiler
ptr[1] = le16toh(ptr[1]);
@@ -368,11 +339,9 @@ static void handleUsbResetInt(void)
USB_EnableSuspendDetection();
USB_EnableDeviceInts();
- // If the device is bus-powered, always put it in the Default state.
- // If the device is self-powered and VBUS is present, put the device in the
- // Default state. Otherwise, put it in the Attached state.
-#if (!SLAB_USB_BUS_POWERED) && \
- (!(SLAB_USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF))
+ // If VBUS is preset, put the device in the Default state.
+ // Otherwise, put it in the Attached state.
+#if (!(SLAB_USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF))
if (USB_IsVbusOn())
{
USBD_SetUsbState(USBD_STATE_DEFAULT);
@@ -437,16 +406,12 @@ static void handleUsbEp0Tx(void)
// Strings can use the USB_STRING_DESCRIPTOR_UTF16LE_PACKED type to pack
// UTF16LE data without the zero's between each character.
// If the current string is of type USB_STRING_DESCRIPTOR_UTF16LE_PACKED,
- // unpack it by inserting a zero between each character in the string.
- if ((myUsbDevice.ep0String.encoding.type == USB_STRING_DESCRIPTOR_UTF16LE_PACKED)
-#if SLAB_USB_UTF8_STRINGS == 1
- || (myUsbDevice.ep0String.encoding.type == USB_STRING_DESCRIPTOR_UTF8)
-#endif
- )
+ // unpacket it by inserting a zero between each character in the string.
+ if (myUsbDevice.ep0String.encoding.type == USB_STRING_DESCRIPTOR_UTF16LE_PACKED)
{
// If ep0String.encoding.init is true, this is the beginning of the string.
// The first two bytes of the string are the bLength and bDescriptorType
- // fields. These are not packed like the reset of the string, so write them
+ // fields. These are no packed like the reset of the string, so write them
// to the FIFO and set ep0String.encoding.init to false.
if (myUsbDevice.ep0String.encoding.init == true)
{
@@ -459,36 +424,9 @@ static void handleUsbEp0Tx(void)
// Insert a 0x00 between each character of the string.
for (i = 0; i < count / 2; i++)
{
-#if SLAB_USB_UTF8_STRINGS == 1
- if (myUsbDevice.ep0String.encoding.type == USB_STRING_DESCRIPTOR_UTF8)
- {
- SI_SEGMENT_VARIABLE(ucs2, uint16_t, MEM_MODEL_SEG);
- uint8_t utf8count;
-
- // decode the utf8 into ucs2 for usb string
- utf8count = decodeUtf8toUcs2(myUsbDevice.ep0.buf, &ucs2);
-
- // if consumed utf8 bytes is 0, it means either null byte was
- // input or bad utf8 byte sequence. Either way its an error and
- // there's not much we can do. So just advance the input string
- // by one character and keep going until count is expired.
- if (utf8count == 0)
- {
- utf8count = 1;
- }
-
- // adjust to next char in utf8 byte sequence
- myUsbDevice.ep0.buf += utf8count;
- ucs2 = htole16(ucs2); // usb 16-bit chars are little endian
- USB_WriteFIFO(0, 2, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))&ucs2, false);
- }
- else
-#endif
- {
- USB_WriteFIFO(0, 1, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))myUsbDevice.ep0.buf, false);
- myUsbDevice.ep0.buf++;
- USB_WriteFIFO(0, 1, (SI_VARIABLE_SEGMENT_POINTER(, uint8_t, SI_SEG_GENERIC))&txZero, false);
- }
+ USB_WriteFIFO(0, 1, myUsbDevice.ep0.buf, false);
+ myUsbDevice.ep0.buf++;
+ USB_WriteFIFO(0, 1, &txZero, false);
}
}
// For any data other than USB_STRING_DESCRIPTOR_UTF16LE_PACKED, just send the
@@ -588,98 +526,6 @@ void SendEp0Stall(void)
USB_Ep0SendStall();
}
-#if SLAB_USB_UTF8_STRINGS == 1
-/***************************************************************************//**
- * Decodes UTF-8 to UCS-2 (16-bit) character encoding that is used
- * for USB string descriptors.
- *
- * @param pUtf8in pointer to next character in UTF-8 string
- * @param pUcs2out pointer to location for 16-bit character output
- *
- * Decodes a UTF-8 byte sequence into a single UCS-2 character. This
- * will only decode up to 16-bit code point and will not handle the
- * 21-bit case (4 bytes input).
- *
- * For valid cases, the UTF8 character sequence decoded into a 16-bit
- * character and stored at the location pointed at by _pUcs2out_.
- * The function will then return the number of input bytes that were
- * consumed (1, 2, or 3). The caller can use the return value to find
- * the start of the next character sequence in a utf-8 string.
- *
- * If either of the input pointers are NULL, then 0 is returned.
- *
- * If the first input character is NULL, then the output 16-bit value
- * will be set to NULL and the function will return 0.
- *
- * If any other invalid sequence is detected, then the 16-bit output
- * will be set to the equivalent of the question mark character (0x003F)
- * and the return code will be 0.
- *
- * @return count of UTF8 bytes consumed
- ******************************************************************************/
-static uint8_t decodeUtf8toUcs2(
- const uint8_t *pUtf8in,
- SI_VARIABLE_SEGMENT_POINTER(pUcs2out, uint16_t, MEM_MODEL_SEG))
-{
- uint8_t ret = 0;
-
- // check the input pointers
- if (!pUtf8in || !pUcs2out)
- {
- return 0;
- }
-
- // set default decode to error '?';
- *pUcs2out = '?';
-
- // valid cases:
- // 0xxxxxxx (7 bits)
- // 110xxxxx 10xxxxxx (11 bits)
- // 1110xxxx 10xxxxxx 10xxxxxx (16 bits)
-
- // null input
- if (pUtf8in[0] == 0)
- {
- *pUcs2out = 0;
- ret = 0;
- }
-
- // 7-bit char
- else if (pUtf8in[0] < 128)
- {
- *pUcs2out = pUtf8in[0];
- ret = 1;
- }
-
- // 11-bit char
- else if ((pUtf8in[0] & 0xE0) == 0xC0)
- {
- if ((pUtf8in[1] & 0xC0) == 0x80)
- {
- *pUcs2out = ((pUtf8in[0] & 0x1F) << 6) | (pUtf8in[1] & 0x3F);
- ret = 2;
- }
- }
-
- // 16-bit char
- else if ((pUtf8in[0] & 0xF0) == 0xE0)
- {
- if ((pUtf8in[1] & 0xC0) == 0x80)
- {
- if ((pUtf8in[2] & 0xC0) == 0x80)
- {
- *pUcs2out = ((pUtf8in[0] & 0x0F) << 12)
- | ((pUtf8in[1] & 0x3F) << 6)
- | (pUtf8in[2] & 0x3F);
- ret = 3;
- }
- }
- }
-
- return ret;
-}
-#endif // SLAB_USB_UTF8_STRINGS
-
// This function is called from USBD_Init(). It forces the user project to pull
// this module from the library so that the declared ISR can be seen and
// included. If this is not done then this entire module by never be included
diff --git a/efm8/lib/efm8ub1/peripheralDrivers/inc/usb_0.h b/efm8/lib/efm8ub1/peripheralDrivers/inc/usb_0.h
index d094fde..be32bad 100644
--- a/efm8/lib/efm8ub1/peripheralDrivers/inc/usb_0.h
+++ b/efm8/lib/efm8ub1/peripheralDrivers/inc/usb_0.h
@@ -10,6 +10,7 @@
#include "SI_EFM8UB1_Register_Enums.h"
#include
#include
+#include "efm8_config.h"
/******************************************************************************/
@@ -167,7 +168,7 @@ extern void USB_DisableInts(void);
* @brief Returns state of USB interrupt enabler
* @return TRUE if USB interrupts are enabled, FALSE otherwise.
******************************************************************************/
-extern bool USB_GetIntsEnabled(void);
+bool USB_GetIntsEnabled(void);
/***************************************************************************//**
* @brief Enables VBUS detection
@@ -324,7 +325,9 @@ extern void USB_SuspendTransceiver(void);
do \
{ \
SFRPAGE = PG3_PAGE; \
- USB0XCN &= ~(USB0XCN_PHYEN__ENABLED | USB0XCN_Dp__HIGH | USB0XCN_Dn__HIGH);\
+ USB0XCN &= ~(USB0XCN_PHYEN__ENABLED \
+ | USB0XCN_Dp__HIGH \
+ | USB0XCN_Dn__HIGH); \
} while (0)
#endif
@@ -503,14 +506,14 @@ extern void USB_UnsuspendRegulator(void);
* @brief Determine if the internal regulator is enabled
* @return TRUE if the internal regulator is enabled, FALSE otherwise
******************************************************************************/
-extern bool USB_IsRegulatorEnabled(void);
+bool USB_IsRegulatorEnabled(void);
/***************************************************************************//**
* @brief Disable the prefetch engine
* @note This function is implemented as a macro.
******************************************************************************/
#ifdef IS_DOXYGEN
-extern void USB_DisablePrefetch(void);
+void USB_DisablePrefetch(void);
#else
#define USB_DisablePrefetch() \
do \
@@ -525,7 +528,7 @@ extern void USB_DisablePrefetch(void);
* @note This function is implemented as a macro.
******************************************************************************/
#ifdef IS_DOXYGEN
-extern void USB_EnablePrefetch(void);
+void USB_EnablePrefetch(void);
#else
#define USB_EnablePrefetch() \
do \
@@ -539,12 +542,12 @@ extern void USB_EnablePrefetch(void);
* @brief Determine if the prefetch engine is enabled
* @return TRUE if prefetch engine is enabled, FALSE otherwise.
******************************************************************************/
-extern bool USB_IsPrefetchEnabled(void);
+bool USB_IsPrefetchEnabled(void);
/***************************************************************************//**
* @brief Suspends internal oscillator
******************************************************************************/
-extern void USB_SuspendOscillator(void);
+void USB_SuspendOscillator(void);
/***************************************************************************//**
* @brief Enables clock recovery in full speed mode
@@ -731,8 +734,7 @@ extern void USB_Ep0SetLastOutPacketReady(void);
#ifdef IS_DOXYGEN
extern void USB_Ep0SendStall(void);
#else
-#define USB_Ep0SendStall() \
- USB_WRITE_BYTE(E0CSR, (E0CSR_SOPRDY__SET | E0CSR_SDSTL__SET))
+#define USB_Ep0SendStall() USB_WRITE_BYTE(E0CSR, E0CSR_SDSTL__SET)
#endif
/***************************************************************************//**
@@ -964,7 +966,7 @@ extern bool USB_IsOut3IntActive(uint8_t OUT1INT_snapshot);
extern void USB_SetSuspendIntActive(uint8_t CMINT_snapshot);
#else
#define USB_SetSuspendIntActive(CMINT_snapshot) \
- ((CMINT_snapshot) |= CMINT_SUSINT__SET)
+ (CMINT_snapshot |= CMINT_SUSINT__SET)
#endif
/***************************************************************************//**
@@ -978,7 +980,7 @@ extern void USB_SetSuspendIntActive(uint8_t CMINT_snapshot);
extern void USB_SetEp0IntActive(uint8_t IN1INT_snapshot);
#else
#define USB_SetEp0IntActive(IN1INT_snapshot) \
- ((IN1INT_snapshot) |= IN1INT_EP0__SET)
+ (IN1INT_snapshot |= IN1INT_EP0__SET)
#endif
/***************************************************************************//**
@@ -992,7 +994,7 @@ extern void USB_SetEp0IntActive(uint8_t IN1INT_snapshot);
extern void USB_SetIn1IntActive(uint8_t IN1INT_snapshot);
#else
#define USB_SetIn1IntActive(IN1INT_snapshot) \
- ((IN1INT_snapshot) |= IN1INT_IN1__SET)
+ (IN1INT_snapshot |= IN1INT_IN1__SET)
#endif
/***************************************************************************//**
@@ -1006,7 +1008,7 @@ extern void USB_SetIn1IntActive(uint8_t IN1INT_snapshot);
extern void USB_SetIn2IntActive(uint8_t IN1INT_snapshot);
#else
#define USB_SetIn2IntActive(IN1INT_snapshot) \
- ((IN1INT_snapshot) |= IN1INT_IN2__SET)
+ (IN1INT_snapshot |= IN1INT_IN2__SET)
#endif
/***************************************************************************//**
@@ -1020,7 +1022,7 @@ extern void USB_SetIn2IntActive(uint8_t IN1INT_snapshot);
extern void USB_SetIn3IntActive(uint8_t IN1INT_snapshot);
#else
#define USB_SetIn3IntActive(IN1INT_snapshot) \
- ((IN1INT_snapshot) |= IN1INT_IN3__SET)
+ (IN1INT_snapshot |= IN1INT_IN3__SET)
#endif
/***************************************************************************//**
@@ -1034,7 +1036,7 @@ extern void USB_SetIn3IntActive(uint8_t IN1INT_snapshot);
extern void USB_SetOut1IntActive(uint8_t OUT1INT_snapshot);
#else
#define USB_SetOut1IntActive(OUT1INT_snapshot) \
- ((OUT1INT_snapshot) |= OUT1INT_OUT1__SET)
+ (OUT1INT_snapshot |= OUT1INT_OUT1__SET)
#endif
/***************************************************************************//**
@@ -1048,7 +1050,7 @@ extern void USB_SetOut1IntActive(uint8_t OUT1INT_snapshot);
extern void USB_SetOut2IntActive(uint8_t OUT1INT_snapshot);
#else
#define USB_SetOut2IntActive(OUT1INT_snapshot) \
- ((OUT1INT_snapshot) |= OUT1INT_OUT2__SET)
+ (OUT1INT_snapshot |= OUT1INT_OUT2__SET)
#endif
/***************************************************************************//**
@@ -1062,7 +1064,7 @@ extern void USB_SetOut2IntActive(uint8_t OUT1INT_snapshot);
extern void USB_SetOut3IntActive(uint8_t OUT1INT_snapshot);
#else
#define USB_SetOut3IntActive(OUT1INT_snapshot) \
- ((OUT1INT_snapshot) |= OUT1INT_OUT3__SET)
+ (OUT1INT_snapshot |= OUT1INT_OUT3__SET)
#endif
/***************************************************************************//**
@@ -1078,7 +1080,7 @@ extern void USB_EnableDeviceInts(void);
(CMIE_SOFE__ENABLED \
| CMIE_RSTINTE__ENABLED \
| CMIE_RSUINTE__ENABLED \
- | CMIE_SUSINTE__ENABLED))
+ | CMIE_SUSINTE__ENABLED));
#endif
/***************************************************************************//**
@@ -1088,7 +1090,7 @@ extern void USB_EnableDeviceInts(void);
#ifdef IS_DOXYGEN
extern void USB_EnableSofInt(void);
#else
-#define USB_EnableSofInt() USB_SET_BITS(CMIE, CMIE_SOFE__ENABLED)
+#define USB_EnableSofInt() USB_SET_BITS(CMIE, CMIE_SOFE__ENABLED);
#endif
/***************************************************************************//**
@@ -1098,7 +1100,7 @@ extern void USB_EnableSofInt(void);
#ifdef IS_DOXYGEN
extern void USB_DisableSofInt(void);
#else
-#define USB_DisableSofInt() USB_CLEAR_BITS(CMIE, CMIE_SOFE__ENABLED)
+#define USB_DisableSofInt() USB_CLEAR_BITS(CMIE, CMIE_SOFE__ENABLED);
#endif
/***************************************************************************//**
@@ -1108,7 +1110,7 @@ extern void USB_DisableSofInt(void);
#ifdef IS_DOXYGEN
extern void USB_EnableResetInt(void);
#else
-#define USB_EnableResetInt() USB_SET_BITS(CMIE, CMIE_RSTINTE__ENABLED)
+#define USB_EnableResetInt() USB_SET_BITS(CMIE, CMIE_RSTINTE__ENABLED);
#endif
/***************************************************************************//**
@@ -1118,7 +1120,7 @@ extern void USB_EnableResetInt(void);
#ifdef IS_DOXYGEN
extern void USB_DisableResetInt(void);
#else
-#define USB_DisableResetInt() USB_CLEAR_BITS(CMIE, CMIE_RSTINTE__ENABLED)
+#define USB_DisableResetInt() USB_CLEAR_BITS(CMIE, CMIE_RSTINTE__ENABLED);
#endif
/***************************************************************************//**
@@ -1128,7 +1130,7 @@ extern void USB_DisableResetInt(void);
#ifdef IS_DOXYGEN
extern void USB_EnableResumeInt(void);
#else
-#define USB_EnableResumeInt() USB_SET_BITS(CMIE, CMIE_RSUINTE__ENABLED)
+#define USB_EnableResumeInt() USB_SET_BITS(CMIE, CMIE_RSUINTE__ENABLED);
#endif
/***************************************************************************//**
@@ -1138,7 +1140,7 @@ extern void USB_EnableResumeInt(void);
#ifdef IS_DOXYGEN
extern void USB_DisableResumeInt(void);
#else
-#define USB_DisableResumeInt() USB_CLEAR_BITS(CMIE, CMIE_RSUINTE__ENABLED)
+#define USB_DisableResumeInt() USB_CLEAR_BITS(CMIE, CMIE_RSUINTE__ENABLED);
#endif
/***************************************************************************//**
@@ -1148,7 +1150,7 @@ extern void USB_DisableResumeInt(void);
#ifdef IS_DOXYGEN
extern void USB_EnableSuspendInt(void);
#else
-#define USB_EnableSuspendInt() USB_SET_BITS(CMIE, CMIE_SUSINTE__ENABLED)
+#define USB_EnableSuspendInt() USB_SET_BITS(CMIE, CMIE_SUSINTE__ENABLED);
#endif
/***************************************************************************//**
@@ -1158,7 +1160,7 @@ extern void USB_EnableSuspendInt(void);
#ifdef IS_DOXYGEN
extern void USB_DisableSuspendInt(void);
#else
-#define USB_DisableSuspendInt() USB_CLEAR_BITS(CMIE, CMIE_SUSINTE__ENABLED)
+#define USB_DisableSuspendInt() USB_CLEAR_BITS(CMIE, CMIE_SUSINTE__ENABLED);
#endif
/***************************************************************************//**
@@ -1168,7 +1170,7 @@ extern void USB_DisableSuspendInt(void);
#ifdef IS_DOXYGEN
extern void USB_EnableEp0Int(void);
#else
-#define USB_EnableEp0Int() USB_SET_BITS(IN1IE, IN1IE_EP0E__ENABLED)
+#define USB_EnableEp0Int() USB_SET_BITS(IN1IE, IN1IE_EP0E__ENABLED);
#endif
/***************************************************************************//**
@@ -1178,7 +1180,7 @@ extern void USB_EnableEp0Int(void);
#ifdef IS_DOXYGEN
extern void USB_DisableEp0Int(void);
#else
-#define USB_DisableEp0Int() USB_CLEAR_BITS(IN1IE, IN1IE_EP0E__ENABLED)
+#define USB_DisableEp0Int() USB_CLEAR_BITS(IN1IE, IN1IE_EP0E__ENABLED);
#endif
/***************************************************************************//**
@@ -1188,7 +1190,7 @@ extern void USB_DisableEp0Int(void);
#ifdef IS_DOXYGEN
extern void USB_EnableIn1Int(void);
#else
-#define USB_EnableIn1Int() USB_SET_BITS(IN1IE, IN1IE_IN1E__ENABLED)
+#define USB_EnableIn1Int() USB_SET_BITS(IN1IE, IN1IE_IN1E__ENABLED);
#endif
/***************************************************************************//**
@@ -1198,7 +1200,7 @@ extern void USB_EnableIn1Int(void);
#ifdef IS_DOXYGEN
extern void USB_DisableIn1Int(void);
#else
-#define USB_DisableIn1Int() USB_CLEAR_BITS(IN1IE, IN1IE_IN1E__ENABLED)
+#define USB_DisableIn1Int() USB_CLEAR_BITS(IN1IE, IN1IE_IN1E__ENABLED);
#endif
/***************************************************************************//**
@@ -1208,7 +1210,7 @@ extern void USB_DisableIn1Int(void);
#ifdef IS_DOXYGEN
extern void USB_EnableIn2Int(void);
#else
-#define USB_EnableIn2Int() USB_SET_BITS(IN1IE, IN1IE_IN2E__ENABLED)
+#define USB_EnableIn2Int() USB_SET_BITS(IN1IE, IN1IE_IN2E__ENABLED);
#endif
/***************************************************************************//**
@@ -1218,7 +1220,7 @@ extern void USB_EnableIn2Int(void);
#ifdef IS_DOXYGEN
extern void USB_DisableIn2Int(void);
#else
-#define USB_DisableIn2Int() USB_CLEAR_BITS(IN1IE, IN1IE_IN2E__ENABLED)
+#define USB_DisableIn2Int() USB_CLEAR_BITS(IN1IE, IN1IE_IN2E__ENABLED);
#endif
/***************************************************************************//**
@@ -1228,7 +1230,7 @@ extern void USB_DisableIn2Int(void);
#ifdef IS_DOXYGEN
extern void USB_EnableIn3Int(void);
#else
-#define USB_EnableIn3Int() USB_SET_BITS(IN1IE, IN1IE_IN3E__ENABLED)
+#define USB_EnableIn3Int() USB_SET_BITS(IN1IE, IN1IE_IN3E__ENABLED);
#endif
/***************************************************************************//**
@@ -1238,7 +1240,7 @@ extern void USB_EnableIn3Int(void);
#ifdef IS_DOXYGEN
extern void USB_DisableIn3Int(void);
#else
-#define USB_DisableIn3Int() USB_CLEAR_BITS(IN1IE, IN1IE_IN3E__ENABLED)
+#define USB_DisableIn3Int() USB_CLEAR_BITS(IN1IE, IN1IE_IN3E__ENABLED);
#endif
/***************************************************************************//**
@@ -1248,7 +1250,7 @@ extern void USB_DisableIn3Int(void);
#ifdef IS_DOXYGEN
extern void USB_EnableOut1Int(void);
#else
-#define USB_EnableOut1Int() USB_SET_BITS(OUT1IE, OUT1IE_OUT1E__ENABLED)
+#define USB_EnableOut1Int() USB_SET_BITS(OUT1IE, OUT1IE_OUT1E__ENABLED);
#endif
/***************************************************************************//**
@@ -1258,7 +1260,7 @@ extern void USB_EnableOut1Int(void);
#ifdef IS_DOXYGEN
extern void USB_DisableOut1Int(void);
#else
-#define USB_DisableOut1Int() USB_CLEAR_BITS(OUT1IE, OUT1IE_OUT1E__ENABLED)
+#define USB_DisableOut1Int() USB_CLEAR_BITS(OUT1IE, OUT1IE_OUT1E__ENABLED);
#endif
/***************************************************************************//**
@@ -1268,7 +1270,7 @@ extern void USB_DisableOut1Int(void);
#ifdef IS_DOXYGEN
extern void USB_EnableOut2Int(void);
#else
-#define USB_EnableOut2Int() USB_SET_BITS(OUT1IE, OUT1IE_OUT2E__ENABLED)
+#define USB_EnableOut2Int() USB_SET_BITS(OUT1IE, OUT1IE_OUT2E__ENABLED);
#endif
/***************************************************************************//**
@@ -1278,7 +1280,7 @@ extern void USB_EnableOut2Int(void);
#ifdef IS_DOXYGEN
extern void USB_DisableOut2Int(void);
#else
-#define USB_DisableOut2Int() USB_CLEAR_BITS(OUT1IE, OUT1IE_OUT2E__ENABLED)
+#define USB_DisableOut2Int() USB_CLEAR_BITS(OUT1IE, OUT1IE_OUT2E__ENABLED);
#endif
/***************************************************************************//**
@@ -1288,7 +1290,7 @@ extern void USB_DisableOut2Int(void);
#ifdef IS_DOXYGEN
extern void USB_EnableOut3Int(void);
#else
-#define USB_EnableOut3Int() USB_SET_BITS(OUT1IE, OUT1IE_OUT3E__ENABLED)
+#define USB_EnableOut3Int() USB_SET_BITS(OUT1IE, OUT1IE_OUT3E__ENABLED);
#endif
/***************************************************************************//**
@@ -1298,7 +1300,7 @@ extern void USB_EnableOut3Int(void);
#ifdef IS_DOXYGEN
extern void USB_DisableOut3Int(void);
#else
-#define USB_DisableOut3Int() USB_CLEAR_BITS(OUT1IE, OUT1IE_OUT3E__ENABLED)
+#define USB_DisableOut3Int() USB_CLEAR_BITS(OUT1IE, OUT1IE_OUT3E__ENABLED);
#endif
/***************************************************************************//**
@@ -1308,7 +1310,7 @@ extern void USB_DisableOut3Int(void);
#ifdef IS_DOXYGEN
extern void USB_EnableEp1(void);
#else
-#define USB_EnableEp1() USB_SET_BITS(EENABLE, EENABLE_EEN1__ENABLED)
+#define USB_EnableEp1() USB_SET_BITS(EENABLE, EENABLE_EEN1__ENABLED);
#endif
/***************************************************************************//**
@@ -1318,7 +1320,7 @@ extern void USB_EnableEp1(void);
#ifdef IS_DOXYGEN
extern void USB_DisableEp1(void);
#else
-#define USB_DisableEp1() USB_CLEAR_BITS(EENABLE, EENABLE_EEN1__ENABLED)
+#define USB_DisableEp1() USB_CLEAR_BITS(EENABLE, EENABLE_EEN1__ENABLED);
#endif
/***************************************************************************//**
@@ -1328,7 +1330,7 @@ extern void USB_DisableEp1(void);
#ifdef IS_DOXYGEN
extern void USB_EnableEp2(void);
#else
-#define USB_EnableEp2() USB_SET_BITS(EENABLE, EENABLE_EEN2__ENABLED)
+#define USB_EnableEp2() USB_SET_BITS(EENABLE, EENABLE_EEN2__ENABLED);
#endif
/***************************************************************************//**
@@ -1338,7 +1340,7 @@ extern void USB_EnableEp2(void);
#ifdef IS_DOXYGEN
extern void USB_DisableEp2(void);
#else
-#define USB_DisableEp2() USB_CLEAR_BITS(EENABLE, EENABLE_EEN2__ENABLED)
+#define USB_DisableEp2() USB_CLEAR_BITS(EENABLE, EENABLE_EEN2__ENABLED);
#endif
/***************************************************************************//**
@@ -1348,7 +1350,7 @@ extern void USB_DisableEp2(void);
#ifdef IS_DOXYGEN
extern void USB_EnableEp3(void);
#else
-#define USB_EnableEp3() USB_SET_BITS(EENABLE, EENABLE_EEN3__ENABLED)
+#define USB_EnableEp3() USB_SET_BITS(EENABLE, EENABLE_EEN3__ENABLED);
#endif
/***************************************************************************//**
@@ -1358,7 +1360,7 @@ extern void USB_EnableEp3(void);
#ifdef IS_DOXYGEN
extern void USB_DisableEp3(void);
#else
-#define USB_DisableEp3() USB_CLEAR_BITS(EENABLE, EENABLE_EEN3__ENABLED)
+#define USB_DisableEp3() USB_CLEAR_BITS(EENABLE, EENABLE_EEN3__ENABLED);
#endif
/***************************************************************************//**
@@ -1368,7 +1370,7 @@ extern void USB_DisableEp3(void);
#ifdef IS_DOXYGEN
extern void USB_EpnDirectionOut(void);
#else
-#define USB_EpnDirectionOut() USB_CLEAR_BITS(EINCSRH, EINCSRH_DIRSEL__IN)
+#define USB_EpnDirectionOut() USB_CLEAR_BITS(EINCSRH, EINCSRH_DIRSEL__IN);
#endif
/***************************************************************************//**
@@ -1378,7 +1380,7 @@ extern void USB_EpnDirectionOut(void);
#ifdef IS_DOXYGEN
extern void USB_EpnDirectionIn(void);
#else
-#define USB_EpnDirectionIn() USB_SET_BITS(EINCSRH, EINCSRH_DIRSEL__IN)
+#define USB_EpnDirectionIn() USB_SET_BITS(EINCSRH, EINCSRH_DIRSEL__IN);
#endif
/***************************************************************************//**
@@ -1389,7 +1391,7 @@ extern void USB_EpnDirectionIn(void);
extern void USB_EpnEnableSplitMode(void);
#else
#define USB_EpnEnableSplitMode() \
- USB_SET_BITS(EINCSRH, EINCSRH_SPLIT__ENABLED)
+ USB_SET_BITS(EINCSRH, EINCSRH_SPLIT__ENABLED);
#endif
/***************************************************************************//**
@@ -1400,7 +1402,7 @@ extern void USB_EpnEnableSplitMode(void);
extern void USB_EpnDisableSplitMode(void);
#else
#define USB_EpnDisableSplitMode() \
- USB_CLEAR_BITS(EINCSRH, EINCSRH_SPLIT__ENABLED)
+ USB_CLEAR_BITS(EINCSRH, EINCSRH_SPLIT__ENABLED);
#endif
/***************************************************************************//**
@@ -1410,7 +1412,7 @@ extern void USB_EpnDisableSplitMode(void);
#ifdef IS_DOXYGEN
extern void USB_EpnInClearDataToggle(void);
#else
-#define USB_EpnInClearDataToggle() USB_SET_BITS(EINCSRL, EINCSRL_CLRDT__BMASK)
+#define USB_EpnInClearDataToggle() USB_SET_BITS(EINCSRL, EINCSRL_CLRDT__BMASK);
#endif
/***************************************************************************//**
@@ -1420,7 +1422,7 @@ extern void USB_EpnInClearDataToggle(void);
#ifdef IS_DOXYGEN
extern void USB_EpnInClearSentStall(void);
#else
-#define USB_EpnInClearSentStall() USB_WRITE_BYTE(EINCSRL, 0)
+#define USB_EpnInClearSentStall() USB_WRITE_BYTE(EINCSRL, 0);
#endif
/***************************************************************************//**
@@ -1430,7 +1432,7 @@ extern void USB_EpnInClearSentStall(void);
#ifdef IS_DOXYGEN
extern void USB_EpnInStall(void);
#else
-#define USB_EpnInStall() USB_WRITE_BYTE(EINCSRL, EINCSRL_SDSTL__SET)
+#define USB_EpnInStall() USB_WRITE_BYTE(EINCSRL, EINCSRL_SDSTL__SET);
#endif
/***************************************************************************//**
@@ -1440,7 +1442,7 @@ extern void USB_EpnInStall(void);
#ifdef IS_DOXYGEN
extern void USB_EpnInEndStall(void);
#else
-#define USB_EpnInEndStall() USB_WRITE_BYTE(EINCSRL, 0)
+#define USB_EpnInEndStall() USB_WRITE_BYTE(EINCSRL, 0);
#endif
/***************************************************************************//**
@@ -1452,7 +1454,7 @@ extern void USB_EpnInEndStall(void);
extern void USB_EpnInEndStallAndClearDataToggle(void);
#else
#define USB_EpnInEndStallAndClearDataToggle() \
- USB_WRITE_BYTE(EINCSRL, EINCSRL_CLRDT__BMASK)
+ USB_WRITE_BYTE(EINCSRL, EINCSRL_CLRDT__BMASK);
#endif
/***************************************************************************//**
@@ -1470,7 +1472,7 @@ extern void USB_EpnInFlush(void);
{ \
USB_READ_BYTE(EINCSRL); \
} while (USB0DAT & EINCSRL_FLUSH__SET); \
- } while (0)
+ } while (0);
#endif
/***************************************************************************//**
@@ -1480,7 +1482,7 @@ extern void USB_EpnInFlush(void);
#ifdef IS_DOXYGEN
extern void USB_EpnInClearUnderrun(void);
#else
-#define USB_EpnInClearUnderrun() USB_CLEAR_BITS(EINCSRL, EINCSRL_UNDRUN__SET)
+#define USB_EpnInClearUnderrun() USB_CLEAR_BITS(EINCSRL, EINCSRL_UNDRUN__SET);
#endif
/***************************************************************************//**
@@ -1490,7 +1492,7 @@ extern void USB_EpnInClearUnderrun(void);
#ifdef IS_DOXYGEN
extern void USB_EpnSetInPacketReady(void);
#else
-#define USB_EpnSetInPacketReady() USB_SET_BITS(EINCSRL, EINCSRL_INPRDY__SET)
+#define USB_EpnSetInPacketReady() USB_SET_BITS(EINCSRL, EINCSRL_INPRDY__SET);
#endif
/***************************************************************************//**
@@ -1501,7 +1503,7 @@ extern void USB_EpnSetInPacketReady(void);
extern void USB_EpnInEnableDoubleBuffer(void);
#else
#define USB_EpnInEnableDoubleBuffer() \
- USB_SET_BITS(EINCSRH, EINCSRH_DBIEN__ENABLED)
+ USB_SET_BITS(EINCSRH, EINCSRH_DBIEN__ENABLED);
#endif
/***************************************************************************//**
@@ -1512,7 +1514,7 @@ extern void USB_EpnInEnableDoubleBuffer(void);
extern void USB_EpnInDisableDoubleBuffer(void);
#else
#define USB_EpnInDisableDoubleBuffer() \
- USB_CLEAR_BITS(EINCSRH, EINCSRH_DBIEN__ENABLED)
+ USB_CLEAR_BITS(EINCSRH, EINCSRH_DBIEN__ENABLED);
#endif
/***************************************************************************//**
@@ -1523,7 +1525,7 @@ extern void USB_EpnInDisableDoubleBuffer(void);
extern void USB_EpnInEnableInterruptBulkMode(void);
#else
#define USB_EpnInEnableInterruptBulkMode() \
- USB_CLEAR_BITS(EINCSRH, EINCSRH_ISO__ENABLED)
+ USB_CLEAR_BITS(EINCSRH, EINCSRH_ISO__ENABLED);
#endif
/***************************************************************************//**
@@ -1534,7 +1536,7 @@ extern void USB_EpnInEnableInterruptBulkMode(void);
extern void USB_EpnInEnableIsochronousMode(void);
#else
#define USB_EpnInEnableIsochronousMode() \
- USB_SET_BITS(EINCSRH, EINCSRH_ISO__ENABLED)
+ USB_SET_BITS(EINCSRH, EINCSRH_ISO__ENABLED);
#endif
/***************************************************************************//**
@@ -1545,7 +1547,7 @@ extern void USB_EpnInEnableIsochronousMode(void);
extern void USB_EpnInEnableForcedDataToggle(void);
#else
#define USB_EpnInEnableForcedDataToggle() \
- USB_SET_BITS(EINCSRH, EINCSRH_FCDT__ALWAYS_TOGGLE)
+ USB_SET_BITS(EINCSRH, EINCSRH_FCDT__ALWAYS_TOGGLE);
#endif
/***************************************************************************//**
@@ -1556,7 +1558,7 @@ extern void USB_EpnInEnableForcedDataToggle(void);
extern void USB_EpnInDisableForcedDataToggle(void);
#else
#define USB_EpnInDisableForcedDataToggle() \
- USB_CLEAR_BITS(EINCSRH, EINCSRH_FCDT__ALWAYS_TOGGLE)
+ USB_CLEAR_BITS(EINCSRH, EINCSRH_FCDT__ALWAYS_TOGGLE);
#endif
/***************************************************************************//**
@@ -1567,7 +1569,7 @@ extern void USB_EpnInDisableForcedDataToggle(void);
extern void USB_EpnOutClearDataToggle(void);
#else
#define USB_EpnOutClearDataToggle() \
- USB_SET_BITS(EOUTCSRL, EOUTCSRL_CLRDT__BMASK)
+ USB_SET_BITS(EOUTCSRL, EOUTCSRL_CLRDT__BMASK);
#endif
/***************************************************************************//**
@@ -1578,7 +1580,7 @@ extern void USB_EpnOutClearDataToggle(void);
extern void USB_EpnOutClearSentStall(void);
#else
#define USB_EpnOutClearSentStall() \
- USB_CLEAR_BITS(EOUTCSRL, EOUTCSRL_STSTL__BMASK)
+ USB_CLEAR_BITS(EOUTCSRL, EOUTCSRL_STSTL__BMASK);
#endif
/***************************************************************************//**
@@ -1589,7 +1591,7 @@ extern void USB_EpnOutClearSentStall(void);
extern void USB_EpnOutStall(void);
#else
#define USB_EpnOutStall() \
- USB_SET_BITS(EOUTCSRL, EOUTCSRL_SDSTL__SET)
+ USB_SET_BITS(EOUTCSRL, EOUTCSRL_SDSTL__SET);
#endif
/***************************************************************************//**
@@ -1599,7 +1601,7 @@ extern void USB_EpnOutStall(void);
#ifdef IS_DOXYGEN
extern void USB_EpnOutEndStall(void);
#else
-#define USB_EpnOutEndStall() USB_CLEAR_BITS(EOUTCSRL, EOUTCSRL_SDSTL__SET)
+#define USB_EpnOutEndStall() USB_CLEAR_BITS(EOUTCSRL, EOUTCSRL_SDSTL__SET);
#endif
/***************************************************************************//**
@@ -1618,7 +1620,7 @@ extern void USB_EpnOutEndStallAndClearDataToggle(void);
while (USB0ADR & USB0ADR_BUSY__SET) {} \
USB0DAT |= EOUTCSRL_CLRDT__BMASK; \
while (USB0ADR & USB0ADR_BUSY__SET) {} \
- } while (0)
+ } while (0);
#endif
/***************************************************************************//**
@@ -1636,7 +1638,7 @@ extern void USB_EpnOutFlush(void);
{ \
USB_READ_BYTE(EOUTCSRL); \
} while (USB0DAT & EOUTCSRL_FLUSH__SET); \
- } while (0)
+ } while (0);
#endif
/***************************************************************************//**
@@ -1646,7 +1648,7 @@ extern void USB_EpnOutFlush(void);
#ifdef IS_DOXYGEN
extern void USB_EpnOutClearOverrun(void);
#else
-#define USB_EpnOutClearOverrun() USB_CLEAR_BITS(EOUTCSRL, EOUTCSRL_OVRUN__SET)
+#define USB_EpnOutClearOverrun() USB_CLEAR_BITS(EOUTCSRL, EOUTCSRL_OVRUN__SET);
#endif
/***************************************************************************//**
@@ -1657,7 +1659,7 @@ extern void USB_EpnOutClearOverrun(void);
extern void USB_EpnClearOutPacketReady(void);
#else
#define USB_EpnClearOutPacketReady() \
- USB_CLEAR_BITS(EOUTCSRL, EOUTCSRL_OPRDY__SET)
+ USB_CLEAR_BITS(EOUTCSRL, EOUTCSRL_OPRDY__SET);
#endif
/***************************************************************************//**
@@ -1668,7 +1670,7 @@ extern void USB_EpnClearOutPacketReady(void);
extern void USB_EpnOutEnableDoubleBuffer(void);
#else
#define USB_EpnOutEnableDoubleBuffer() \
- USB_SET_BITS(EOUTCSRH, EOUTCSRH_DBIEN__ENABLED)
+ USB_SET_BITS(EOUTCSRH, EOUTCSRH_DBIEN__ENABLED);
#endif
/***************************************************************************//**
@@ -1679,7 +1681,7 @@ extern void USB_EpnOutEnableDoubleBuffer(void);
extern void USB_EpnOutDisableDoubleBuffer(void);
#else
#define USB_EpnOutDisableDoubleBuffer() \
- USB_CLEAR_BITS(EOUTCSRH, EOUTCSRH_DBIEN__ENABLED)
+ USB_CLEAR_BITS(EOUTCSRH, EOUTCSRH_DBIEN__ENABLED);
#endif
/***************************************************************************//**
@@ -1690,7 +1692,7 @@ extern void USB_EpnOutDisableDoubleBuffer(void);
extern void USB_EpnOutEnableInterruptBulkMode(void);
#else
#define USB_EpnOutEnableInterruptBulkMode() \
- USB_CLEAR_BITS(EOUTCSRH, EOUTCSRH_ISO__ENABLED)
+ USB_CLEAR_BITS(EOUTCSRH, EOUTCSRH_ISO__ENABLED);
#endif
/***************************************************************************//**
@@ -1701,7 +1703,7 @@ extern void USB_EpnOutEnableInterruptBulkMode(void);
extern void USB_EpnOutEnableIsochronousMode(void);
#else
#define USB_EpnOutEnableIsochronousMode() \
- USB_SET_BITS(EOUTCSRH, EOUTCSRH_ISO__ENABLED)
+ USB_SET_BITS(EOUTCSRH, EOUTCSRH_ISO__ENABLED);
#endif
/***************************************************************************//**
@@ -1719,7 +1721,7 @@ extern void USB_EnableReadFIFO(uint8_t fifoNum);
while (USB0ADR & USB0ADR_BUSY__SET) {} \
USB0ADR = (USB0ADR_BUSY__SET \
| USB0ADR_AUTORD__ENABLED \
- | (FIFO0 | (fifoNum))); \
+ | (FIFO0 | fifoNum)); \
} while (0)
#endif
@@ -1742,13 +1744,13 @@ extern void USB_DisableReadFIFO(uint8_t fifoNum);
* @note This function is implemented as a macro.
******************************************************************************/
#ifdef IS_DOXYGEN
-extern void USB_GetFIFOByte(uint8_t *readDat);
+extern void USB_GetFIFOByte(uint8_t * readDat);
#else
#define USB_GetFIFOByte(readDat) \
do \
{ \
while (USB0ADR & USB0ADR_BUSY__SET) {} \
- *(readDat) = USB0DAT; \
+ readDat = USB0DAT; \
} while (0)
#endif
@@ -1764,14 +1766,14 @@ extern void USB_GetFIFOByte(uint8_t *readDat);
* @note This function is implemented as a macro.
******************************************************************************/
#ifdef IS_DOXYGEN
-extern void USB_GetLastFIFOByte(uint8_t *readDat, uint8_t fifoNum);
+extern void USB_GetLastFIFOByte(uint8_t * readDat, uint8_t fifoNum);
#else
#define USB_GetLastFIFOByte(readDat, fifoNum) \
do \
{ \
while (USB0ADR & USB0ADR_BUSY__SET) {} \
- USB0ADR = (FIFO0 | (fifoNum));\
- *(readDat) = USB0DAT; \
+ USB0ADR = (FIFO0 | fifoNum);\
+ readDat = USB0DAT; \
} while (0)
#endif
@@ -1788,7 +1790,7 @@ extern void USB_EnableWriteFIFO(uint8_t fifoNum);
do \
{ \
while (USB0ADR & USB0ADR_BUSY__SET) {} \
- USB0ADR = (FIFO0 | (fifoNum)); \
+ USB0ADR = (FIFO0 | fifoNum); \
} while (0)
#endif
@@ -1817,7 +1819,7 @@ extern void USB_SetFIFOByte(uint8_t writeDat);
do \
{ \
while (USB0ADR & USB0ADR_BUSY__SET) {} \
- USB0DAT = (writeDat); \
+ USB0DAT = writeDat; \
} while (0)
#endif
@@ -1850,98 +1852,92 @@ extern void USB_RestoreSfrPage();
* @param epsel
* Endpoint index to target
******************************************************************************/
-extern void USB_SetIndex(uint8_t epsel);
+void USB_SetIndex(uint8_t epsel);
/***************************************************************************//**
* @brief Reads the USB common interrupt register
* @return Value of CMINT
******************************************************************************/
-extern uint8_t USB_GetCommonInts(void);
+uint8_t USB_GetCommonInts(void);
/***************************************************************************//**
* @brief Reads the USB in interrupt register
* @return Value of IN1INT
******************************************************************************/
-extern uint8_t USB_GetInInts(void);
+uint8_t USB_GetInInts(void);
/***************************************************************************//**
* @brief Reads the out interrupt register
* @return Value of OUT1INT
******************************************************************************/
-extern uint8_t USB_GetOutInts(void);
+uint8_t USB_GetOutInts(void);
/***************************************************************************//**
* @brief Reads the value in INDEX
* @return Value of INDEX
******************************************************************************/
-extern uint8_t USB_GetIndex(void);
+uint8_t USB_GetIndex(void);
/***************************************************************************//**
* @brief Determines if the USB is currently suspended
* @return TRUE if USB is in suspend mode
******************************************************************************/
-extern bool USB_IsSuspended(void);
+bool USB_IsSuspended(void);
/***************************************************************************//**
* @brief Gets Setup End state
* @return TRUE when a control transaction end before software has
* set the DATAEND bit.
******************************************************************************/
-extern bool USB_GetSetupEnd(void);
+bool USB_GetSetupEnd(void);
/***************************************************************************//**
* @brief Determines if STALL was send on Endpoint 0
* @return TRUE after a STALL was sent on Endpoint 0
******************************************************************************/
-extern bool USB_Ep0SentStall(void);
+bool USB_Ep0SentStall(void);
/***************************************************************************//**
* @brief Determines if Out Packet Ready is set on Endpoint 0
* @return TRUE if Out Packet Ready is set on Endpoint 0
******************************************************************************/
-extern bool USB_Ep0InPacketReady(void);
+bool USB_Ep0InPacketReady(void);
/***************************************************************************//**
* @brief Determines if In Packet Ready is set on Endpoint 0
* @return TRUE if In Packet Ready is set on Endpoint 0
******************************************************************************/
-extern bool USB_Ep0OutPacketReady(void);
+bool USB_Ep0OutPacketReady(void);
/***************************************************************************//**
* @brief Gets Endpoint 0 data count
* @return Number of received data bytes in the Endpoint 0 FIFO
******************************************************************************/
-extern uint8_t USB_Ep0GetCount(void);
+uint8_t USB_Ep0GetCount(void);
/***************************************************************************//**
* @brief Checks if stall was sent on IN Endpoint N
* @return TRUE if stall was sent on IN Endpoint N, FALSE otherwise
******************************************************************************/
-extern bool USB_EpnInGetSentStall(void);
+bool USB_EpnInGetSentStall(void);
/***************************************************************************//**
* @brief Checks if stall was sent on OUT Endpoint N
* @return TRUE if stall was sent on OUT Endpoint N, FALSE otherwise
******************************************************************************/
-extern bool USB_EpnGetInPacketReady(void);
+bool USB_EpnGetInPacketReady(void);
/***************************************************************************//**
* @brief Checks if stall was sent on OUT Endpoint N
* @return TRUE if stall was sent on OUT Endpoint N, FALSE otherwise
******************************************************************************/
-extern bool USB_EpnOutGetSentStall(void);
+bool USB_EpnOutGetSentStall(void);
/***************************************************************************//**
* @brief Gets OutPacketReady on OUT Endpoint N
* @return TRUE if OUTPacketReady is set, FALSE otherwise
******************************************************************************/
-extern bool USB_EpnGetOutPacketReady(void);
-
-/***************************************************************************//**
- * @brief Gets DataError on OUT Endpoint N
- * @return TRUE if Data Error bit is set, FALSE otherwise
- ******************************************************************************/
-extern bool USB_EpnGetDataError(void);
+bool USB_EpnGetOutPacketReady(void);
/***************************************************************************//**
* @brief Gets number of bytes in the OUT FIFO
@@ -1949,27 +1945,27 @@ extern bool USB_EpnGetDataError(void);
* @return Number of bytes in the FIFO from the last received
* packet
******************************************************************************/
-extern uint16_t USB_EpOutGetCount(void);
+uint16_t USB_EpOutGetCount(void);
/***************************************************************************//**
* @brief Reads the USB frame number
* @return The frame number on the most recent SOF packet
******************************************************************************/
-extern uint16_t USB_GetSofNumber(void);
+uint16_t USB_GetSofNumber(void);
/***************************************************************************//**
* @brief Aborts pending IN transactions on the selected endpoint
* @param fifoNum
* Endpoint to abort
******************************************************************************/
-extern void USB_AbortInEp(uint8_t fifoNum);
+void USB_AbortInEp(uint8_t fifoNum);
/***************************************************************************//**
* @brief Aborts pending OUT transactions on the selected endpoint
* @param fifoNum
* Endpoint to abort
******************************************************************************/
-extern void USB_AbortOutEp(uint8_t fifoNum);
+void USB_AbortOutEp(uint8_t fifoNum);
/***************************************************************************//**
* @brief Activates the selected endpoint
@@ -1984,11 +1980,11 @@ extern void USB_AbortOutEp(uint8_t fifoNum);
* @param isoMode
* Set to 1 if endpoint is in isochronous mode, 0 if it is not
******************************************************************************/
-extern void USB_ActivateEp(uint8_t ep,
- uint16_t packetSize,
- bool inDir,
- bool splitMode,
- bool isoMode);
+void USB_ActivateEp(uint8_t ep,
+ uint16_t packetSize,
+ bool inDir,
+ bool splitMode,
+ bool isoMode);
/** @} (end addtogroup usb_0_runtime USB0 Runtime API) */
/** @} (end addtogroup usb_0_group USB0 Driver) */
diff --git a/efm8/lib/efm8ub1/peripheralDrivers/src/usb_0.c b/efm8/lib/efm8ub1/peripheralDrivers/src/usb_0.c
index 91a03ea..9c44e3f 100644
--- a/efm8/lib/efm8ub1/peripheralDrivers/src/usb_0.c
+++ b/efm8/lib/efm8ub1/peripheralDrivers/src/usb_0.c
@@ -18,7 +18,7 @@
/**************************************************************************//**
* @brief Reads a 16-bit indirect USB register value
- * @param [in] regAddr
+ * @param regAddr
* Address of high byte of 16-bit USB indirect register to read
* @return 16-bit register value
*****************************************************************************/
@@ -127,12 +127,6 @@ bool USB_EpnGetOutPacketReady(void)
return (bool)(USB0DAT & EOUTCSRL_OPRDY__SET);
}
-bool USB_EpnGetDataError(void)
-{
- USB_READ_BYTE(EOUTCSRL);
- return (bool)(USB0DAT & EOUTCSRL_DATERR__SET);
-}
-
uint16_t USB_EpOutGetCount(void)
{
return USB_GetShortRegister(EOUTCNTH);
diff --git a/efm8/src/InitDevice.c b/efm8/src/InitDevice.c
index 1c75b3c..2f86874 100644
--- a/efm8/src/InitDevice.c
+++ b/efm8/src/InitDevice.c
@@ -29,8 +29,8 @@ extern void enter_DefaultMode_from_RESET(void) {
WDT_0_enter_DefaultMode_from_RESET();
PORTS_0_enter_DefaultMode_from_RESET();
PORTS_1_enter_DefaultMode_from_RESET();
- PORTS_2_enter_DefaultMode_from_RESET();
PBCFG_0_enter_DefaultMode_from_RESET();
+ LFOSC_0_enter_DefaultMode_from_RESET();
CIP51_0_enter_DefaultMode_from_RESET();
CLOCK_0_enter_DefaultMode_from_RESET();
TIMER01_0_enter_DefaultMode_from_RESET();
@@ -184,14 +184,14 @@ extern void TIMER_SETUP_0_enter_DefaultMode_from_RESET(void) {
- System clock divided by 4
- Counter/Timer 0 uses the clock defined by the prescale field, SCA
- Timer 2 high byte uses the clock defined by T2XCLK in TMR2CN0
- - Timer 2 low byte uses the system clock
+ - Timer 2 low byte uses the clock defined by T2XCLK in TMR2CN0
- Timer 3 high byte uses the clock defined by T3XCLK in TMR3CN0
- - Timer 3 low byte uses the system clock
+ - Timer 3 low byte uses the clock defined by T3XCLK in TMR3CN0
- Timer 1 uses the system clock
***********************************************************************/
CKCON0 = CKCON0_SCA__SYSCLK_DIV_4 | CKCON0_T0M__PRESCALE
- | CKCON0_T2MH__EXTERNAL_CLOCK | CKCON0_T2ML__SYSCLK
- | CKCON0_T3MH__EXTERNAL_CLOCK | CKCON0_T3ML__SYSCLK
+ | CKCON0_T2MH__EXTERNAL_CLOCK | CKCON0_T2ML__EXTERNAL_CLOCK
+ | CKCON0_T3MH__EXTERNAL_CLOCK | CKCON0_T3ML__EXTERNAL_CLOCK
| CKCON0_T1M__SYSCLK;
// [CKCON0 - Clock Control 0]$
@@ -288,23 +288,19 @@ extern void TIMER16_2_enter_DefaultMode_from_RESET(void) {
// $[TMR2RLH - Timer 2 Reload High Byte]
/***********************************************************************
- - Timer 2 Reload High Byte = 0x44
+ - Timer 2 Reload High Byte = 0x63
***********************************************************************/
- TMR2RLH = (0x44 << TMR2RLH_TMR2RLH__SHIFT);
+ TMR2RLH = (0x63 << TMR2RLH_TMR2RLH__SHIFT);
// [TMR2RLH - Timer 2 Reload High Byte]$
// $[TMR2RLL - Timer 2 Reload Low Byte]
/***********************************************************************
- - Timer 2 Reload Low Byte = 0x80
+ - Timer 2 Reload Low Byte = 0xC0
***********************************************************************/
- TMR2RLL = (0x80 << TMR2RLL_TMR2RLL__SHIFT);
+ TMR2RLL = (0xC0 << TMR2RLL_TMR2RLL__SHIFT);
// [TMR2RLL - Timer 2 Reload Low Byte]$
// $[TMR2CN0]
- /***********************************************************************
- - Start Timer 2 running
- ***********************************************************************/
- TMR2CN0 |= TMR2CN0_TR2__RUN;
// [TMR2CN0]$
// $[Timer Restoration]
@@ -327,6 +323,10 @@ extern void TIMER16_3_enter_DefaultMode_from_RESET(void) {
// [TMR3CN1 - Timer 3 Control 1]$
// $[TMR3CN0 - Timer 3 Control]
+ /***********************************************************************
+ - Timer 3 clock is the low-frequency oscillator divided by 8
+ ***********************************************************************/
+ TMR3CN0 |= TMR3CN0_T3XCLK__LFOSC_DIV_8;
// [TMR3CN0 - Timer 3 Control]$
// $[TMR3H - Timer 3 High Byte]
@@ -342,6 +342,10 @@ extern void TIMER16_3_enter_DefaultMode_from_RESET(void) {
// [TMR3RLL - Timer 3 Reload Low Byte]$
// $[TMR3CN0]
+ /***********************************************************************
+ - Start Timer 3 running
+ ***********************************************************************/
+ TMR3CN0 |= TMR3CN0_TR3__RUN;
// [TMR3CN0]$
// $[Timer Restoration]
@@ -408,7 +412,7 @@ extern void PORTS_1_enter_DefaultMode_from_RESET(void) {
// $[P1MDOUT - Port 1 Output Mode]
/***********************************************************************
- P1.0 output is open-drain
- - P1.1 output is open-drain
+ - P1.1 output is push-pull
- P1.2 output is open-drain
- P1.3 output is open-drain
- P1.4 output is push-pull
@@ -416,7 +420,7 @@ extern void PORTS_1_enter_DefaultMode_from_RESET(void) {
- P1.6 output is push-pull
- P1.7 output is open-drain
***********************************************************************/
- P1MDOUT = P1MDOUT_B0__OPEN_DRAIN | P1MDOUT_B1__OPEN_DRAIN
+ P1MDOUT = P1MDOUT_B0__OPEN_DRAIN | P1MDOUT_B1__PUSH_PULL
| P1MDOUT_B2__OPEN_DRAIN | P1MDOUT_B3__OPEN_DRAIN
| P1MDOUT_B4__PUSH_PULL | P1MDOUT_B5__PUSH_PULL
| P1MDOUT_B6__PUSH_PULL | P1MDOUT_B7__OPEN_DRAIN;
@@ -520,9 +524,9 @@ extern void UART_0_enter_DefaultMode_from_RESET(void) {
extern void SPI_0_enter_DefaultMode_from_RESET(void) {
// $[SPI0CKR - SPI0 Clock Rate]
/***********************************************************************
- - SPI0 Clock Rate = 0x17
+ - SPI0 Clock Rate = 0x0B
***********************************************************************/
- SPI0CKR = (0x17 << SPI0CKR_SPI0CKR__SHIFT);
+ SPI0CKR = (0x0B << SPI0CKR_SPI0CKR__SHIFT);
// [SPI0CKR - SPI0 Clock Rate]$
// $[SPI0FCN0 - SPI0 FIFO Control 0]
@@ -545,3 +549,20 @@ extern void SPI_0_enter_DefaultMode_from_RESET(void) {
}
+extern void LFOSC_0_enter_DefaultMode_from_RESET(void) {
+ // $[LFO0CN - Low Frequency Oscillator Control]
+ /***********************************************************************
+ - Internal L-F Oscillator Enabled
+ - Divide by 8 selected
+ ***********************************************************************/
+ LFO0CN &= ~LFO0CN_OSCLD__FMASK;
+ LFO0CN |= LFO0CN_OSCLEN__ENABLED;
+ // [LFO0CN - Low Frequency Oscillator Control]$
+
+ // $[Wait for LFOSC Ready]
+ while ((LFO0CN & LFO0CN_OSCLRDY__BMASK) != LFO0CN_OSCLRDY__SET)
+ ;
+ // [Wait for LFOSC Ready]$
+
+}
+
diff --git a/efm8/src/callback.c b/efm8/src/callback.c
index cf9008f..968e4b2 100644
--- a/efm8/src/callback.c
+++ b/efm8/src/callback.c
@@ -38,6 +38,7 @@ uint8_t tmpBuffer;
void USBD_ResetCb(void) {
+// cprints("USBD_ResetCb\r\n");
// u2f_print_ev("USBD_ResetCb\r\n");
}
@@ -45,6 +46,7 @@ void USBD_ResetCb(void) {
void USBD_DeviceStateChangeCb(USBD_State_TypeDef oldState,
USBD_State_TypeDef newState) {
+// cprints("USBD_DeviceStateChangeCb\r\n");
UNUSED(oldState);
UNUSED(newState);
@@ -52,6 +54,7 @@ void USBD_DeviceStateChangeCb(USBD_State_TypeDef oldState,
}
bool USBD_IsSelfPoweredCb(void) {
+// cprints("USBD_IsSelfPoweredCb\r\n");
return false;
}
@@ -60,19 +63,22 @@ USB_Status_TypeDef USBD_SetupCmdCb(
SI_VARIABLE_SEGMENT_POINTER(setup, USB_Setup_TypeDef, MEM_MODEL_SEG)) {
USB_Status_TypeDef retVal = USB_STATUS_REQ_UNHANDLED;
-
+// USB_Status_TypeDef retVal = USB_STATUS_OK;
+// cprints("USBD_SetupCmdCb\r\n");
if ((setup->bmRequestType.Type == USB_SETUP_TYPE_STANDARD)
&& (setup->bmRequestType.Direction == USB_SETUP_DIR_IN)
&& (setup->bmRequestType.Recipient == USB_SETUP_RECIPIENT_INTERFACE)) {
// A HID device must extend the standard GET_DESCRIPTOR command
// with support for HID descriptors.
-
+// cprints("USB_SETUP_TYPE_STANDARD\r\n");
switch (setup->bRequest) {
case GET_DESCRIPTOR:
+// cprints("GET_DESCRIPTOR\r\n");
if (setup->wIndex == 0)
{
if ((setup->wValue >> 8) == USB_HID_REPORT_DESCRIPTOR) {
+// cprints("1\r\n");
USBD_Write(EP0, ReportDescriptor0,
EFM8_MIN(sizeof(ReportDescriptor0), setup->wLength),
@@ -80,7 +86,7 @@ USB_Status_TypeDef USBD_SetupCmdCb(
retVal = USB_STATUS_OK;
} else if ((setup->wValue >> 8) == USB_HID_DESCRIPTOR) {
-
+// cprints("2\r\n");
USBD_Write(EP0, (&configDesc[18]),
EFM8_MIN(USB_HID_DESCSIZE, setup->wLength), false);
retVal = USB_STATUS_OK;
@@ -94,10 +100,12 @@ USB_Status_TypeDef USBD_SetupCmdCb(
&& (setup->bmRequestType.Recipient == USB_SETUP_RECIPIENT_INTERFACE)
&& (setup->wIndex == HID_INTERFACE_INDEX))
{
+// cprints("USB_SETUP_TYPE_CLASS\r\n");
// Implement the necessary HID class specific commands.
switch (setup->bRequest)
{
case USB_HID_SET_IDLE:
+// cprints("USB_HID_SET_IDLE\r\n");
if (((setup->wValue & 0xFF) == 0) // Report ID
&& (setup->wLength == 0)
&& (setup->bmRequestType.Direction != USB_SETUP_DIR_IN))
@@ -107,6 +115,7 @@ USB_Status_TypeDef USBD_SetupCmdCb(
break;
case USB_HID_GET_IDLE:
+// cprints("USB_HID_GET_IDLE\r\n");
if ((setup->wValue == 0) // Report ID
&& (setup->wLength == 1)
&& (setup->bmRequestType.Direction == USB_SETUP_DIR_IN))
@@ -120,6 +129,10 @@ USB_Status_TypeDef USBD_SetupCmdCb(
break;
}
}
+ else
+ {
+// cprints("nothing\r\n");
+ }
return retVal;
}
diff --git a/efm8/src/eeprom.c b/efm8/src/eeprom.c
new file mode 100644
index 0000000..80ff675
--- /dev/null
+++ b/efm8/src/eeprom.c
@@ -0,0 +1,79 @@
+#include
+#include
+
+#include "eeprom.h"
+#include "printing.h"
+
+char __erase_mem[3];
+
+static void erase_ram()
+{
+ data uint16_t i;
+ data uint8_t xdata * clear = 0;
+ for (i=0; i<0x400;i++)
+ {
+ *(clear++) = 0x0;
+ }
+}
+
+
+void eeprom_init()
+{
+ uint8_t secbyte;
+ eeprom_read(0xFBFF,&secbyte,1);
+ if (secbyte == 0xff)
+ {
+ eeprom_erase(0xFBC0);
+ secbyte = -32;
+ eeprom_write(0xFBFF, &secbyte, 1);
+ erase_ram();
+ // Reboot
+ cprints("rebooting\r\n");
+ RSTSRC = (1<<4);
+ }
+ else
+ {
+// cprints("no reboot\r\n");
+ }
+}
+
+void eeprom_read(uint16_t addr, uint8_t * buf, uint8_t len)
+{
+ uint8_t code * eepaddr = (uint8_t code *) addr;
+ bit old_int;
+
+ while(len--)
+ {
+ old_int = IE_EA;
+ IE_EA = 0;
+ *buf++ = *eepaddr++;
+ IE_EA = old_int;
+ }
+}
+
+void _eeprom_write(uint16_t addr, uint8_t * buf, uint8_t len, uint8_t flags)
+{
+ uint8_t xdata * data eepaddr = (uint8_t xdata *) addr;
+ bit old_int;
+
+ while(len--)
+ {
+ old_int = IE_EA;
+ IE_EA = 0;
+ // Enable VDD monitor
+ VDM0CN = 0x80;
+ RSTSRC = 0x02;
+
+ // unlock key
+ FLKEY = 0xA5;
+ FLKEY = 0xF1;
+ PSCTL |= flags;
+
+ *eepaddr = *buf;
+ PSCTL &= ~flags;
+ IE_EA = old_int;
+
+ eepaddr++;
+ buf++;
+ }
+}
diff --git a/efm8/src/main.c b/efm8/src/main.c
index c1d075a..575e0b3 100644
--- a/efm8/src/main.c
+++ b/efm8/src/main.c
@@ -4,13 +4,16 @@
#include "uart_1.h"
#include "printing.h"
-#define BUFFER_SIZE 10
+#define BUFFER_SIZE 13
-uint8_t write_ptr = 0;
-uint8_t read_ptr = 0;
-uint8_t count = 0;
+data uint8_t write_ptr = 0;
+data uint8_t read_ptr = 0;
+data uint8_t i_ptr = 0;
+data uint8_t count = 0;
+data uint8_t writebackbuf_count = 0;
uint8_t hidmsgbuf[64][BUFFER_SIZE];
+data uint8_t writebackbuf[64];
void usb_transfer_complete()
{
@@ -20,81 +23,129 @@ void usb_transfer_complete()
{
write_ptr = 0;
}
- cprints("read hid msg\r\n");
+ if (count == 1 && i_ptr == 0)
+ {
+ SPI0DAT = hidmsgbuf[read_ptr][i_ptr++];
+ }
+
+
+// MSG_RDY_INT_PIN = 0;
+// MSG_RDY_INT_PIN = 1;
+
}
void spi_transfer_complete()
{
count--;
+ i_ptr = 0;
+ SPI0FCN0 |= (1<<2); // Flush rx fifo buffer
+ if (count)
+ {
+ SPI0DAT = hidmsgbuf[read_ptr][i_ptr++];
+ }
read_ptr++;
+
if (read_ptr == BUFFER_SIZE)
{
read_ptr = 0;
}
- cprints("sent hid msg\r\n");
+
+// cprints("sent hid msg\r\n");
}
SI_INTERRUPT (SPI0_ISR, SPI0_IRQn)
{
-
- static unsigned char command;
- static unsigned char array_index = 0;
- static unsigned char state = 0;
- char arr[2];
-
if (SPI0CN0_WCOL == 1)
{
- // Write collision occurred
- SPI0CN0_WCOL = 0; // Clear the Write collision flag
+ // Write collision occurred
+ SPI0CN0_WCOL = 0;
+// cprints("SPI0CN0_WCOL\r\n");
}
else if(SPI0CN0_RXOVRN == 1)
{
- // Receive overrun occurred
- SPI0CN0_RXOVRN = 0; // Clear the Receive Overrun flag
+ // Receive overrun occurred
+ SPI0CN0_RXOVRN = 0;
+// cprints("SPI0CN0_RXOVRN\r\n");
}
else
{
- // SPI0CN0_SPIF caused the interrupt
+ if (EFM32_RW_PIN)
+ {
+ if (writebackbuf_count < 64) writebackbuf[writebackbuf_count++] = SPI0DAT;
+ else cprints("overflow\r\n");
+ }
+ else
+ {
+ if (count)
+ {
+ if (i_ptr < 64)
+ {
+ SPI0DAT = hidmsgbuf[read_ptr][i_ptr++];
- arr[0] = SPI0DAT; // Read the command
- arr[1] = 0;
-
- cprints("got data: ");
- cprints(arr);
- cprints("\n\r");
-
-
-
- SPI0CN0_SPIF = 0; // Clear the SPIF0 flag
+ }
+ else
+ {
+ spi_transfer_complete();
+ }
+ }
+ }
+ SPI0CN0_SPIF = 0;
}
}
+void usb_write()
+{
+ data uint8_t errors = 0;
+ while (USB_STATUS_OK != (USBD_Write(EP1IN, writebackbuf, 64, false)))
+ {
+ delay(2);
+ if (errors++ > 30)
+ {
+ cprints("ERROR USB WRITE\r\n");
+ break;
+ }
+ }
+}
+
int main(void) {
- volatile int xdata i,j,k;
+ uint8_t k;
+ uint16_t t1 = 0;
uint8_t lastcount = count;
+
+ int reset;
+ data int lastwritecount = writebackbuf_count;
+
enter_DefaultMode_from_RESET();
- IE_EA = 1;
+
+ eeprom_init();
+
SCON0_TI = 1;
P2_B0 = 1;
+
+ MSG_RDY_INT_PIN = 1;
+
+ // enable SPI interrupts
+ SPI0FCN1 = SPI0FCN1 | (1<<4);
+ IE_EA = 1;
+ IE_ESPI0 = 1;
+
cprints("hello,world\r\n");
-
+ reset = RSTSRC;
+ cprintx("reset source: ", 1, reset);
while (1) {
- k++;
- for (i = 0; i < 1000; i++)
+// delay(1500);
+ if (millis() - t1 > 1500)
{
- for (j = 0; j < 100; j++)
- {
-
- }
- P1_B4 = i&1;
+ P1_B5 = k++&1;
+ t1 = millis();
}
- P1_B5 = k&1;
if (!USBD_EpIsBusy(EP1OUT) && !USBD_EpIsBusy(EP1IN))
{
+// cprintd("sched read to ",1,reset);
if (count == BUFFER_SIZE)
{
cprints("Warning, USB buffer full\r\n");
@@ -104,9 +155,32 @@ int main(void) {
USBD_Read(EP1OUT, hidmsgbuf[write_ptr], 64, true);
}
}
- if (count != lastcount)
+
+ if (writebackbuf_count == 64)
{
- cprints("+1 to count \r\n");
+// cprints("<< ");
+// dump_hex(writebackbuf,64);
+ writebackbuf_count = 0;
+// while (USBD_EpIsBusy(EP1IN))
+// ;
+ usb_write();
+ }
+
+ if (lastcount != count)
+ {
+ if (count > lastcount)
+ {
+// cprints(">> ");
+// dump_hex(writebackbuf,64);
+
+ MSG_RDY_INT_PIN = 0;
+ MSG_RDY_INT_PIN = 1;
+ }
+ else
+ {
+// cprints("efm32 read hid msg\r\n>> ");
+// dump_hex(debug,64);
+ }
lastcount = count;
}
diff --git a/efm8/src/printing.c b/efm8/src/printing.c
index 48d4e61..d5edd85 100644
--- a/efm8/src/printing.c
+++ b/efm8/src/printing.c
@@ -11,6 +11,13 @@
#include
#include "printing.h"
+void delay(uint16_t ms)
+{
+ uint16_t m1 = millis();
+ while (millis() - m1 < ms)
+ ;
+}
+#ifdef USE_PRINTING
void putf(char c)
{
uint8_t i;
@@ -19,20 +26,23 @@ void putf(char c)
for (i=0; i<200; i++){}
for (i=0; i<200; i++){}
for (i=0; i<190; i++){}
-// watchdog();
}
+
+
void dump_hex(uint8_t* hex, uint8_t len)
{
uint8_t i;
+ uint8_t b;
+ const char lut[] = "0123456789abcdef";
for (i=0 ; i < len ; i++)
{
- if (hex[i]<0x10)
- {
- putf('0');
- }
- cputb(hex[i]);
+ b = ((*hex) & 0xf0)>>4;
+ putf(lut[b]);
+ b = ((*hex) & 0x0f);
+ putf(lut[b]);
+ hex++;
}
cprints("\r\n");
}
@@ -169,3 +179,4 @@ void cprintlx(const char * tag, uint8_t c, ...)
put_line();
va_end(args);
}
+#endif
diff --git a/fido2/main.c b/fido2/main.c
index 5c2c02f..074388f 100644
--- a/fido2/main.c
+++ b/fido2/main.c
@@ -23,12 +23,12 @@ int main(int argc, char * argv[])
set_logging_mask(
/*0*/
- /*TAG_GEN|*/
+ TAG_GEN|
/*TAG_MC |*/
/*TAG_GA |*/
/*TAG_CP |*/
TAG_CTAP|
- /*TAG_HID|*/
+ TAG_HID|
/*TAG_U2F|*/
/*TAG_PARSE |*/
/*TAG_TIME|*/
diff --git a/tools/ctap_test.py b/tools/ctap_test.py
index 0330470..467b8ed 100644
--- a/tools/ctap_test.py
+++ b/tools/ctap_test.py
@@ -547,13 +547,24 @@ class Tester():
print('PASS')
+def test_find_brute_force():
+ i = 0
+ while 1:
+ t1 = time.time() * 1000
+ t = Tester()
+ t.find_device()
+ t2 = time.time() * 1000
+ print('connected %d (%d ms)' % (i, t2-t1))
+ i += 1
+ time.sleep(0.01)
+
if __name__ == '__main__':
t = Tester()
t.find_device()
#t.test_hid()
#t.test_fido2()
- #t.test_fido2_simple()
+ t.test_fido2_simple()
#t.test_fido2_brute_force()