Removed scheduler and memory allocation libraries.
Added new EVENT_USB_StartOfFrame event in the library to indicate the start of each USB frame (when generated).
Removed Tx interrupt from the USBtoSerial demo; now sends characters via polling to ensure more time for the Rx interrupt.
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \\r
- $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \\r
\r
\r
# List C++ source files here. (C dependencies are automatically generated.)\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \\r
- $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \\r
\r
\r
# List C++ source files here. (C dependencies are automatically generated.)\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \\r
- $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \\r
\r
\r
# List C++ source files here. (C dependencies are automatically generated.)\r
this software.\r
*/\r
\r
-/** \file\r
- *\r
- * Main source file for the Audio Input demo. This file contains the main tasks of the demo and\r
- * is responsible for the initial application hardware configuration.\r
- */\r
-\r
#include "AudioInput.h"\r
\r
-/* Scheduler Task List */\r
-TASK_LIST\r
+USB_ClassInfo_Audio_t Microphone_Audio_Interface =\r
+ {\r
+ .InterfaceNumber = 0,\r
+\r
+ .DataINEndpointNumber = AUDIO_STREAM_EPNUM,\r
+ .DataINEndpointSize = AUDIO_STREAM_EPSIZE,\r
+ };\r
+ \r
+int main(void)\r
{\r
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },\r
- { .Task = USB_Audio_Task , .TaskStatus = TASK_STOP },\r
-};\r
+ SetupHardware();\r
\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
+ \r
+ for (;;)\r
+ {\r
+ if (Microphone_Audio_Interface.InterfaceEnabled)\r
+ ProcessNextSample();\r
\r
-/** Main program entry point. This routine configures the hardware required by the application, then\r
- * starts the scheduler to run the application tasks.\r
- */\r
-int main(void)\r
+ USB_USBTask();\r
+ }\r
+}\r
+\r
+void SetupHardware(void)\r
{\r
/* Disable watchdog if enabled by bootloader/fuses */\r
MCUSR &= ~(1 << WDRF);\r
\r
/* Hardware Initialization */\r
LEDs_Init();\r
+ USB_Init();\r
ADC_Init(ADC_FREE_RUNNING | ADC_PRESCALE_32);\r
ADC_SetupChannel(MIC_IN_ADC_CHANNEL);\r
\r
/* Start the ADC conversion in free running mode */\r
ADC_StartReading(ADC_REFERENCE_AVCC | ADC_RIGHT_ADJUSTED | MIC_IN_ADC_CHANNEL);\r
- \r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
- \r
- /* Initialize Scheduler so that it can be used */\r
- Scheduler_Init();\r
+}\r
\r
- /* Initialize USB Subsystem */\r
- USB_Init();\r
+void ProcessNextSample(void)\r
+{\r
+ if ((TIFR0 & (1 << OCF0A)) && USB_Audio_IsReadyForNextSample(&Microphone_Audio_Interface))\r
+ {\r
+ TIFR0 |= (1 << OCF0A);\r
+\r
+ /* Audio sample is ADC value scaled to fit the entire range */\r
+ int16_t AudioSample = ((SAMPLE_MAX_RANGE / ADC_MAX_RANGE) * ADC_GetResult());\r
+ \r
+#if defined(MICROPHONE_BIASED_TO_HALF_RAIL)\r
+ /* Microphone is biased to half rail voltage, subtract the bias from the sample value */\r
+ AudioSample -= (SAMPLE_MAX_RANGE / 2));\r
+#endif\r
\r
- /* Scheduling - routine never returns, so put this last in the main function */\r
- Scheduler_Start();\r
+ USB_Audio_WriteSample16(AudioSample);\r
+ }\r
}\r
\r
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs, and\r
- * configures the sample update and PWM timers.\r
- */\r
void EVENT_USB_Connect(void)\r
{\r
- /* Start USB management task */\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);\r
-\r
- /* Indicate USB enumerating */\r
- UpdateStatus(Status_USBEnumerating);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);\r
\r
/* Sample reload timer initialization */\r
OCR0A = (F_CPU / AUDIO_SAMPLE_FREQUENCY) - 1;\r
TCCR0B = (1 << CS00); // Fcpu speed\r
}\r
\r
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via\r
- * the status LEDs, disables the sample update and PWM output timers and stops the USB and Audio management tasks.\r
- */\r
void EVENT_USB_Disconnect(void)\r
{\r
/* Stop the sample reload timer */\r
TCCR0B = 0;\r
\r
- /* Stop running audio and USB management tasks */\r
- Scheduler_SetTaskMode(USB_Audio_Task, TASK_STOP);\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);\r
-\r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
}\r
\r
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration\r
- * of the USB device after enumeration - the device endpoints are configured.\r
- */\r
void EVENT_USB_ConfigurationChanged(void)\r
{\r
- /* Setup audio stream endpoint */\r
- Endpoint_ConfigureEndpoint(AUDIO_STREAM_EPNUM, EP_TYPE_ISOCHRONOUS,\r
- ENDPOINT_DIR_IN, AUDIO_STREAM_EPSIZE,\r
- ENDPOINT_BANK_DOUBLE);\r
-\r
- /* Indicate USB connected and ready */\r
- UpdateStatus(Status_USBReady);\r
-}\r
-\r
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific\r
- * control requests that are not handled internally by the USB library (including the Audio class-specific\r
- * requests) so that they can be handled appropriately for the application.\r
- */\r
-void EVENT_USB_UnhandledControlPacket(void)\r
-{\r
- /* Process General and Audio specific control requests */\r
- switch (USB_ControlRequest.bRequest)\r
- {\r
- case REQ_SetInterface:\r
- /* Set Interface is not handled by the library, as its function is application-specific */\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE))\r
- {\r
- Endpoint_ClearSETUP();\r
- \r
- /* Check if the host is enabling the audio interface (setting AlternateSetting to 1) */\r
- if (USB_ControlRequest.wValue)\r
- {\r
- /* Start audio task */\r
- Scheduler_SetTaskMode(USB_Audio_Task, TASK_RUN);\r
- }\r
- else\r
- {\r
- /* Stop audio task */\r
- Scheduler_SetTaskMode(USB_Audio_Task, TASK_STOP); \r
- }\r
- \r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
- }\r
-\r
- break;\r
- }\r
-}\r
-\r
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to\r
- * log to a serial port, or anything else that is suitable for status updates.\r
- *\r
- * \param CurrentStatus Current status of the system, from the AudioInput_StatusCodes_t enum\r
- */\r
-void UpdateStatus(uint8_t CurrentStatus)\r
-{\r
- uint8_t LEDMask = LEDS_NO_LEDS;\r
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
\r
- /* Set the LED mask to the appropriate LED mask based on the given status code */\r
- switch (CurrentStatus)\r
- {\r
- case Status_USBNotReady:\r
- LEDMask = (LEDS_LED1);\r
- break;\r
- case Status_USBEnumerating:\r
- LEDMask = (LEDS_LED1 | LEDS_LED2);\r
- break;\r
- case Status_USBReady:\r
- LEDMask = (LEDS_LED2 | LEDS_LED4);\r
- break;\r
- }\r
- \r
- /* Set the board LEDs to the new LED mask */\r
- LEDs_SetAllLEDs(LEDMask);\r
+ if (!(USB_Audio_ConfigureEndpoints(&Microphone_Audio_Interface)))\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
}\r
\r
-/** Task to manage the Audio interface, reading in ADC samples from the microphone, and them to the host. */\r
-TASK(USB_Audio_Task)\r
+void EVENT_USB_UnhandledControlPacket(void)\r
{\r
- /* Select the audio stream endpoint */\r
- Endpoint_SelectEndpoint(AUDIO_STREAM_EPNUM);\r
- \r
- /* Check if the current endpoint can be written to and that the next sample should be stored */\r
- if (Endpoint_IsINReady() && (TIFR0 & (1 << OCF0A)))\r
- {\r
- /* Clear the sample reload timer */\r
- TIFR0 |= (1 << OCF0A);\r
-\r
- /* Audio sample is ADC value scaled to fit the entire range */\r
- int16_t AudioSample = ((SAMPLE_MAX_RANGE / ADC_MAX_RANGE) * ADC_GetResult());\r
- \r
-#if defined(MICROPHONE_BIASED_TO_HALF_RAIL)\r
- /* Microphone is biased to half rail voltage, subtract the bias from the sample value */\r
- AudioSample -= (SAMPLE_MAX_RANGE / 2));\r
-#endif\r
-\r
- /* Write the sample to the buffer */\r
- Endpoint_Write_Word_LE(AudioSample);\r
-\r
- /* Check to see if the bank is now full */\r
- if (!(Endpoint_IsReadWriteAllowed()))\r
- {\r
- /* Send the full packet to the host */\r
- Endpoint_ClearIN();\r
- }\r
- }\r
+ USB_Audio_ProcessControlPacket(&Microphone_Audio_Interface);\r
}\r
\r
#include "Descriptors.h"\r
\r
- #include <LUFA/Version.h> // Library Version Information\r
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver\r
- #include <LUFA/Drivers/Peripheral/ADC.h> // ADC driver\r
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management\r
-\r
+ #include <LUFA/Version.h>\r
+ #include <LUFA/Drivers/Board/LEDs.h>\r
+ #include <LUFA/Drivers/Board/Joystick.h>\r
+ #include <LUFA/Drivers/Peripheral/ADC.h>\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/Audio.h>\r
+ \r
/* Macros: */\r
/** ADC channel number for the microphone input. */\r
#define MIC_IN_ADC_CHANNEL 2\r
/** Maximum ADC range for the microphone input. */\r
#define ADC_MAX_RANGE 0x3FF\r
\r
- /* Enums: */\r
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */\r
- enum AudioInput_StatusCodes_t\r
- {\r
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */\r
- Status_USBEnumerating = 1, /**< USB interface is enumerating */\r
- Status_USBReady = 2, /**< USB interface is connected and ready */\r
- };\r
-\r
- /* Task Definitions: */\r
- TASK(USB_Audio_Task);\r
-\r
+ /* Macros: */\r
+ #define LEDMASK_USB_NOTREADY LEDS_LED1\r
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)\r
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)\r
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)\r
+ \r
/* Function Prototypes: */\r
+ void SetupHardware(void);\r
+ void ProcessNextSample(void);\r
+ \r
void EVENT_USB_Connect(void);\r
void EVENT_USB_Disconnect(void);\r
void EVENT_USB_ConfigurationChanged(void);\r
void EVENT_USB_UnhandledControlPacket(void);\r
\r
- void UpdateStatus(uint8_t CurrentStatus);\r
- \r
#endif\r
# List C source files here. (C dependencies are automatically generated.)\r
SRC = $(TARGET).c \\r
Descriptors.c \\r
- $(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Endpoint.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Host.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \\r
- $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \\r
+ $(LUFA_PATH)/LUFA/Drivers/USB/Class/Device/Audio.c \\r
\r
\r
# List C++ source files here. (C dependencies are automatically generated.)\r
this software.\r
*/\r
\r
-/** \file\r
- *\r
- * Main source file for the Audio Output demo. This file contains the main tasks of the demo and\r
- * is responsible for the initial application hardware configuration.\r
- */\r
- \r
#include "AudioOutput.h"\r
\r
-/* Scheduler Task List */\r
-TASK_LIST\r
-{\r
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },\r
- { .Task = USB_Audio_Task , .TaskStatus = TASK_STOP },\r
-};\r
+USB_ClassInfo_Audio_t Speaker_Audio_Interface =\r
+ {\r
+ .InterfaceNumber = 0,\r
\r
+ .DataOUTEndpointNumber = AUDIO_STREAM_EPNUM,\r
+ .DataOUTEndpointSize = AUDIO_STREAM_EPSIZE,\r
+ };\r
\r
-/** Main program entry point. This routine configures the hardware required by the application, then\r
- * starts the scheduler to run the application tasks.\r
- */\r
int main(void)\r
{\r
+ SetupHardware();\r
+\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
+ \r
+ for (;;)\r
+ {\r
+ if (Speaker_Audio_Interface.InterfaceEnabled)\r
+ ProcessNextSample();\r
+\r
+ USB_USBTask();\r
+ }\r
+}\r
+\r
+void SetupHardware(void)\r
+{\r
/* Disable watchdog if enabled by bootloader/fuses */\r
MCUSR &= ~(1 << WDRF);\r
wdt_disable();\r
\r
/* Hardware Initialization */\r
LEDs_Init();\r
- \r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
- \r
- /* Initialize Scheduler so that it can be used */\r
- Scheduler_Init();\r
-\r
- /* Initialize USB Subsystem */\r
USB_Init();\r
-\r
- /* Scheduling - routine never returns, so put this last in the main function */\r
- Scheduler_Start();\r
-}\r
-\r
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs, and\r
- * configures the sample update and PWM timers.\r
- */\r
-void EVENT_USB_Connect(void)\r
-{\r
- /* Start USB management task */\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);\r
-\r
- /* Indicate USB enumerating */\r
- UpdateStatus(Status_USBEnumerating);\r
- \r
- /* Sample reload timer initialization */\r
- OCR0A = (F_CPU / AUDIO_SAMPLE_FREQUENCY) - 1;\r
- TCCR0A = (1 << WGM01); // CTC mode\r
- TCCR0B = (1 << CS00); // Fcpu speed\r
- \r
-#if defined(AUDIO_OUT_MONO)\r
- /* Set speaker as output */\r
- DDRC |= (1 << 6);\r
-#elif defined(AUDIO_OUT_STEREO)\r
- /* Set speakers as outputs */\r
- DDRC |= ((1 << 6) | (1 << 5));\r
-#elif defined(AUDIO_OUT_PORTC)\r
- /* Set PORTC as outputs */\r
- DDRC |= 0xFF;\r
-#endif\r
-\r
-#if (defined(AUDIO_OUT_MONO) || defined(AUDIO_OUT_STEREO))\r
- /* PWM speaker timer initialization */\r
- TCCRxA = ((1 << WGMx0) | (1 << COMxA1) | (1 << COMxA0)\r
- | (1 << COMxB1) | (1 << COMxB0)); // Set on match, clear on TOP\r
- TCCRxB = ((1 << WGMx2) | (1 << CSx0)); // Fast 8-Bit PWM, Fcpu speed\r
-#endif \r
}\r
\r
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via\r
- * the status LEDs, disables the sample update and PWM output timers and stops the USB and Audio management tasks.\r
- */\r
-void EVENT_USB_Disconnect(void)\r
-{\r
- /* Stop the timers */\r
- TCCR0B = 0;\r
-#if (defined(AUDIO_OUT_MONO) || defined(AUDIO_OUT_STEREO))\r
- TCCRxB = 0;\r
-#endif \r
-\r
-#if defined(AUDIO_OUT_MONO)\r
- /* Set speaker as input to reduce current draw */\r
- DDRC &= ~(1 << 6);\r
-#elif defined(AUDIO_OUT_STEREO)\r
- /* Set speakers as inputs to reduce current draw */\r
- DDRC &= ~((1 << 6) | (1 << 5));\r
-#elif defined(AUDIO_OUT_PORTC)\r
- /* Set PORTC low */\r
- PORTC = 0x00;\r
-#endif\r
-\r
- /* Stop running audio and USB management tasks */\r
- Scheduler_SetTaskMode(USB_Audio_Task, TASK_STOP);\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);\r
-\r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
-}\r
-\r
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration\r
- * of the USB device after enumeration - the device endpoints are configured.\r
- */\r
-void EVENT_USB_ConfigurationChanged(void)\r
-{\r
- /* Setup audio stream endpoint */\r
- Endpoint_ConfigureEndpoint(AUDIO_STREAM_EPNUM, EP_TYPE_ISOCHRONOUS,\r
- ENDPOINT_DIR_OUT, AUDIO_STREAM_EPSIZE,\r
- ENDPOINT_BANK_DOUBLE);\r
-\r
- /* Indicate USB connected and ready */\r
- UpdateStatus(Status_USBReady);\r
-}\r
-\r
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific\r
- * control requests that are not handled internally by the USB library (including the Audio class-specific\r
- * requests) so that they can be handled appropriately for the application.\r
- */\r
-void EVENT_USB_UnhandledControlPacket(void)\r
+void ProcessNextSample(void)\r
{\r
- /* Process General and Audio specific control requests */\r
- switch (USB_ControlRequest.bRequest)\r
- {\r
- case REQ_SetInterface:\r
- /* Set Interface is not handled by the library, as its function is application-specific */\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE))\r
- {\r
- Endpoint_ClearSETUP();\r
- \r
- /* Check if the host is enabling the audio interface (setting AlternateSetting to 1) */\r
- if (USB_ControlRequest.wValue)\r
- {\r
- /* Start audio task */\r
- Scheduler_SetTaskMode(USB_Audio_Task, TASK_RUN);\r
- }\r
- else\r
- {\r
- /* Stop audio task */\r
- Scheduler_SetTaskMode(USB_Audio_Task, TASK_STOP); \r
- }\r
- \r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
- }\r
-\r
- break;\r
- }\r
-}\r
-\r
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to\r
- * log to a serial port, or anything else that is suitable for status updates.\r
- *\r
- * \param CurrentStatus Current status of the system, from the AudioOutput_StatusCodes_t enum\r
- */\r
-void UpdateStatus(uint8_t CurrentStatus)\r
-{\r
- uint8_t LEDMask = LEDS_NO_LEDS;\r
- \r
- /* Set the LED mask to the appropriate LED mask based on the given status code */\r
- switch (CurrentStatus)\r
- {\r
- case Status_USBNotReady:\r
- LEDMask = (LEDS_LED1);\r
- break;\r
- case Status_USBEnumerating:\r
- LEDMask = (LEDS_LED1 | LEDS_LED2);\r
- break;\r
- case Status_USBReady:\r
- LEDMask = (LEDS_LED2 | LEDS_LED4);\r
- break;\r
- }\r
- \r
- /* Set the board LEDs to the new LED mask */\r
- LEDs_SetAllLEDs(LEDMask);\r
-}\r
-\r
-/** Task to manage the Audio interface, reading in audio samples from the host, and outputting them to the speakers/LEDs as\r
- * desired.\r
- */\r
-TASK(USB_Audio_Task)\r
-{\r
- /* Select the audio stream endpoint */\r
- Endpoint_SelectEndpoint(AUDIO_STREAM_EPNUM);\r
- \r
- /* Check if the current endpoint can be read from (contains a packet) and that the next sample should be read */\r
- if (Endpoint_IsOUTReceived() && (TIFR0 & (1 << OCF0A)))\r
+ if ((TIFR0 & (1 << OCF0A)) && USB_Audio_IsSampleReceived(&Speaker_Audio_Interface))\r
{\r
/* Clear the sample reload timer */\r
TIFR0 |= (1 << OCF0A);\r
\r
/* Retrieve the signed 16-bit left and right audio samples */\r
- int16_t LeftSample_16Bit = (int16_t)Endpoint_Read_Word_LE();\r
- int16_t RightSample_16Bit = (int16_t)Endpoint_Read_Word_LE();\r
-\r
- /* Check to see if the bank is now empty */\r
- if (!(Endpoint_IsReadWriteAllowed()))\r
- {\r
- /* Acknowledge the packet, clear the bank ready for the next packet */\r
- Endpoint_ClearOUT();\r
- }\r
+ int16_t LeftSample_16Bit = (int16_t)USB_Audio_ReadSample16();\r
+ int16_t RightSample_16Bit = (int16_t)USB_Audio_ReadSample16();\r
\r
/* Massage signed 16-bit left and right audio samples into signed 8-bit */\r
int8_t LeftSample_8Bit = (LeftSample_16Bit >> 8);\r
#endif\r
}\r
}\r
+\r
+void EVENT_USB_Connect(void)\r
+{\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);\r
+ \r
+ /* Sample reload timer initialization */\r
+ OCR0A = (F_CPU / AUDIO_SAMPLE_FREQUENCY) - 1;\r
+ TCCR0A = (1 << WGM01); // CTC mode\r
+ TCCR0B = (1 << CS00); // Fcpu speed\r
+\r
+#if defined(AUDIO_OUT_MONO)\r
+ /* Set speaker as output */\r
+ DDRC |= (1 << 6);\r
+#elif defined(AUDIO_OUT_STEREO)\r
+ /* Set speakers as outputs */\r
+ DDRC |= ((1 << 6) | (1 << 5));\r
+#elif defined(AUDIO_OUT_PORTC)\r
+ /* Set PORTC as outputs */\r
+ DDRC |= 0xFF;\r
+#endif\r
+\r
+#if (defined(AUDIO_OUT_MONO) || defined(AUDIO_OUT_STEREO))\r
+ /* PWM speaker timer initialization */\r
+ TCCRxA = ((1 << WGMx0) | (1 << COMxA1) | (1 << COMxA0)\r
+ | (1 << COMxB1) | (1 << COMxB0)); // Set on match, clear on TOP\r
+ TCCRxB = ((1 << WGMx2) | (1 << CSx0)); // Fast 8-Bit PWM, Fcpu speed\r
+#endif \r
+}\r
+\r
+/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via\r
+ * the status LEDs, disables the sample update and PWM output timers and stops the USB and Audio management tasks.\r
+ */\r
+void EVENT_USB_Disconnect(void)\r
+{\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
+\r
+ /* Stop the timers */\r
+ TCCR0B = 0;\r
+#if (defined(AUDIO_OUT_MONO) || defined(AUDIO_OUT_STEREO))\r
+ TCCRxB = 0;\r
+#endif \r
+\r
+#if defined(AUDIO_OUT_MONO)\r
+ /* Set speaker as input to reduce current draw */\r
+ DDRC &= ~(1 << 6);\r
+#elif defined(AUDIO_OUT_STEREO)\r
+ /* Set speakers as inputs to reduce current draw */\r
+ DDRC &= ~((1 << 6) | (1 << 5));\r
+#elif defined(AUDIO_OUT_PORTC)\r
+ /* Set PORTC low */\r
+ PORTC = 0x00;\r
+#endif\r
+}\r
+\r
+void EVENT_USB_ConfigurationChanged(void)\r
+{\r
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
+ \r
+ if (!(USB_Audio_ConfigureEndpoints(&Speaker_Audio_Interface)))\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
+}\r
+\r
+void EVENT_USB_UnhandledControlPacket(void)\r
+{\r
+ USB_Audio_ProcessControlPacket(&Speaker_Audio_Interface);\r
+}\r
\r
#include "Descriptors.h"\r
\r
- #include <LUFA/Version.h> // Library Version Information\r
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver\r
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management\r
+ #include <LUFA/Version.h>\r
+ #include <LUFA/Drivers/Board/LEDs.h>\r
+ #include <LUFA/Drivers/Board/Joystick.h>\r
+ #include <LUFA/Drivers/Peripheral/ADC.h>\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/Audio.h>\r
\r
/* Macros: */\r
#if defined(USB_FULL_CONTROLLER) || defined(USB_MODIFIED_FULL_CONTROLLER)\r
#define CSx0 CS10\r
#endif\r
\r
- /* Enums: */\r
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */\r
- enum AudioOutput_StatusCodes_t\r
- {\r
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */\r
- Status_USBEnumerating = 1, /**< USB interface is enumerating */\r
- Status_USBReady = 2, /**< USB interface is connected and ready */\r
- };\r
-\r
- /* Task Definitions: */\r
- TASK(USB_Audio_Task);\r
- \r
+ /* Macros: */\r
+ #define LEDMASK_USB_NOTREADY LEDS_LED1\r
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)\r
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)\r
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)\r
+ \r
/* Function Prototypes: */\r
+ void SetupHardware(void);\r
+ void ProcessNextSample(void);\r
+ \r
void EVENT_USB_Connect(void);\r
void EVENT_USB_Disconnect(void);\r
void EVENT_USB_ConfigurationChanged(void);\r
void EVENT_USB_UnhandledControlPacket(void);\r
- \r
- void UpdateStatus(uint8_t CurrentStatus);\r
\r
#endif\r
# List C source files here. (C dependencies are automatically generated.)\r
SRC = $(TARGET).c \\r
Descriptors.c \\r
- $(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Endpoint.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Host.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \\r
- $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \\r
+ $(LUFA_PATH)/LUFA/Drivers/USB/Class/Device/Audio.c \\r
\r
\r
# List C++ source files here. (C dependencies are automatically generated.)\r
CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY\r
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION\r
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"\r
-CDEFS += -DAUDIO_OUT_STEREO\r
+CDEFS += -DAUDIO_OUT_MONO\r
\r
# Place -D or -U options here for ASM sources\r
ADEFS = -DF_CPU=$(F_CPU)\r
this software.\r
*/\r
\r
-/** \file\r
- *\r
- * Main source file for the CDC demo. This file contains the main tasks of the demo and\r
- * is responsible for the initial application hardware configuration.\r
- */\r
-\r
#include "CDC.h"\r
\r
-/* Scheduler Task List */\r
-TASK_LIST\r
-{\r
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },\r
- { .Task = CDC_Task , .TaskStatus = TASK_STOP },\r
-};\r
+USB_ClassInfo_CDC_t VirtualSerial_CDC_Interface =\r
+ {\r
+ .ControlInterfaceNumber = 0,\r
\r
-/* Globals: */\r
-/** Contains the current baud rate and other settings of the virtual serial port. While this demo does not use\r
- * the physical USART and thus does not use these settings, they must still be retained and returned to the host\r
- * upon request or the host will assume the device is non-functional.\r
- *\r
- * These values are set by the host via a class-specific request, however they are not required to be used accurately.\r
- * It is possible to completely ignore these value or use other settings as the host is completely unaware of the physical\r
- * serial link characteristics and instead sends and receives data in endpoint streams.\r
- */\r
-CDC_Line_Coding_t LineCoding = { .BaudRateBPS = 9600,\r
- .CharFormat = OneStopBit,\r
- .ParityType = Parity_None,\r
- .DataBits = 8 };\r
+ .DataINEndpointNumber = CDC_TX_EPNUM,\r
+ .DataINEndpointSize = CDC_TXRX_EPSIZE,\r
\r
-/** String to print through the virtual serial port when the joystick is pressed upwards. */\r
-char JoystickUpString[] = "Joystick Up\r\n";\r
+ .DataOUTEndpointNumber = CDC_RX_EPNUM,\r
+ .DataOUTEndpointSize = CDC_TXRX_EPSIZE,\r
\r
-/** String to print through the virtual serial port when the joystick is pressed downward. */\r
-char JoystickDownString[] = "Joystick Down\r\n";\r
+ .NotificationEndpointNumber = CDC_NOTIFICATION_EPNUM,\r
+ .NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE,\r
+ };\r
\r
-/** String to print through the virtual serial port when the joystick is pressed left. */\r
-char JoystickLeftString[] = "Joystick Left\r\n";\r
+int main(void)\r
+{\r
+ SetupHardware();\r
+ \r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
\r
-/** String to print through the virtual serial port when the joystick is pressed right. */\r
-char JoystickRightString[] = "Joystick Right\r\n";\r
+ for (;;)\r
+ {\r
+ CheckJoystickMovement();\r
+ \r
+ uint16_t BytesToDiscard = USB_CDC_BytesReceived(&VirtualSerial_CDC_Interface);\r
+ while (BytesToDiscard--)\r
+ USB_CDC_ReceiveByte(&VirtualSerial_CDC_Interface);\r
\r
-/** String to print through the virtual serial port when the joystick is pressed inwards. */\r
-char JoystickPressedString[] = "Joystick Pressed\r\n";\r
+ USB_CDC_USBTask(&VirtualSerial_CDC_Interface);\r
+ USB_USBTask();\r
+ }\r
+}\r
\r
-/** Main program entry point. This routine configures the hardware required by the application, then\r
- * starts the scheduler to run the application tasks.\r
- */\r
-int main(void)\r
+void SetupHardware(void)\r
{\r
/* Disable watchdog if enabled by bootloader/fuses */\r
MCUSR &= ~(1 << WDRF);\r
/* Hardware Initialization */\r
Joystick_Init();\r
LEDs_Init();\r
- \r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
- \r
- /* Initialize Scheduler so that it can be used */\r
- Scheduler_Init();\r
-\r
- /* Initialize USB Subsystem */\r
USB_Init();\r
-\r
- /* Scheduling - routine never returns, so put this last in the main function */\r
- Scheduler_Start();\r
-}\r
-\r
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and\r
- * starts the library USB task to begin the enumeration and USB management process.\r
- */\r
-void EVENT_USB_Connect(void)\r
-{\r
- /* Start USB management task */\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);\r
-\r
- /* Indicate USB enumerating */\r
- UpdateStatus(Status_USBEnumerating);\r
-}\r
-\r
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via\r
- * the status LEDs and stops the USB management and CDC management tasks.\r
- */\r
-void EVENT_USB_Disconnect(void)\r
-{\r
- /* Stop running CDC and USB management tasks */\r
- Scheduler_SetTaskMode(CDC_Task, TASK_STOP);\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);\r
-\r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
-}\r
-\r
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration\r
- * of the USB device after enumeration - the device endpoints are configured and the CDC management task started.\r
- */\r
-void EVENT_USB_ConfigurationChanged(void)\r
-{\r
- /* Setup CDC Notification, Rx and Tx Endpoints */\r
- Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,\r
- ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK,\r
- ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK,\r
- ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- /* Indicate USB connected and ready */\r
- UpdateStatus(Status_USBReady);\r
- \r
- /* Start CDC task */\r
- Scheduler_SetTaskMode(CDC_Task, TASK_RUN);\r
-}\r
-\r
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific\r
- * control requests that are not handled internally by the USB library (including the CDC control commands,\r
- * which are all issued via the control endpoint), so that they can be handled appropriately for the application.\r
- */\r
-void EVENT_USB_UnhandledControlPacket(void)\r
-{\r
- uint8_t* LineCodingData = (uint8_t*)&LineCoding;\r
-\r
- /* Process CDC specific control requests */\r
- switch (USB_ControlRequest.bRequest)\r
- {\r
- case REQ_GetLineEncoding:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
- { \r
- /* Acknowledge the SETUP packet, ready for data transfer */\r
- Endpoint_ClearSETUP();\r
-\r
- /* Write the line coding data to the control endpoint */\r
- Endpoint_Write_Control_Stream_LE(LineCodingData, sizeof(CDC_Line_Coding_t));\r
- \r
- /* Finalize the stream transfer to send the last packet or clear the host abort */\r
- Endpoint_ClearOUT();\r
- }\r
- \r
- break;\r
- case REQ_SetLineEncoding:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- /* Acknowledge the SETUP packet, ready for data transfer */\r
- Endpoint_ClearSETUP();\r
-\r
- /* Read the line coding data in from the host into the global struct */\r
- Endpoint_Read_Control_Stream_LE(LineCodingData, sizeof(CDC_Line_Coding_t));\r
-\r
- /* Finalize the stream transfer to clear the last packet from the host */\r
- Endpoint_ClearIN();\r
- }\r
- \r
- break;\r
- case REQ_SetControlLineState:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- /* Acknowledge the SETUP packet, ready for data transfer */\r
- Endpoint_ClearSETUP();\r
- \r
- /* NOTE: Here you can read in the line state mask from the host, to get the current state of the output handshake\r
- lines. The mask is read in from the wValue parameter in USB_ControlRequest, and can be masked against the\r
- CONTROL_LINE_OUT_* masks to determine the RTS and DTR line states using the following code:\r
- */\r
- \r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
- }\r
- \r
- break;\r
- }\r
}\r
\r
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to\r
- * log to a serial port, or anything else that is suitable for status updates.\r
- *\r
- * \param CurrentStatus Current status of the system, from the CDC_StatusCodes_t enum\r
- */\r
-void UpdateStatus(uint8_t CurrentStatus)\r
+void CheckJoystickMovement(void)\r
{\r
- uint8_t LEDMask = LEDS_NO_LEDS;\r
- \r
- /* Set the LED mask to the appropriate LED mask based on the given status code */\r
- switch (CurrentStatus)\r
- {\r
- case Status_USBNotReady:\r
- LEDMask = (LEDS_LED1);\r
- break;\r
- case Status_USBEnumerating:\r
- LEDMask = (LEDS_LED1 | LEDS_LED2);\r
- break;\r
- case Status_USBReady:\r
- LEDMask = (LEDS_LED2 | LEDS_LED4);\r
- break;\r
- }\r
+ uint8_t JoyStatus_LCL = Joystick_GetStatus();\r
+ char* ReportString = NULL;\r
+ static bool ActionSent = false;\r
\r
- /* Set the board LEDs to the new LED mask */\r
- LEDs_SetAllLEDs(LEDMask);\r
-}\r
-\r
-/** Function to manage CDC data transmission and reception to and from the host. */\r
-TASK(CDC_Task)\r
-{\r
- char* ReportString = NULL;\r
- uint8_t JoyStatus_LCL = Joystick_GetStatus();\r
- static bool ActionSent = false;\r
- \r
-#if 0\r
- /* NOTE: Here you can use the notification endpoint to send back line state changes to the host, for the special RS-232\r
- handshake signal lines (and some error states), via the CONTROL_LINE_IN_* masks and the following code:\r
- */\r
- USB_Notification_Header_t Notification = (USB_Notification_Header_t)\r
+ char* JoystickStrings[] =\r
{\r
- .NotificationType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),\r
- .Notification = NOTIF_SerialState,\r
- .wValue = 0,\r
- .wIndex = 0,\r
- .wLength = sizeof(uint16_t),\r
+ "Joystick Up\r\n",\r
+ "Joystick Down\r\n",\r
+ "Joystick Left\r\n",\r
+ "Joystick Right\r\n",\r
+ "Joystick Pressed\r\n",\r
};\r
- \r
- uint16_t LineStateMask;\r
- \r
- // Set LineStateMask here to a mask of CONTROL_LINE_IN_* masks to set the input handshake line states to send to the host\r
- \r
- Endpoint_SelectEndpoint(CDC_NOTIFICATION_EPNUM);\r
- Endpoint_Write_Stream_LE(&Notification, sizeof(Notification));\r
- Endpoint_Write_Stream_LE(&LineStateMask, sizeof(LineStateMask));\r
- Endpoint_ClearIN();\r
-#endif\r
\r
- /* Determine if a joystick action has occurred */\r
if (JoyStatus_LCL & JOY_UP)\r
- ReportString = JoystickUpString;\r
+ ReportString = JoystickStrings[0];\r
else if (JoyStatus_LCL & JOY_DOWN)\r
- ReportString = JoystickDownString;\r
+ ReportString = JoystickStrings[1];\r
else if (JoyStatus_LCL & JOY_LEFT)\r
- ReportString = JoystickLeftString;\r
+ ReportString = JoystickStrings[2];\r
else if (JoyStatus_LCL & JOY_RIGHT)\r
- ReportString = JoystickRightString;\r
+ ReportString = JoystickStrings[3];\r
else if (JoyStatus_LCL & JOY_PRESS)\r
- ReportString = JoystickPressedString;\r
-\r
- /* Flag management - Only allow one string to be sent per action */\r
- if (ReportString == NULL)\r
- {\r
- ActionSent = false;\r
- }\r
- else if (ActionSent == false)\r
+ ReportString = JoystickStrings[4];\r
+ else\r
+ ActionSent = false;\r
+ \r
+ if ((ReportString != NULL) && (ActionSent == false))\r
{\r
ActionSent = true;\r
+ \r
+ USB_CDC_SendString(&VirtualSerial_CDC_Interface, ReportString, strlen(ReportString)); \r
+ }\r
+}\r
\r
- /* Select the Serial Tx Endpoint */\r
- Endpoint_SelectEndpoint(CDC_TX_EPNUM);\r
+void EVENT_USB_Connect(void)\r
+{\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);\r
+}\r
\r
- /* Write the String to the Endpoint */\r
- Endpoint_Write_Stream_LE(ReportString, strlen(ReportString));\r
- \r
- /* Remember if the packet to send completely fills the endpoint */\r
- bool IsFull = (Endpoint_BytesInEndpoint() == CDC_TXRX_EPSIZE);\r
+void EVENT_USB_Disconnect(void)\r
+{\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
+}\r
\r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearIN();\r
+void EVENT_USB_ConfigurationChanged(void)\r
+{\r
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
\r
- /* If the last packet filled the endpoint, send an empty packet to release the buffer on \r
- * the receiver (otherwise all data will be cached until a non-full packet is received) */\r
- if (IsFull)\r
- {\r
- /* Wait until the endpoint is ready for another packet */\r
- while (!(Endpoint_IsINReady()));\r
- \r
- /* Send an empty packet to ensure that the host does not buffer data sent to it */\r
- Endpoint_ClearIN();\r
- }\r
- }\r
+ if (!(USB_CDC_ConfigureEndpoints(&VirtualSerial_CDC_Interface)))\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
+}\r
\r
- /* Select the Serial Rx Endpoint */\r
- Endpoint_SelectEndpoint(CDC_RX_EPNUM);\r
- \r
- /* Throw away any received data from the host */\r
- if (Endpoint_IsOUTReceived())\r
- Endpoint_ClearOUT();\r
+void EVENT_USB_UnhandledControlPacket(void)\r
+{\r
+ USB_CDC_ProcessControlPacket(&VirtualSerial_CDC_Interface);\r
}\r
\r
#include "Descriptors.h"\r
\r
- #include <LUFA/Version.h> // Library Version Information\r
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
- #include <LUFA/Drivers/Board/Joystick.h> // Joystick driver\r
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver\r
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management\r
+ #include <LUFA/Version.h>\r
+ #include <LUFA/Drivers/Board/LEDs.h>\r
+ #include <LUFA/Drivers/Board/Joystick.h>\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/CDC.h>\r
\r
/* Macros: */\r
- /** CDC Class specific request to get the current virtual serial port configuration settings. */\r
- #define REQ_GetLineEncoding 0x21\r
-\r
- /** CDC Class specific request to set the current virtual serial port configuration settings. */\r
- #define REQ_SetLineEncoding 0x20\r
-\r
- /** CDC Class specific request to set the current virtual serial port handshake line states. */\r
- #define REQ_SetControlLineState 0x22\r
- \r
- /** Notification type constant for a change in the virtual serial port handshake line states, for\r
- * use with a USB_Notification_Header_t notification structure when sent to the host via the CDC \r
- * notification endpoint.\r
- */\r
- #define NOTIF_SerialState 0x20\r
-\r
- /** Mask for the DTR handshake line for use with the REQ_SetControlLineState class specific request\r
- * from the host, to indicate that the DTR line state should be high.\r
- */\r
- #define CONTROL_LINE_OUT_DTR (1 << 0)\r
-\r
- /** Mask for the RTS handshake line for use with the REQ_SetControlLineState class specific request\r
- * from the host, to indicate that theRTS line state should be high.\r
- */\r
- #define CONTROL_LINE_OUT_RTS (1 << 1)\r
- \r
- /** Mask for the DCD handshake line for use with the a NOTIF_SerialState class specific notification\r
- * from the device to the host, to indicate that the DCD line state is currently high.\r
- */\r
- #define CONTROL_LINE_IN_DCD (1 << 0)\r
-\r
- /** Mask for the DSR handshake line for use with the a NOTIF_SerialState class specific notification\r
- * from the device to the host, to indicate that the DSR line state is currently high.\r
- */\r
- #define CONTROL_LINE_IN_DSR (1 << 1)\r
-\r
- /** Mask for the BREAK handshake line for use with the a NOTIF_SerialState class specific notification\r
- * from the device to the host, to indicate that the BREAK line state is currently high.\r
- */\r
- #define CONTROL_LINE_IN_BREAK (1 << 2)\r
-\r
- /** Mask for the RING handshake line for use with the a NOTIF_SerialState class specific notification\r
- * from the device to the host, to indicate that the RING line state is currently high.\r
- */\r
- #define CONTROL_LINE_IN_RING (1 << 3)\r
-\r
- /** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,\r
- * to indicate that a framing error has occurred on the virtual serial port.\r
- */\r
- #define CONTROL_LINE_IN_FRAMEERROR (1 << 4)\r
-\r
- /** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,\r
- * to indicate that a parity error has occurred on the virtual serial port.\r
- */\r
- #define CONTROL_LINE_IN_PARITYERROR (1 << 5)\r
-\r
- /** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,\r
- * to indicate that a data overrun error has occurred on the virtual serial port.\r
- */\r
- #define CONTROL_LINE_IN_OVERRUNERROR (1 << 6)\r
- \r
- /* Type Defines: */\r
- /** Type define for the virtual serial port line encoding settings, for storing the current USART configuration\r
- * as set by the host via a class specific request.\r
- */\r
- typedef struct\r
- {\r
- uint32_t BaudRateBPS; /**< Baud rate of the virtual serial port, in bits per second */\r
- uint8_t CharFormat; /**< Character format of the virtual serial port, a value from the\r
- * CDCDevice_CDC_LineCodingFormats_t enum\r
- */\r
- uint8_t ParityType; /**< Parity setting of the virtual serial port, a value from the\r
- * CDCDevice_LineCodingParity_t enum\r
- */\r
- uint8_t DataBits; /**< Bits of data per character of the virtual serial port */\r
- } CDC_Line_Coding_t;\r
- \r
- /** Type define for a CDC notification, sent to the host via the CDC notification endpoint to indicate a\r
- * change in the device state asynchronously.\r
- */\r
- typedef struct\r
- {\r
- uint8_t NotificationType; /**< Notification type, a mask of REQDIR_*, REQTYPE_* and REQREC_* constants\r
- * from the library StdRequestType.h header\r
- */\r
- uint8_t Notification; /**< Notification value, a NOTIF_* constant */\r
- uint16_t wValue; /**< Notification wValue, notification-specific */\r
- uint16_t wIndex; /**< Notification wIndex, notification-specific */\r
- uint16_t wLength; /**< Notification wLength, notification-specific */\r
- } USB_Notification_Header_t;\r
- \r
- /* Enums: */\r
- /** Enum for the possible line encoding formats of a virtual serial port. */\r
- enum CDCDevice_CDC_LineCodingFormats_t\r
- {\r
- OneStopBit = 0, /**< Each frame contains one stop bit */\r
- OneAndAHalfStopBits = 1, /**< Each frame contains one and a half stop bits */\r
- TwoStopBits = 2, /**< Each frame contains two stop bits */\r
- };\r
+ #define LEDMASK_USB_NOTREADY LEDS_LED1\r
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)\r
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)\r
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)\r
\r
- /** Enum for the possible line encoding parity settings of a virtual serial port. */\r
- enum CDCDevice_LineCodingParity_t\r
- {\r
- Parity_None = 0, /**< No parity bit mode on each frame */\r
- Parity_Odd = 1, /**< Odd parity bit mode on each frame */\r
- Parity_Even = 2, /**< Even parity bit mode on each frame */\r
- Parity_Mark = 3, /**< Mark parity bit mode on each frame */\r
- Parity_Space = 4, /**< Space parity bit mode on each frame */\r
- };\r
-\r
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */\r
- enum CDC_StatusCodes_t\r
- {\r
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */\r
- Status_USBEnumerating = 1, /**< USB interface is enumerating */\r
- Status_USBReady = 2, /**< USB interface is connected and ready */\r
- };\r
- \r
- /* Tasks: */\r
- TASK(CDC_Task);\r
-\r
/* Function Prototypes: */\r
+ void SetupHardware(void);\r
+ void CheckJoystickMovement(void);\r
+\r
void EVENT_USB_Connect(void);\r
void EVENT_USB_Disconnect(void);\r
void EVENT_USB_ConfigurationChanged(void);\r
void EVENT_USB_UnhandledControlPacket(void);\r
-\r
- void UpdateStatus(uint8_t CurrentStatus);\r
+ void EVENT_USB_StartOfFrame(void);\r
\r
#endif\r
#define _DESCRIPTORS_H_\r
\r
/* Includes: */\r
- #include <LUFA/Drivers/USB/USB.h>\r
-\r
#include <avr/pgmspace.h>\r
\r
- /* Macros: */\r
- /** Macro to define a CDC class-specific functional descriptor. CDC functional descriptors have a\r
- * uniform structure but variable sized data payloads, thus cannot be represented accurately by\r
- * a single typedef struct. A macro is used instead so that functional descriptors can be created\r
- * easily by specifying the size of the payload. This allows sizeof() to work correctly.\r
- *\r
- * \param DataSize Size in bytes of the CDC functional descriptor's data payload\r
- */\r
- #define CDC_FUNCTIONAL_DESCRIPTOR(DataSize) \\r
- struct \\r
- { \\r
- USB_Descriptor_Header_t Header; \\r
- uint8_t SubType; \\r
- uint8_t Data[DataSize]; \\r
- }\r
- \r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/CDC.h>\r
+\r
+ /* Macros: */ \r
/** Endpoint number of the CDC device-to-host notification IN endpoint. */\r
#define CDC_NOTIFICATION_EPNUM 2\r
\r
# List C source files here. (C dependencies are automatically generated.)\r
SRC = $(TARGET).c \\r
Descriptors.c \\r
- $(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Endpoint.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Host.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \\r
- $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \\r
+ $(LUFA_PATH)/LUFA/Drivers/USB/Class/Device/CDC.c \\r
\r
\r
# List C++ source files here. (C dependencies are automatically generated.)\r
\r
# Place -D or -U options here for C sources\r
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)\r
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY\r
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY\r
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION\r
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"\r
\r
#define _DESCRIPTORS_H_\r
\r
/* Includes: */\r
- #include <LUFA/Drivers/USB/USB.h>\r
-\r
#include <avr/pgmspace.h>\r
\r
- /* Macros: */\r
- /** Macro to define a CDC class-specific functional descriptor. CDC functional descriptors have a\r
- * uniform structure but variable sized data payloads, thus cannot be represented accurately by\r
- * a single typedef struct. A macro is used instead so that functional descriptors can be created\r
- * easily by specifying the size of the payload. This allows sizeof() to work correctly.\r
- *\r
- * \param DataSize Size in bytes of the CDC functional descriptor's data payload\r
- */\r
- #define CDC_FUNCTIONAL_DESCRIPTOR(DataSize) \\r
- struct \\r
- { \\r
- USB_Descriptor_Header_t Header; \\r
- uint8_t SubType; \\r
- uint8_t Data[DataSize]; \\r
- }\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/CDC.h>\r
\r
+ /* Macros: */\r
/** Endpoint number of the first CDC interface's device-to-host notification IN endpoint. */\r
#define CDC1_NOTIFICATION_EPNUM 3\r
\r
arising out of or in connection with the use or performance of\r
this software.\r
*/\r
-\r
-/** \file\r
- *\r
- * Main source file for the DualCDC demo. This file contains the main tasks of the demo and\r
- * is responsible for the initial application hardware configuration.\r
- */\r
\r
#include "DualCDC.h"\r
\r
-/* Scheduler Task List */\r
-TASK_LIST\r
-{\r
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },\r
- { .Task = CDC1_Task , .TaskStatus = TASK_STOP },\r
- { .Task = CDC2_Task , .TaskStatus = TASK_STOP },\r
-};\r
+USB_ClassInfo_CDC_t VirtualSerial1_CDC_Interface =\r
+ {\r
+ .ControlInterfaceNumber = 0,\r
\r
-/* Globals: */\r
-/** Contains the current baud rate and other settings of the first virtual serial port. While this demo does not use\r
- * the physical USART and thus does not use these settings, they must still be retained and returned to the host\r
- * upon request or the host will assume the device is non-functional.\r
- *\r
- * These values are set by the host via a class-specific request, however they are not required to be used accurately.\r
- * It is possible to completely ignore these value or use other settings as the host is completely unaware of the physical\r
- * serial link characteristics and instead sends and receives data in endpoint streams.\r
- */\r
-CDC_Line_Coding_t LineCoding1 = { .BaudRateBPS = 9600,\r
- .CharFormat = OneStopBit,\r
- .ParityType = Parity_None,\r
- .DataBits = 8 };\r
+ .DataINEndpointNumber = CDC1_TX_EPNUM,\r
+ .DataINEndpointSize = CDC_TXRX_EPSIZE,\r
\r
-/** Contains the current baud rate and other settings of the second virtual serial port. While this demo does not use\r
- * the physical USART and thus does not use these settings, they must still be retained and returned to the host\r
- * upon request or the host will assume the device is non-functional.\r
- *\r
- * These values are set by the host via a class-specific request, however they are not required to be used accurately.\r
- * It is possible to completely ignore these value or use other settings as the host is completely unaware of the physical\r
- * serial link characteristics and instead sends and receives data in endpoint streams.\r
- */\r
-CDC_Line_Coding_t LineCoding2 = { .BaudRateBPS = 9600,\r
- .CharFormat = OneStopBit,\r
- .ParityType = Parity_None,\r
- .DataBits = 8 };\r
- \r
-/** String to print through the first virtual serial port when the joystick is pressed upwards. */\r
-char JoystickUpString[] = "Joystick Up\r\n";\r
+ .DataOUTEndpointNumber = CDC1_RX_EPNUM,\r
+ .DataOUTEndpointSize = CDC_TXRX_EPSIZE,\r
\r
-/** String to print through the first virtual serial port when the joystick is pressed downward. */\r
-char JoystickDownString[] = "Joystick Down\r\n";\r
+ .NotificationEndpointNumber = CDC1_NOTIFICATION_EPNUM,\r
+ .NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE,\r
+ };\r
+\r
+USB_ClassInfo_CDC_t VirtualSerial2_CDC_Interface =\r
+ {\r
+ .ControlInterfaceNumber = 0,\r
\r
-/** String to print through the first virtual serial port when the joystick is pressed left. */\r
-char JoystickLeftString[] = "Joystick Left\r\n";\r
+ .DataINEndpointNumber = CDC2_TX_EPNUM,\r
+ .DataINEndpointSize = CDC_TXRX_EPSIZE,\r
\r
-/** String to print through the first virtual serial port when the joystick is pressed right. */\r
-char JoystickRightString[] = "Joystick Right\r\n";\r
+ .DataOUTEndpointNumber = CDC2_RX_EPNUM,\r
+ .DataOUTEndpointSize = CDC_TXRX_EPSIZE,\r
\r
-/** String to print through the first virtual serial port when the joystick is pressed inwards. */\r
-char JoystickPressedString[] = "Joystick Pressed\r\n";\r
+ .NotificationEndpointNumber = CDC2_NOTIFICATION_EPNUM,\r
+ .NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE,\r
+ };\r
\r
-/** Main program entry point. This routine configures the hardware required by the application, then\r
- * starts the scheduler to run the application tasks.\r
- */\r
int main(void)\r
{\r
+ SetupHardware();\r
+ \r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
+\r
+ for (;;)\r
+ {\r
+ CheckJoystickMovement();\r
+\r
+ uint16_t BytesToDiscard = USB_CDC_BytesReceived(&VirtualSerial1_CDC_Interface);\r
+ while (BytesToDiscard--)\r
+ USB_CDC_ReceiveByte(&VirtualSerial1_CDC_Interface);\r
+\r
+ uint16_t BytesToEcho = USB_CDC_BytesReceived(&VirtualSerial2_CDC_Interface);\r
+ while (BytesToEcho--)\r
+ USB_CDC_SendByte(&VirtualSerial2_CDC_Interface, USB_CDC_ReceiveByte(&VirtualSerial2_CDC_Interface));\r
+ \r
+ USB_CDC_USBTask(&VirtualSerial1_CDC_Interface);\r
+ USB_CDC_USBTask(&VirtualSerial2_CDC_Interface);\r
+ USB_USBTask();\r
+ }\r
+}\r
+\r
+void SetupHardware(void)\r
+{\r
/* Disable watchdog if enabled by bootloader/fuses */\r
MCUSR &= ~(1 << WDRF);\r
wdt_disable();\r
/* Hardware Initialization */\r
Joystick_Init();\r
LEDs_Init();\r
- \r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
- \r
- /* Initialize Scheduler so that it can be used */\r
- Scheduler_Init();\r
-\r
- /* Initialize USB Subsystem */\r
USB_Init();\r
-\r
- /* Scheduling - routine never returns, so put this last in the main function */\r
- Scheduler_Start();\r
-}\r
-\r
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and\r
- * starts the library USB task to begin the enumeration and USB management process.\r
- */\r
-void EVENT_USB_Connect(void)\r
-{\r
- /* Start USB management task */\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);\r
-\r
- /* Indicate USB enumerating */\r
- UpdateStatus(Status_USBEnumerating);\r
-}\r
-\r
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via\r
- * the status LEDs and stops the USB management and CDC management tasks.\r
- */\r
-void EVENT_USB_Disconnect(void)\r
-{\r
- /* Stop running CDC and USB management tasks */\r
- Scheduler_SetTaskMode(CDC1_Task, TASK_STOP);\r
- Scheduler_SetTaskMode(CDC2_Task, TASK_STOP);\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);\r
-\r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
-}\r
-\r
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration\r
- * of the USB device after enumeration - the device endpoints are configured and the CDC management tasks are started.\r
- */\r
-void EVENT_USB_ConfigurationChanged(void)\r
-{\r
- /* Setup CDC Notification, Rx and Tx Endpoints for the first CDC */\r
- Endpoint_ConfigureEndpoint(CDC1_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,\r
- ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- Endpoint_ConfigureEndpoint(CDC1_TX_EPNUM, EP_TYPE_BULK,\r
- ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- Endpoint_ConfigureEndpoint(CDC1_RX_EPNUM, EP_TYPE_BULK,\r
- ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- /* Setup CDC Notification, Rx and Tx Endpoints for the second CDC */\r
- Endpoint_ConfigureEndpoint(CDC2_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,\r
- ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- Endpoint_ConfigureEndpoint(CDC2_TX_EPNUM, EP_TYPE_BULK,\r
- ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- Endpoint_ConfigureEndpoint(CDC2_RX_EPNUM, EP_TYPE_BULK,\r
- ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
- \r
- /* Indicate USB connected and ready */\r
- UpdateStatus(Status_USBReady);\r
- \r
- /* Start CDC tasks */\r
- Scheduler_SetTaskMode(CDC1_Task, TASK_RUN);\r
- Scheduler_SetTaskMode(CDC2_Task, TASK_RUN);\r
-}\r
-\r
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific\r
- * control requests that are not handled internally by the USB library (including the CDC control commands,\r
- * which are all issued via the control endpoint), so that they can be handled appropriately for the application.\r
- */\r
-void EVENT_USB_UnhandledControlPacket(void)\r
-{\r
- /* Determine which interface's Line Coding data is being set from the wIndex parameter */\r
- uint8_t* LineCodingData = (USB_ControlRequest.wIndex == 0) ? (uint8_t*)&LineCoding1 : (uint8_t*)&LineCoding2;\r
-\r
- /* Process CDC specific control requests */\r
- switch (USB_ControlRequest.bRequest)\r
- {\r
- case REQ_GetLineEncoding:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
- { \r
- /* Acknowledge the SETUP packet, ready for data transfer */\r
- Endpoint_ClearSETUP();\r
-\r
- /* Write the line coding data to the control endpoint */\r
- Endpoint_Write_Control_Stream_LE(LineCodingData, sizeof(CDC_Line_Coding_t));\r
- \r
- /* Finalize the stream transfer to send the last packet or clear the host abort */\r
- Endpoint_ClearOUT();\r
- }\r
- \r
- break;\r
- case REQ_SetLineEncoding:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- /* Acknowledge the SETUP packet, ready for data transfer */\r
- Endpoint_ClearSETUP();\r
-\r
- /* Read the line coding data in from the host into the global struct */\r
- Endpoint_Read_Control_Stream_LE(LineCodingData, sizeof(CDC_Line_Coding_t));\r
-\r
- /* Finalize the stream transfer to clear the last packet from the host */\r
- Endpoint_ClearIN();\r
- }\r
- \r
- break;\r
- case REQ_SetControlLineState:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- /* Acknowledge the SETUP packet, ready for data transfer */\r
- Endpoint_ClearSETUP();\r
- \r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
- }\r
- \r
- break;\r
- }\r
-}\r
-\r
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to\r
- * log to a serial port, or anything else that is suitable for status updates.\r
- *\r
- * \param CurrentStatus Current status of the system, from the DualCDC_StatusCodes_t enum\r
- */\r
-void UpdateStatus(uint8_t CurrentStatus)\r
-{\r
- uint8_t LEDMask = LEDS_NO_LEDS;\r
- \r
- /* Set the LED mask to the appropriate LED mask based on the given status code */\r
- switch (CurrentStatus)\r
- {\r
- case Status_USBNotReady:\r
- LEDMask = (LEDS_LED1);\r
- break;\r
- case Status_USBEnumerating:\r
- LEDMask = (LEDS_LED1 | LEDS_LED2);\r
- break;\r
- case Status_USBReady:\r
- LEDMask = (LEDS_LED2 | LEDS_LED4);\r
- break;\r
- }\r
- \r
- /* Set the board LEDs to the new LED mask */\r
- LEDs_SetAllLEDs(LEDMask);\r
}\r
\r
-/** Function to manage CDC data transmission and reception to and from the host for the first CDC interface, which sends joystick\r
- * movements to the host as ASCII strings.\r
- */\r
-TASK(CDC1_Task)\r
+void CheckJoystickMovement(void)\r
{\r
- char* ReportString = NULL;\r
- uint8_t JoyStatus_LCL = Joystick_GetStatus();\r
- static bool ActionSent = false;\r
+ uint8_t JoyStatus_LCL = Joystick_GetStatus();\r
+ char* ReportString = NULL;\r
+ static bool ActionSent = false;\r
+\r
+ char* JoystickStrings[] =\r
+ {\r
+ "Joystick Up\r\n",\r
+ "Joystick Down\r\n",\r
+ "Joystick Left\r\n",\r
+ "Joystick Right\r\n",\r
+ "Joystick Pressed\r\n",\r
+ };\r
\r
- /* Determine if a joystick action has occurred */\r
if (JoyStatus_LCL & JOY_UP)\r
- ReportString = JoystickUpString;\r
+ ReportString = JoystickStrings[0];\r
else if (JoyStatus_LCL & JOY_DOWN)\r
- ReportString = JoystickDownString;\r
+ ReportString = JoystickStrings[1];\r
else if (JoyStatus_LCL & JOY_LEFT)\r
- ReportString = JoystickLeftString;\r
+ ReportString = JoystickStrings[2];\r
else if (JoyStatus_LCL & JOY_RIGHT)\r
- ReportString = JoystickRightString;\r
+ ReportString = JoystickStrings[3];\r
else if (JoyStatus_LCL & JOY_PRESS)\r
- ReportString = JoystickPressedString;\r
-\r
- /* Flag management - Only allow one string to be sent per action */\r
- if (ReportString == NULL)\r
- {\r
- ActionSent = false;\r
- }\r
- else if (ActionSent == false)\r
+ ReportString = JoystickStrings[4];\r
+ else\r
+ ActionSent = false;\r
+ \r
+ if ((ReportString != NULL) && (ActionSent == false))\r
{\r
ActionSent = true;\r
\r
- /* Select the Serial Tx Endpoint */\r
- Endpoint_SelectEndpoint(CDC1_TX_EPNUM);\r
-\r
- /* Write the String to the Endpoint */\r
- Endpoint_Write_Stream_LE(ReportString, strlen(ReportString));\r
- \r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearIN();\r
-\r
- /* Wait until the endpoint is ready for another packet */\r
- while (!(Endpoint_IsINReady()));\r
- \r
- /* Send an empty packet to ensure that the host does not buffer data sent to it */\r
- Endpoint_ClearIN();\r
+ USB_CDC_SendString(&VirtualSerial1_CDC_Interface, ReportString, strlen(ReportString)); \r
}\r
-\r
- /* Select the Serial Rx Endpoint */\r
- Endpoint_SelectEndpoint(CDC1_RX_EPNUM);\r
- \r
- /* Throw away any received data from the host */\r
- if (Endpoint_IsOUTReceived())\r
- Endpoint_ClearOUT();\r
}\r
\r
-/** Function to manage CDC data transmission and reception to and from the host for the second CDC interface, which echoes back\r
- * all data sent to it from the host.\r
- */\r
-TASK(CDC2_Task)\r
+void EVENT_USB_Connect(void)\r
{\r
- /* Select the Serial Rx Endpoint */\r
- Endpoint_SelectEndpoint(CDC2_RX_EPNUM);\r
- \r
- /* Check to see if any data has been received */\r
- if (Endpoint_IsOUTReceived())\r
- {\r
- /* Create a temp buffer big enough to hold the incoming endpoint packet */\r
- uint8_t Buffer[Endpoint_BytesInEndpoint()];\r
- \r
- /* Remember how large the incoming packet is */\r
- uint16_t DataLength = Endpoint_BytesInEndpoint();\r
- \r
- /* Read in the incoming packet into the buffer */\r
- Endpoint_Read_Stream_LE(&Buffer, DataLength);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);\r
+}\r
\r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearOUT();\r
+void EVENT_USB_Disconnect(void)\r
+{\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
+}\r
\r
- /* Select the Serial Tx Endpoint */\r
- Endpoint_SelectEndpoint(CDC2_TX_EPNUM);\r
- \r
- /* Write the received data to the endpoint */\r
- Endpoint_Write_Stream_LE(&Buffer, DataLength);\r
+void EVENT_USB_ConfigurationChanged(void)\r
+{\r
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
\r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearIN();\r
+ if (!(USB_CDC_ConfigureEndpoints(&VirtualSerial1_CDC_Interface)))\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
\r
- /* Wait until the endpoint is ready for the next packet */\r
- while (!(Endpoint_IsINReady()));\r
+ if (!(USB_CDC_ConfigureEndpoints(&VirtualSerial2_CDC_Interface)))\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
+}\r
\r
- /* Send an empty packet to prevent host buffering */\r
- Endpoint_ClearIN();\r
- }\r
+void EVENT_USB_UnhandledControlPacket(void)\r
+{\r
+ USB_CDC_ProcessControlPacket(&VirtualSerial1_CDC_Interface);\r
+ USB_CDC_ProcessControlPacket(&VirtualSerial2_CDC_Interface);\r
}\r
\r
#include "Descriptors.h"\r
\r
- #include <LUFA/Version.h> // Library Version Information\r
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
- #include <LUFA/Drivers/Board/Joystick.h> // Joystick driver\r
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver\r
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management\r
+ #include <LUFA/Version.h>\r
+ #include <LUFA/Drivers/Board/LEDs.h>\r
+ #include <LUFA/Drivers/Board/Joystick.h>\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/CDC.h>\r
\r
/* Macros: */\r
- /** CDC Class specific request to get the current virtual serial port configuration settings. */\r
- #define REQ_GetLineEncoding 0x21\r
-\r
- /** CDC Class specific request to set the current virtual serial port configuration settings. */\r
- #define REQ_SetLineEncoding 0x20\r
-\r
- /** CDC Class specific request to set the current virtual serial port handshake line states. */\r
- #define REQ_SetControlLineState 0x22\r
-\r
- /* Type Defines: */\r
- /** Type define for the virtual serial port line encoding settings, for storing the current USART configuration\r
- * as set by the host via a class specific request.\r
- */\r
- typedef struct\r
- {\r
- uint32_t BaudRateBPS; /**< Baud rate of the virtual serial port, in bits per second */\r
- uint8_t CharFormat; /**< Character format of the virtual serial port, a value from the\r
- * CDCDevice_CDC_LineCodingFormats_t enum\r
- */\r
- uint8_t ParityType; /**< Parity setting of the virtual serial port, a value from the\r
- * CDCDevice_LineCodingParity_t enum\r
- */\r
- uint8_t DataBits; /**< Bits of data per character of the virtual serial port */\r
- } CDC_Line_Coding_t;\r
+ #define LEDMASK_USB_NOTREADY LEDS_LED1\r
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)\r
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)\r
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)\r
\r
- /* Enums: */\r
- /** Enum for the possible line encoding formats of a virtual serial port. */\r
- enum CDCDevice_CDC_LineCodingFormats_t\r
- {\r
- OneStopBit = 0, /**< Each frame contains one stop bit */\r
- OneAndAHalfStopBits = 1, /**< Each frame contains one and a half stop bits */\r
- TwoStopBits = 2, /**< Each frame contains two stop bits */\r
- };\r
- \r
- /** Enum for the possible line encoding parity settings of a virtual serial port. */\r
- enum CDCDevice_LineCodingParity_t\r
- {\r
- Parity_None = 0, /**< No parity bit mode on each frame */\r
- Parity_Odd = 1, /**< Odd parity bit mode on each frame */\r
- Parity_Even = 2, /**< Even parity bit mode on each frame */\r
- Parity_Mark = 3, /**< Mark parity bit mode on each frame */\r
- Parity_Space = 4, /**< Space parity bit mode on each frame */\r
- };\r
-\r
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */\r
- enum DualCDC_StatusCodes_t\r
- {\r
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */\r
- Status_USBEnumerating = 1, /**< USB interface is enumerating */\r
- Status_USBReady = 2, /**< USB interface is connected and ready */\r
- };\r
-\r
- /* Tasks: */\r
- TASK(CDC1_Task);\r
- TASK(CDC2_Task);\r
-\r
/* Function Prototypes: */\r
+ void SetupHardware(void);\r
+ void CheckJoystickMovement(void);\r
+\r
void EVENT_USB_Connect(void);\r
void EVENT_USB_Disconnect(void);\r
void EVENT_USB_ConfigurationChanged(void);\r
void EVENT_USB_UnhandledControlPacket(void);\r
-\r
- void UpdateStatus(uint8_t CurrentStatus);\r
+ void EVENT_USB_StartOfFrame(void);\r
\r
#endif\r
# List C source files here. (C dependencies are automatically generated.)\r
SRC = $(TARGET).c \\r
Descriptors.c \\r
- $(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Endpoint.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Host.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \\r
- $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \\r
+ $(LUFA_PATH)/LUFA/Drivers/USB/Class/Device/CDC.c \\r
\r
\r
# List C++ source files here. (C dependencies are automatically generated.)\r
\r
# Place -D or -U options here for C sources\r
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)\r
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY\r
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY\r
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION\r
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"\r
\r
#define _DESCRIPTORS_H_\r
\r
/* Includes: */\r
- #include <LUFA/Drivers/USB/USB.h>\r
-\r
#include <avr/pgmspace.h>\r
\r
- /* Type Defines: */\r
- /** Type define for the HID class specific HID descriptor, to describe the HID device's specifications. Refer to the HID\r
- * specification for details on the structure elements.\r
- */\r
- typedef struct\r
- {\r
- USB_Descriptor_Header_t Header;\r
- \r
- uint16_t HIDSpec;\r
- uint8_t CountryCode;\r
- \r
- uint8_t TotalReportDescriptors;\r
-\r
- uint8_t HIDReportType;\r
- uint16_t HIDReportLength;\r
- } USB_Descriptor_HID_t;\r
-\r
- /** Type define for the data type used to store HID report descriptor elements. */\r
- typedef uint8_t USB_Descriptor_HIDReport_Datatype_t;\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>\r
\r
+ /** Type Defines: */\r
/** Type define for the device configuration descriptor structure. This must be defined in the\r
* application code, as the configuration descriptor contains several sub-descriptors which\r
* vary between devices, and which describe the device's usage to the host.\r
USB_Descriptor_Endpoint_t GenericINEndpoint;\r
USB_Descriptor_Endpoint_t GenericOUTEndpoint;\r
} USB_Descriptor_Configuration_t;\r
- \r
+\r
/* Macros: */\r
/** Endpoint number of the Generic HID reporting IN endpoint. */\r
#define GENERIC_IN_EPNUM 1\r
\r
/** Size in bytes of the Generic HID reports (including report ID byte). */\r
#define GENERIC_REPORT_SIZE 8\r
-\r
- /** Descriptor header type value, to indicate a HID class HID descriptor. */\r
- #define DTYPE_HID 0x21\r
\r
- /** Descriptor header type value, to indicate a HID class HID report descriptor. */\r
- #define DTYPE_Report 0x22\r
-\r
/* Function Prototypes: */\r
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)\r
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);\r
this software.\r
*/\r
\r
-/** \file\r
- *\r
- * Main source file for the GenericHID demo. This file contains the main tasks of the demo and\r
- * is responsible for the initial application hardware configuration.\r
- */\r
-\r
#include "GenericHID.h"\r
\r
-/* Scheduler Task List */\r
-TASK_LIST\r
-{\r
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },\r
- { .Task = USB_HID_Report , .TaskStatus = TASK_STOP },\r
-};\r
+USB_ClassInfo_HID_t Generic_HID_Interface =\r
+ {\r
+ .InterfaceNumber = 0,\r
\r
-/** Static buffer to hold the last received report from the host, so that it can be echoed back in the next sent report */\r
-static uint8_t LastReceived[GENERIC_REPORT_SIZE];\r
+ .ReportINEndpointNumber = GENERIC_IN_EPNUM,\r
+ .ReportINEndpointSize = GENERIC_EPSIZE,\r
+ \r
+ .ReportOUTEndpointNumber = GENERIC_OUT_EPNUM,\r
+ .ReportOUTEndpointSize = GENERIC_EPSIZE,\r
+ \r
+ .ReportBufferSize = GENERIC_REPORT_SIZE,\r
\r
+ .UsingReportProtocol = true,\r
+ };\r
\r
-/** Main program entry point. This routine configures the hardware required by the application, then\r
- * starts the scheduler to run the USB management task.\r
- */\r
int main(void)\r
{\r
+ SetupHardware();\r
+ \r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
+ \r
+ for (;;)\r
+ {\r
+ USB_HID_USBTask(&Generic_HID_Interface);\r
+ USB_USBTask();\r
+ }\r
+}\r
+\r
+void SetupHardware(void)\r
+{\r
/* Disable watchdog if enabled by bootloader/fuses */\r
MCUSR &= ~(1 << WDRF);\r
wdt_disable();\r
\r
/* Hardware Initialization */\r
LEDs_Init();\r
-\r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
-\r
- /* Initialize Scheduler so that it can be used */\r
- Scheduler_Init();\r
-\r
- /* Initialize USB Subsystem */\r
USB_Init();\r
- \r
- /* Scheduling - routine never returns, so put this last in the main function */\r
- Scheduler_Start();\r
}\r
\r
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and\r
- * starts the library USB task to begin the enumeration and USB management process.\r
- */\r
void EVENT_USB_Connect(void)\r
{\r
- /* Start USB management task */\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);\r
-\r
- /* Indicate USB enumerating */\r
- UpdateStatus(Status_USBEnumerating);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);\r
}\r
\r
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via\r
- * the status LEDs and stops the USB management task.\r
- */\r
void EVENT_USB_Disconnect(void)\r
{\r
- /* Stop running HID reporting and USB management tasks */\r
- Scheduler_SetTaskMode(USB_HID_Report, TASK_STOP);\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);\r
-\r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
}\r
\r
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host sets the current configuration\r
- * of the USB device after enumeration, and configures the generic HID device endpoints.\r
- */\r
void EVENT_USB_ConfigurationChanged(void)\r
{\r
- /* Setup Generic IN Report Endpoint */\r
- Endpoint_ConfigureEndpoint(GENERIC_IN_EPNUM, EP_TYPE_INTERRUPT,\r
- ENDPOINT_DIR_IN, GENERIC_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
\r
- /* Setup Generic OUT Report Endpoint */\r
- Endpoint_ConfigureEndpoint(GENERIC_OUT_EPNUM, EP_TYPE_INTERRUPT,\r
- ENDPOINT_DIR_OUT, GENERIC_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- /* Indicate USB connected and ready */\r
- UpdateStatus(Status_USBReady);\r
+ if (!(USB_HID_ConfigureEndpoints(&Generic_HID_Interface)))\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
}\r
\r
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific\r
- * control requests that are not handled internally by the USB library (including the HID commands, which are\r
- * all issued via the control endpoint), so that they can be handled appropriately for the application.\r
- */\r
void EVENT_USB_UnhandledControlPacket(void)\r
{\r
- /* Handle HID Class specific requests */\r
- switch (USB_ControlRequest.bRequest)\r
- {\r
- case REQ_GetReport:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- uint8_t GenericData[GENERIC_REPORT_SIZE];\r
-\r
- Endpoint_ClearSETUP();\r
- \r
- CreateGenericHIDReport(GenericData);\r
-\r
- /* Write the report data to the control endpoint */\r
- Endpoint_Write_Control_Stream_LE(&GenericData, sizeof(GenericData));\r
-\r
- /* Finalize the stream transfer to send the last packet or clear the host abort */\r
- Endpoint_ClearOUT();\r
- }\r
- \r
- break;\r
- case REQ_SetReport:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- uint8_t GenericData[GENERIC_REPORT_SIZE];\r
-\r
- Endpoint_ClearSETUP();\r
- \r
- /* Wait until the generic report has been sent by the host */\r
- while (!(Endpoint_IsOUTReceived()));\r
-\r
- Endpoint_Read_Control_Stream_LE(&GenericData, sizeof(GenericData));\r
-\r
- ProcessGenericHIDReport(GenericData);\r
- \r
- /* Clear the endpoint data */\r
- Endpoint_ClearOUT();\r
-\r
- /* Wait until the host is ready to receive the request confirmation */\r
- while (!(Endpoint_IsINReady()));\r
- \r
- /* Handshake the request by sending an empty IN packet */\r
- Endpoint_ClearIN();\r
- }\r
- \r
- break;\r
- }\r
+ USB_HID_ProcessControlPacket(&Generic_HID_Interface);\r
}\r
\r
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to\r
- * log to a serial port, or anything else that is suitable for status updates.\r
- *\r
- * \param CurrentStatus Current status of the system, from the GenericHID_StatusCodes_t enum\r
- */\r
-void UpdateStatus(uint8_t CurrentStatus)\r
+void EVENT_USB_StartOfFrame(void)\r
{\r
- uint8_t LEDMask = LEDS_NO_LEDS;\r
- \r
- /* Set the LED mask to the appropriate LED mask based on the given status code */\r
- switch (CurrentStatus)\r
- {\r
- case Status_USBNotReady:\r
- LEDMask = (LEDS_LED1);\r
- break;\r
- case Status_USBEnumerating:\r
- LEDMask = (LEDS_LED1 | LEDS_LED2);\r
- break;\r
- case Status_USBReady:\r
- LEDMask = (LEDS_LED2 | LEDS_LED4);\r
- break;\r
- }\r
- \r
- /* Set the board LEDs to the new LED mask */\r
- LEDs_SetAllLEDs(LEDMask);\r
+ USB_HID_RegisterStartOfFrame(&Generic_HID_Interface);\r
}\r
\r
-/** Function to process the lest received report from the host.\r
- *\r
- * \param DataArray Pointer to a buffer where the last report data is stored\r
- */\r
-void ProcessGenericHIDReport(uint8_t* DataArray)\r
+uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData)\r
{\r
- /*\r
- This is where you need to process the reports being sent from the host to the device.\r
- DataArray is an array holding the last report from the host. This function is called\r
- each time the host has sent a report to the device.\r
- */\r
+ // Create generic HID report here\r
\r
- for (uint8_t i = 0; i < GENERIC_REPORT_SIZE; i++)\r
- LastReceived[i] = DataArray[i];\r
+ return 0;\r
}\r
\r
-/** Function to create the next report to send back to the host at the next reporting interval.\r
- *\r
- * \param DataArray Pointer to a buffer where the next report data should be stored\r
- */\r
-void CreateGenericHIDReport(uint8_t* DataArray)\r
+void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize)\r
{\r
- /*\r
- This is where you need to create reports to be sent to the host from the device. This\r
- function is called each time the host is ready to accept a new report. DataArray is \r
- an array to hold the report to the host.\r
- */\r
-\r
- for (uint8_t i = 0; i < GENERIC_REPORT_SIZE; i++)\r
- DataArray[i] = LastReceived[i];\r
-}\r
-\r
-TASK(USB_HID_Report)\r
-{\r
- /* Check if the USB system is connected to a host */\r
- if (USB_IsConnected)\r
- {\r
- Endpoint_SelectEndpoint(GENERIC_OUT_EPNUM);\r
- \r
- /* Check to see if a packet has been sent from the host */\r
- if (Endpoint_IsOUTReceived())\r
- {\r
- /* Check to see if the packet contains data */\r
- if (Endpoint_IsReadWriteAllowed())\r
- {\r
- /* Create a temporary buffer to hold the read in report from the host */\r
- uint8_t GenericData[GENERIC_REPORT_SIZE];\r
- \r
- /* Read Generic Report Data */\r
- Endpoint_Read_Stream_LE(&GenericData, sizeof(GenericData));\r
- \r
- /* Process Generic Report Data */\r
- ProcessGenericHIDReport(GenericData);\r
- }\r
-\r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearOUT();\r
- } \r
-\r
- Endpoint_SelectEndpoint(GENERIC_IN_EPNUM);\r
- \r
- /* Check to see if the host is ready to accept another packet */\r
- if (Endpoint_IsINReady())\r
- {\r
- /* Create a temporary buffer to hold the report to send to the host */\r
- uint8_t GenericData[GENERIC_REPORT_SIZE];\r
- \r
- /* Create Generic Report Data */\r
- CreateGenericHIDReport(GenericData);\r
-\r
- /* Write Generic Report Data */\r
- Endpoint_Write_Stream_LE(&GenericData, sizeof(GenericData));\r
-\r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearIN();\r
- }\r
- }\r
+ // Process received generic HID report here\r
}\r
\r
#include "Descriptors.h"\r
\r
- #include <LUFA/Version.h> // Library Version Information\r
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management\r
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver\r
- \r
- /* Macros: */\r
- /** HID Class specific request to get the next HID report from the device. */\r
- #define REQ_GetReport 0x01\r
-\r
- /** HID Class specific request to send the next HID report to the device. */\r
- #define REQ_SetReport 0x09\r
-\r
- /* Enums: */\r
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */\r
- enum GenericHID_StatusCodes_t\r
- {\r
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */\r
- Status_USBEnumerating = 1, /**< USB interface is enumerating */\r
- Status_USBReady = 2, /**< USB interface is connected and ready */\r
- };\r
+ #include <LUFA/Version.h>\r
+ #include <LUFA/Drivers/Board/LEDs.h>\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>\r
\r
- /* Task Definitions: */\r
- TASK(USB_HID_Report);\r
+ /* Macros: */\r
+ #define LEDMASK_USB_NOTREADY LEDS_LED1\r
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)\r
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)\r
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)\r
\r
/* Function Prototypes: */\r
+ void SetupHardware(void);\r
+\r
void EVENT_USB_Connect(void);\r
void EVENT_USB_Disconnect(void);\r
void EVENT_USB_ConfigurationChanged(void);\r
void EVENT_USB_UnhandledControlPacket(void);\r
+ void EVENT_USB_StartOfFrame(void);\r
\r
- void UpdateStatus(uint8_t CurrentStatus);\r
- void ProcessGenericHIDReport(uint8_t* DataArray);\r
- void CreateGenericHIDReport(uint8_t* DataArray);\r
+ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);\r
+ void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo,\r
+ void* ReportData, uint16_t ReportSize);\r
\r
#endif\r
# List C source files here. (C dependencies are automatically generated.)\r
SRC = $(TARGET).c \\r
Descriptors.c \\r
- $(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Endpoint.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Host.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \\r
- $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \\r
+ $(LUFA_PATH)/LUFA/Drivers/USB/Class/Device/HID.c \\r
\r
\r
# List C++ source files here. (C dependencies are automatically generated.)\r
\r
# Place -D or -U options here for C sources\r
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)\r
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY\r
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY\r
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION\r
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"\r
\r
#define _DESCRIPTORS_H_\r
\r
/* Includes: */\r
- #include <LUFA/Drivers/USB/USB.h>\r
-\r
#include <avr/pgmspace.h>\r
\r
- /* Type Defines: */\r
- /** Type define for the HID class specific HID descriptor, to describe the HID device's specifications. Refer to the HID\r
- * specification for details on the structure elements.\r
- */\r
- typedef struct\r
- {\r
- USB_Descriptor_Header_t Header;\r
- \r
- uint16_t HIDSpec;\r
- uint8_t CountryCode;\r
- \r
- uint8_t TotalReportDescriptors;\r
-\r
- uint8_t HIDReportType;\r
- uint16_t HIDReportLength;\r
- } USB_Descriptor_HID_t;\r
-\r
- /** Type define for the data type used to store HID report descriptor elements. */\r
- typedef uint8_t USB_Descriptor_HIDReport_Datatype_t;\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>\r
\r
+ /* Type Defines: */\r
/** Type define for the device configuration descriptor structure. This must be defined in the\r
* application code, as the configuration descriptor contains several sub-descriptors which\r
* vary between devices, and which describe the device's usage to the host.\r
/** Size in bytes of the Joystick HID reporting IN endpoint. */\r
#define JOYSTICK_EPSIZE 8\r
\r
- /** Descriptor header type value, to indicate a HID class HID descriptor. */\r
- #define DTYPE_HID 0x21\r
- \r
- /** Descriptor header type value, to indicate a HID class HID report descriptor. */\r
- #define DTYPE_Report 0x22\r
-\r
/* Function Prototypes: */\r
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)\r
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);\r
this software.\r
*/\r
\r
-/** \file\r
- *\r
- * Main source file for the Joystick demo. This file contains the main tasks of the demo and\r
- * is responsible for the initial application hardware configuration.\r
- */\r
-\r
#include "Joystick.h"\r
\r
-/* Scheduler Task List */\r
-TASK_LIST\r
-{\r
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },\r
- { .Task = USB_Joystick_Report , .TaskStatus = TASK_STOP },\r
-};\r
+USB_ClassInfo_HID_t Joystick_HID_Interface =\r
+ {\r
+ .InterfaceNumber = 0,\r
+\r
+ .ReportINEndpointNumber = JOYSTICK_EPNUM,\r
+ .ReportINEndpointSize = JOYSTICK_EPSIZE,\r
+ \r
+ .ReportBufferSize = sizeof(USB_JoystickReport_Data_t),\r
+\r
+ .UsingReportProtocol = true,\r
+ };\r
\r
-/** Main program entry point. This routine configures the hardware required by the application, then\r
- * starts the scheduler to run the application tasks.\r
- */\r
int main(void)\r
{\r
+ SetupHardware();\r
+ \r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
+ \r
+ for (;;)\r
+ {\r
+ USB_HID_USBTask(&Joystick_HID_Interface);\r
+ USB_USBTask();\r
+ }\r
+}\r
+\r
+void SetupHardware(void)\r
+{\r
/* Disable watchdog if enabled by bootloader/fuses */\r
MCUSR &= ~(1 << WDRF);\r
wdt_disable();\r
Joystick_Init();\r
LEDs_Init();\r
Buttons_Init();\r
- \r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
- \r
- /* Initialize Scheduler so that it can be used */\r
- Scheduler_Init();\r
-\r
- /* Initialize USB Subsystem */\r
USB_Init();\r
-\r
- /* Scheduling - routine never returns, so put this last in the main function */\r
- Scheduler_Start();\r
}\r
\r
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and\r
- * starts the library USB task to begin the enumeration and USB management process.\r
- */\r
void EVENT_USB_Connect(void)\r
{\r
- /* Start USB management task */\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);\r
-\r
- /* Indicate USB enumerating */\r
- UpdateStatus(Status_USBEnumerating);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);\r
}\r
\r
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via\r
- * the status LEDs and stops the USB management and joystick reporting tasks.\r
- */\r
void EVENT_USB_Disconnect(void)\r
{\r
- /* Stop running joystick reporting and USB management tasks */\r
- Scheduler_SetTaskMode(USB_Joystick_Report, TASK_STOP);\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);\r
-\r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
}\r
\r
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration\r
- * of the USB device after enumeration - the device endpoints are configured and the joystick reporting task started.\r
- */ \r
void EVENT_USB_ConfigurationChanged(void)\r
{\r
- /* Setup Joystick Report Endpoint */\r
- Endpoint_ConfigureEndpoint(JOYSTICK_EPNUM, EP_TYPE_INTERRUPT,\r
- ENDPOINT_DIR_IN, JOYSTICK_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
\r
- /* Indicate USB connected and ready */\r
- UpdateStatus(Status_USBReady);\r
-\r
- /* Start joystick reporting task */\r
- Scheduler_SetTaskMode(USB_Joystick_Report, TASK_RUN);\r
+ if (!(USB_HID_ConfigureEndpoints(&Joystick_HID_Interface)))\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
}\r
\r
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific\r
- * control requests that are not handled internally by the USB library (including the HID commands, which are\r
- * all issued via the control endpoint), so that they can be handled appropriately for the application.\r
- */\r
void EVENT_USB_UnhandledControlPacket(void)\r
{\r
- /* Handle HID Class specific requests */\r
- switch (USB_ControlRequest.bRequest)\r
- {\r
- case REQ_GetReport:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- USB_JoystickReport_Data_t JoystickReportData;\r
- \r
- Endpoint_ClearSETUP();\r
-\r
- /* Create the next HID report to send to the host */ \r
- GetNextReport(&JoystickReportData);\r
- \r
- /* Write the report data to the control endpoint */\r
- Endpoint_Write_Control_Stream_LE(&JoystickReportData, sizeof(JoystickReportData));\r
- \r
- /* Finalize the stream transfer to send the last packet or clear the host abort */\r
- Endpoint_ClearOUT();\r
- }\r
- \r
- break;\r
- }\r
+ USB_HID_ProcessControlPacket(&Joystick_HID_Interface);\r
}\r
\r
-/** Fills the given HID report data structure with the next HID report to send to the host.\r
- *\r
- * \param ReportData Pointer to a HID report data structure to be filled\r
- *\r
- * \return Boolean true if the new report differs from the last report, false otherwise\r
- */\r
-bool GetNextReport(USB_JoystickReport_Data_t* ReportData)\r
+void EVENT_USB_StartOfFrame(void)\r
{\r
- static uint8_t PrevJoyStatus = 0;\r
- static uint8_t PrevButtonStatus = 0;\r
- uint8_t JoyStatus_LCL = Joystick_GetStatus();\r
- uint8_t ButtonStatus_LCL = Buttons_GetStatus();\r
- bool InputChanged = false;\r
+ USB_HID_RegisterStartOfFrame(&Joystick_HID_Interface);\r
+}\r
\r
- /* Clear the report contents */\r
- memset(ReportData, 0, sizeof(USB_JoystickReport_Data_t));\r
+uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData)\r
+{\r
+ USB_JoystickReport_Data_t* JoystickReport = (USB_JoystickReport_Data_t*)ReportData;\r
+ \r
+ uint8_t JoyStatus_LCL = Joystick_GetStatus();\r
+ uint8_t ButtonStatus_LCL = Buttons_GetStatus();\r
\r
if (JoyStatus_LCL & JOY_UP)\r
- ReportData->Y = -100;\r
+ JoystickReport->Y = -100;\r
else if (JoyStatus_LCL & JOY_DOWN)\r
- ReportData->Y = 100;\r
+ JoystickReport->Y = 100;\r
\r
if (JoyStatus_LCL & JOY_RIGHT)\r
- ReportData->X = 100;\r
+ JoystickReport->X = 100;\r
else if (JoyStatus_LCL & JOY_LEFT)\r
- ReportData->X = -100;\r
+ JoystickReport->X = -100;\r
\r
if (JoyStatus_LCL & JOY_PRESS)\r
- ReportData->Button = (1 << 1);\r
+ JoystickReport->Button = (1 << 1);\r
\r
if (ButtonStatus_LCL & BUTTONS_BUTTON1)\r
- ReportData->Button |= (1 << 0);\r
+ JoystickReport->Button |= (1 << 0);\r
\r
- /* Check if the new report is different to the previous report */\r
- InputChanged = (uint8_t)(PrevJoyStatus ^ JoyStatus_LCL) | (uint8_t)(PrevButtonStatus ^ ButtonStatus_LCL);\r
-\r
- /* Save the current joystick status for later comparison */\r
- PrevJoyStatus = JoyStatus_LCL;\r
- PrevButtonStatus = ButtonStatus_LCL;\r
-\r
- /* Return whether the new report is different to the previous report or not */\r
- return InputChanged;\r
+ return sizeof(USB_JoystickReport_Data_t);\r
}\r
\r
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to\r
- * log to a serial port, or anything else that is suitable for status updates.\r
- *\r
- * \param CurrentStatus Current status of the system, from the Joystick_StatusCodes_t enum\r
- */\r
-void UpdateStatus(uint8_t CurrentStatus)\r
+void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize)\r
{\r
- uint8_t LEDMask = LEDS_NO_LEDS;\r
- \r
- /* Set the LED mask to the appropriate LED mask based on the given status code */\r
- switch (CurrentStatus)\r
- {\r
- case Status_USBNotReady:\r
- LEDMask = (LEDS_LED1);\r
- break;\r
- case Status_USBEnumerating:\r
- LEDMask = (LEDS_LED1 | LEDS_LED2);\r
- break;\r
- case Status_USBReady:\r
- LEDMask = (LEDS_LED2 | LEDS_LED4);\r
- break;\r
- }\r
- \r
- /* Set the board LEDs to the new LED mask */\r
- LEDs_SetAllLEDs(LEDMask);\r
-}\r
-\r
-/** Function to manage HID report generation and transmission to the host. */\r
-TASK(USB_Joystick_Report)\r
-{\r
- /* Check if the USB System is connected to a Host */\r
- if (USB_IsConnected)\r
- {\r
- /* Select the Joystick Report Endpoint */\r
- Endpoint_SelectEndpoint(JOYSTICK_EPNUM);\r
-\r
- /* Check to see if the host is ready for another packet */\r
- if (Endpoint_IsINReady())\r
- {\r
- USB_JoystickReport_Data_t JoystickReportData;\r
- \r
- /* Create the next HID report to send to the host */\r
- GetNextReport(&JoystickReportData);\r
- \r
- /* Write Joystick Report Data */\r
- Endpoint_Write_Stream_LE(&JoystickReportData, sizeof(JoystickReportData));\r
-\r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearIN();\r
- \r
- /* Clear the report data afterwards */\r
- memset(&JoystickReportData, 0, sizeof(JoystickReportData));\r
- }\r
- }\r
+ // Unused (but mandatory for the HID class driver) in this demo, since there are no Host->Device reports\r
}\r
\r
#include "Descriptors.h"\r
\r
- #include <LUFA/Version.h> // Library Version Information\r
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
- #include <LUFA/Drivers/Board/Joystick.h> // Joystick driver\r
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver\r
- #include <LUFA/Drivers/Board/Buttons.h> // Board Buttons driver\r
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management\r
- \r
- /* Task Definitions: */\r
- TASK(USB_Joystick_Report);\r
-\r
- /* Macros: */\r
- /** HID Class specific request to get the next HID report from the device. */\r
- #define REQ_GetReport 0x01\r
+ #include <LUFA/Version.h>\r
+ #include <LUFA/Drivers/Board/Joystick.h>\r
+ #include <LUFA/Drivers/Board/LEDs.h>\r
+ #include <LUFA/Drivers/Board/Buttons.h>\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>\r
\r
/* Type Defines: */\r
/** Type define for the joystick HID report structure, for creating and sending HID reports to the host PC.\r
uint8_t Button; /**< Bit mask of the currently pressed joystick buttons */\r
} USB_JoystickReport_Data_t;\r
\r
- /* Enums: */\r
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */\r
- enum Joystick_StatusCodes_t\r
- {\r
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */\r
- Status_USBEnumerating = 1, /**< USB interface is enumerating */\r
- Status_USBReady = 2, /**< USB interface is connected and ready */\r
- };\r
+ /* Macros: */\r
+ #define LEDMASK_USB_NOTREADY LEDS_LED1\r
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)\r
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)\r
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)\r
\r
/* Function Prototypes: */\r
+ void SetupHardware(void);\r
+\r
void EVENT_USB_Connect(void);\r
void EVENT_USB_Disconnect(void);\r
void EVENT_USB_ConfigurationChanged(void);\r
void EVENT_USB_UnhandledControlPacket(void);\r
+ void EVENT_USB_StartOfFrame(void);\r
\r
- bool GetNextReport(USB_JoystickReport_Data_t* ReportData);\r
- void UpdateStatus(uint8_t CurrentStatus);\r
+ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);\r
+ void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo,\r
+ void* ReportData, uint16_t ReportSize);\r
\r
#endif\r
# List C source files here. (C dependencies are automatically generated.)\r
SRC = $(TARGET).c \\r
Descriptors.c \\r
- $(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Endpoint.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Host.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \\r
- $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \\r
+ $(LUFA_PATH)/LUFA/Drivers/USB/Class/Device/HID.c \\r
\r
\r
# List C++ source files here. (C dependencies are automatically generated.)\r
\r
# Place -D or -U options here for C sources\r
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)\r
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY\r
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY\r
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION\r
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"\r
\r
#define _DESCRIPTORS_H_\r
\r
/* Includes: */\r
- #include <LUFA/Drivers/USB/USB.h>\r
-\r
#include <avr/pgmspace.h>\r
\r
- /* Type Defines: */\r
- /** Type define for the HID class specific HID descriptor, to describe the HID device's specifications. Refer to the HID\r
- * specification for details on the structure elements.\r
- */ \r
- typedef struct\r
- {\r
- USB_Descriptor_Header_t Header;\r
- \r
- uint16_t HIDSpec;\r
- uint8_t CountryCode;\r
- \r
- uint8_t TotalReportDescriptors;\r
-\r
- uint8_t HIDReportType;\r
- uint16_t HIDReportLength;\r
- } USB_Descriptor_HID_t;\r
- \r
- /** Type define for the data type used to store HID report descriptor elements. */\r
- typedef uint8_t USB_Descriptor_HIDReport_Datatype_t;\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>\r
\r
+ /* Type Defines: */\r
/** Type define for the device configuration descriptor structure. This must be defined in the\r
* application code, as the configuration descriptor contains several sub-descriptors which\r
* vary between devices, and which describe the device's usage to the host.\r
/** Size in bytes of the Keyboard HID reporting IN and OUT endpoints. */ \r
#define KEYBOARD_EPSIZE 8\r
\r
- /** Descriptor header type value, to indicate a HID class HID descriptor. */\r
- #define DTYPE_HID 0x21\r
- \r
- /** Descriptor header type value, to indicate a HID class HID report descriptor. */\r
- #define DTYPE_Report 0x22\r
-\r
/* Function Prototypes: */\r
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)\r
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);\r
arising out of or in connection with the use or performance of\r
this software.\r
*/\r
-\r
-/** \file\r
- *\r
- * Main source file for the Keyboard demo. This file contains the main tasks of the demo and\r
- * is responsible for the initial application hardware configuration.\r
- */\r
\r
#include "Keyboard.h"\r
\r
-/* Scheduler Task List */\r
-TASK_LIST\r
-{\r
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP }, \r
- { .Task = USB_Keyboard_Report , .TaskStatus = TASK_STOP },\r
-};\r
-\r
-/* Global Variables */\r
-/** Indicates what report mode the host has requested, true for normal HID reporting mode, false for special boot\r
- * protocol reporting mode.\r
- */\r
-bool UsingReportProtocol = true;\r
+USB_ClassInfo_HID_t Keyboard_HID_Interface =\r
+ {\r
+ .InterfaceNumber = 0,\r
\r
-/** Current Idle period. This is set by the host via a Set Idle HID class request to silence the device's reports\r
- * for either the entire idle duration, or until the report status changes (e.g. the user presses a key).\r
- */\r
-uint16_t IdleCount = 500;\r
+ .ReportINEndpointNumber = KEYBOARD_EPNUM,\r
+ .ReportINEndpointSize = KEYBOARD_EPSIZE,\r
\r
-/** Current Idle period remaining. When the IdleCount value is set, this tracks the remaining number of idle\r
- * milliseconds. This is separate to the IdleCount timer and is incremented and compared as the host may request \r
- * the current idle period via a Get Idle HID class request, thus its value must be preserved.\r
- */\r
-uint16_t IdleMSRemaining = 0;\r
+ .ReportOUTEndpointNumber = KEYBOARD_LEDS_EPNUM,\r
+ .ReportOUTEndpointSize = KEYBOARD_EPSIZE,\r
+ \r
+ .ReportBufferSize = sizeof(USB_KeyboardReport_Data_t),\r
\r
+ .IdleCount = 500,\r
+ };\r
\r
-/** Main program entry point. This routine configures the hardware required by the application, then\r
- * starts the scheduler to run the USB management task.\r
- */\r
int main(void)\r
{\r
- /* Disable watchdog if enabled by bootloader/fuses */\r
- MCUSR &= ~(1 << WDRF);\r
- wdt_disable();\r
-\r
- /* Disable clock division */\r
- clock_prescale_set(clock_div_1);\r
-\r
- /* Hardware Initialization */\r
- Joystick_Init();\r
- LEDs_Init();\r
- \r
- /* Millisecond timer initialization, with output compare interrupt enabled for the idle timing */\r
- OCR0A = 0x7D;\r
- TCCR0A = (1 << WGM01);\r
- TCCR0B = ((1 << CS01) | (1 << CS00));\r
- TIMSK0 = (1 << OCIE0A);\r
-\r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
-\r
- /* Initialize Scheduler so that it can be used */\r
- Scheduler_Init();\r
+ SetupHardware();\r
+\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
+ \r
+ for (;;)\r
+ {\r
+ USB_HID_USBTask(&Keyboard_HID_Interface);\r
+ USB_USBTask();\r
+ }\r
+}\r
\r
- /* Initialize USB Subsystem */\r
- USB_Init();\r
- \r
- /* Scheduling - routine never returns, so put this last in the main function */\r
- Scheduler_Start();\r
+void SetupHardware()\r
+{\r
+ /* Disable watchdog if enabled by bootloader/fuses */\r
+ MCUSR &= ~(1 << WDRF);\r
+ wdt_disable();\r
+\r
+ /* Disable clock division */\r
+ clock_prescale_set(clock_div_1);\r
+\r
+ /* Hardware Initialization */\r
+ Joystick_Init();\r
+ LEDs_Init();\r
+ Buttons_Init();\r
+ USB_Init();\r
}\r
\r
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and\r
- * starts the library USB task to begin the enumeration and USB management process.\r
- */\r
void EVENT_USB_Connect(void)\r
{\r
- /* Start USB management task */\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);\r
-\r
- /* Indicate USB enumerating */\r
- UpdateStatus(Status_USBEnumerating);\r
-\r
- /* Default to report protocol on connect */\r
- UsingReportProtocol = true;\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);\r
}\r
\r
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via\r
- * the status LEDs.\r
- */\r
void EVENT_USB_Disconnect(void)\r
{\r
- /* Stop running keyboard reporting and USB management tasks */\r
- Scheduler_SetTaskMode(USB_Keyboard_Report, TASK_STOP);\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);\r
- \r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
}\r
\r
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host sets the current configuration\r
- * of the USB device after enumeration, and configures the keyboard device endpoints.\r
- */\r
void EVENT_USB_ConfigurationChanged(void)\r
{\r
- /* Setup Keyboard Keycode Report Endpoint */\r
- Endpoint_ConfigureEndpoint(KEYBOARD_EPNUM, EP_TYPE_INTERRUPT,\r
- ENDPOINT_DIR_IN, KEYBOARD_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- /* Setup Keyboard LED Report Endpoint */\r
- Endpoint_ConfigureEndpoint(KEYBOARD_LEDS_EPNUM, EP_TYPE_INTERRUPT,\r
- ENDPOINT_DIR_OUT, KEYBOARD_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
\r
- /* Indicate USB connected and ready */\r
- UpdateStatus(Status_USBReady);\r
-\r
- /* Start running keyboard reporting task */\r
- Scheduler_SetTaskMode(USB_Keyboard_Report, TASK_RUN);\r
+ if (!(USB_HID_ConfigureEndpoints(&Keyboard_HID_Interface)))\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
}\r
\r
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific\r
- * control requests that are not handled internally by the USB library (including the HID commands, which are\r
- * all issued via the control endpoint), so that they can be handled appropriately for the application.\r
- */\r
void EVENT_USB_UnhandledControlPacket(void)\r
{\r
- /* Handle HID Class specific requests */\r
- switch (USB_ControlRequest.bRequest)\r
- {\r
- case REQ_GetReport:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- USB_KeyboardReport_Data_t KeyboardReportData;\r
-\r
- Endpoint_ClearSETUP();\r
- \r
- /* Create the next keyboard report for transmission to the host */\r
- CreateKeyboardReport(&KeyboardReportData);\r
-\r
- /* Write the report data to the control endpoint */\r
- Endpoint_Write_Control_Stream_LE(&KeyboardReportData, sizeof(KeyboardReportData));\r
- \r
- /* Finalize the stream transfer to send the last packet or clear the host abort */\r
- Endpoint_ClearOUT();\r
- }\r
- \r
- break;\r
- case REQ_SetReport:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- Endpoint_ClearSETUP();\r
- \r
- /* Wait until the LED report has been sent by the host */\r
- while (!(Endpoint_IsOUTReceived()));\r
-\r
- /* Read in the LED report from the host */\r
- uint8_t LEDStatus = Endpoint_Read_Byte();\r
-\r
- /* Process the incoming LED report */\r
- ProcessLEDReport(LEDStatus);\r
- \r
- /* Clear the endpoint data */\r
- Endpoint_ClearOUT();\r
-\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
- }\r
- \r
- break;\r
- case REQ_GetProtocol:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- Endpoint_ClearSETUP();\r
- \r
- /* Write the current protocol flag to the host */\r
- Endpoint_Write_Byte(UsingReportProtocol);\r
- \r
- /* Send the flag to the host */\r
- Endpoint_ClearIN();\r
-\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
- }\r
- \r
- break;\r
- case REQ_SetProtocol:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- Endpoint_ClearSETUP();\r
-\r
- /* Set or clear the flag depending on what the host indicates that the current Protocol should be */\r
- UsingReportProtocol = (USB_ControlRequest.wValue != 0);\r
-\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
- }\r
- \r
- break;\r
- case REQ_SetIdle:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- Endpoint_ClearSETUP();\r
- \r
- /* Get idle period in MSB */\r
- IdleCount = (USB_ControlRequest.wValue >> 8);\r
- \r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
- }\r
- \r
- break;\r
- case REQ_GetIdle:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
- { \r
- Endpoint_ClearSETUP();\r
- \r
- /* Write the current idle duration to the host */\r
- Endpoint_Write_Byte(IdleCount);\r
- \r
- /* Send the flag to the host */\r
- Endpoint_ClearIN();\r
-\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
- }\r
-\r
- break;\r
- }\r
+ USB_HID_ProcessControlPacket(&Keyboard_HID_Interface);\r
}\r
\r
-/** ISR for the timer 0 compare vector. This ISR fires once each millisecond, and increments the\r
- * scheduler elapsed idle period counter when the host has set an idle period.\r
- */\r
-ISR(TIMER0_COMPA_vect, ISR_BLOCK)\r
+void EVENT_USB_StartOfFrame(void)\r
{\r
- /* One millisecond has elapsed, decrement the idle time remaining counter if it has not already elapsed */\r
- if (IdleMSRemaining)\r
- IdleMSRemaining--;\r
-}\r
-\r
-/** Fills the given HID report data structure with the next HID report to send to the host.\r
- *\r
- * \param ReportData Pointer to a HID report data structure to be filled\r
- */\r
-void CreateKeyboardReport(USB_KeyboardReport_Data_t* ReportData)\r
-{\r
- uint8_t JoyStatus_LCL = Joystick_GetStatus();\r
-\r
- /* Clear the report contents */\r
- memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));\r
-\r
- if (JoyStatus_LCL & JOY_UP)\r
- ReportData->KeyCode[0] = 0x04; // A\r
- else if (JoyStatus_LCL & JOY_DOWN)\r
- ReportData->KeyCode[0] = 0x05; // B\r
-\r
- if (JoyStatus_LCL & JOY_LEFT)\r
- ReportData->KeyCode[0] = 0x06; // C\r
- else if (JoyStatus_LCL & JOY_RIGHT)\r
- ReportData->KeyCode[0] = 0x07; // D\r
-\r
- if (JoyStatus_LCL & JOY_PRESS)\r
- ReportData->KeyCode[0] = 0x08; // E\r
-}\r
-\r
-/** Processes a received LED report, and updates the board LEDs states to match.\r
- *\r
- * \param LEDReport LED status report from the host\r
- */\r
-void ProcessLEDReport(uint8_t LEDReport)\r
-{\r
- uint8_t LEDMask = LEDS_LED2;\r
- \r
- if (LEDReport & 0x01) // NUM Lock\r
- LEDMask |= LEDS_LED1;\r
- \r
- if (LEDReport & 0x02) // CAPS Lock\r
- LEDMask |= LEDS_LED3;\r
-\r
- if (LEDReport & 0x04) // SCROLL Lock\r
- LEDMask |= LEDS_LED4;\r
-\r
- /* Set the status LEDs to the current Keyboard LED status */\r
- LEDs_SetAllLEDs(LEDMask);\r
-}\r
-\r
-/** Sends the next HID report to the host, via the keyboard data endpoint. */\r
-void SendNextReport(void)\r
-{\r
- static USB_KeyboardReport_Data_t PrevKeyboardReportData;\r
- USB_KeyboardReport_Data_t KeyboardReportData;\r
- bool SendReport = true;\r
- \r
- /* Create the next keyboard report for transmission to the host */\r
- CreateKeyboardReport(&KeyboardReportData);\r
- \r
- /* Check to see if the report data has changed - if so a report MUST be sent */\r
- SendReport = (memcmp(&PrevKeyboardReportData, &KeyboardReportData, sizeof(USB_KeyboardReport_Data_t)) != 0);\r
- \r
- /* Save the current report data for later comparison to check for changes */\r
- PrevKeyboardReportData = KeyboardReportData;\r
- \r
- /* Check if the idle period is set and has elapsed */\r
- if ((IdleCount != HID_IDLE_CHANGESONLY) && (!(IdleMSRemaining)))\r
- {\r
- /* Reset the idle time remaining counter, must multiply by 4 to get the duration in milliseconds */\r
- IdleMSRemaining = (IdleCount << 2);\r
- \r
- /* Idle period is set and has elapsed, must send a report to the host */\r
- SendReport = true;\r
- }\r
- \r
- /* Select the Keyboard Report Endpoint */\r
- Endpoint_SelectEndpoint(KEYBOARD_EPNUM);\r
-\r
- /* Check if Keyboard Endpoint Ready for Read/Write and if we should send a new report */\r
- if (Endpoint_IsReadWriteAllowed() && SendReport)\r
- {\r
- /* Write Keyboard Report Data */\r
- Endpoint_Write_Stream_LE(&KeyboardReportData, sizeof(KeyboardReportData));\r
- \r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearIN();\r
- }\r
-}\r
-\r
-/** Reads the next LED status report from the host from the LED data endpoint, if one has been sent. */\r
-void ReceiveNextReport(void)\r
-{\r
- /* Select the Keyboard LED Report Endpoint */\r
- Endpoint_SelectEndpoint(KEYBOARD_LEDS_EPNUM);\r
-\r
- /* Check if Keyboard LED Endpoint contains a packet */\r
- if (Endpoint_IsOUTReceived())\r
- {\r
- /* Check to see if the packet contains data */\r
- if (Endpoint_IsReadWriteAllowed())\r
- {\r
- /* Read in the LED report from the host */\r
- uint8_t LEDReport = Endpoint_Read_Byte();\r
-\r
- /* Process the read LED report from the host */\r
- ProcessLEDReport(LEDReport);\r
- }\r
-\r
- /* Handshake the OUT Endpoint - clear endpoint and ready for next report */\r
- Endpoint_ClearOUT();\r
- }\r
+ USB_HID_RegisterStartOfFrame(&Keyboard_HID_Interface);\r
}\r
\r
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to\r
- * log to a serial port, or anything else that is suitable for status updates.\r
- *\r
- * \param CurrentStatus Current status of the system, from the Keyboard_StatusCodes_t enum\r
- */\r
-void UpdateStatus(uint8_t CurrentStatus)\r
+uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData)\r
{\r
- uint8_t LEDMask = LEDS_NO_LEDS;\r
- \r
- /* Set the LED mask to the appropriate LED mask based on the given status code */\r
- switch (CurrentStatus)\r
- {\r
- case Status_USBNotReady:\r
- LEDMask = (LEDS_LED1);\r
- break;\r
- case Status_USBEnumerating:\r
- LEDMask = (LEDS_LED1 | LEDS_LED2);\r
- break;\r
- case Status_USBReady:\r
- LEDMask = (LEDS_LED2 | LEDS_LED4);\r
- break;\r
- }\r
- \r
- /* Set the board LEDs to the new LED mask */\r
- LEDs_SetAllLEDs(LEDMask);\r
+ USB_KeyboardReport_Data_t* KeyboardReport = (USB_KeyboardReport_Data_t*)ReportData;\r
+ \r
+ uint8_t JoyStatus_LCL = Joystick_GetStatus();\r
+ uint8_t ButtonStatus_LCL = Buttons_GetStatus();\r
+\r
+ if (JoyStatus_LCL & JOY_UP)\r
+ KeyboardReport->KeyCode[0] = 0x04; // A\r
+ else if (JoyStatus_LCL & JOY_DOWN)\r
+ KeyboardReport->KeyCode[0] = 0x05; // B\r
+\r
+ if (JoyStatus_LCL & JOY_LEFT)\r
+ KeyboardReport->KeyCode[0] = 0x06; // C\r
+ else if (JoyStatus_LCL & JOY_RIGHT)\r
+ KeyboardReport->KeyCode[0] = 0x07; // D\r
+\r
+ if (JoyStatus_LCL & JOY_PRESS)\r
+ KeyboardReport->KeyCode[0] = 0x08; // E\r
+ \r
+ if (ButtonStatus_LCL & BUTTONS_BUTTON1)\r
+ KeyboardReport->KeyCode[0] = 0x09; // F\r
+ \r
+ return sizeof(USB_KeyboardReport_Data_t);\r
}\r
\r
-/** Function to manage HID report generation and transmission to the host, when in report mode. */\r
-TASK(USB_Keyboard_Report)\r
+void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize)\r
{\r
- /* Check if the USB system is connected to a host */\r
- if (USB_IsConnected)\r
- {\r
- /* Send the next keypress report to the host */\r
- SendNextReport();\r
- \r
- /* Process the LED report sent from the host */\r
- ReceiveNextReport();\r
- }\r
+ uint8_t LEDMask = LEDS_NO_LEDS;\r
+ uint8_t* LEDReport = (uint8_t*)ReportData;\r
+\r
+ if (*LEDReport & 0x01) // NUM Lock\r
+ LEDMask |= LEDS_LED1;\r
+ \r
+ if (*LEDReport & 0x02) // CAPS Lock\r
+ LEDMask |= LEDS_LED3;\r
+\r
+ if (*LEDReport & 0x04) // SCROLL Lock\r
+ LEDMask |= LEDS_LED4;\r
+ \r
+ LEDs_SetAllLEDs(LEDMask);\r
}\r
\r
#include "Descriptors.h"\r
\r
- #include <LUFA/Version.h> // Library Version Information\r
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management\r
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
- #include <LUFA/Drivers/Board/Joystick.h> // Joystick driver\r
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver\r
-\r
- /* Macros: */\r
- /** Idle period indicating that reports should be sent only when the inputs have changed */\r
- #define HID_IDLE_CHANGESONLY 0\r
-\r
- /** HID Class specific request to get the next HID report from the device. */\r
- #define REQ_GetReport 0x01\r
-\r
- /** HID Class specific request to get the idle timeout period of the device. */\r
- #define REQ_GetIdle 0x02\r
-\r
- /** HID Class specific request to send the next HID report to the device. */\r
- #define REQ_SetReport 0x09\r
-\r
- /** HID Class specific request to set the idle timeout period of the device. */\r
- #define REQ_SetIdle 0x0A\r
-\r
- /** HID Class specific request to get the current HID protocol in use, either report or boot. */\r
- #define REQ_GetProtocol 0x03\r
-\r
- /** HID Class specific request to set the current HID protocol in use, either report or boot. */\r
- #define REQ_SetProtocol 0x0B\r
- \r
- /* Task Definitions: */\r
- TASK(USB_Keyboard_Report);\r
+ #include <LUFA/Version.h>\r
+ #include <LUFA/Drivers/Board/Joystick.h>\r
+ #include <LUFA/Drivers/Board/LEDs.h>\r
+ #include <LUFA/Drivers/Board/Buttons.h>\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>\r
\r
/* Type Defines: */\r
/** Type define for the keyboard HID report structure, for creating and sending HID reports to the host PC.\r
uint8_t KeyCode[6]; /**< Array of up to six simultaneous key codes of pressed keys */\r
} USB_KeyboardReport_Data_t;\r
\r
- /* Enums: */\r
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */\r
- enum Keyboard_StatusCodes_t\r
- {\r
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */\r
- Status_USBEnumerating = 1, /**< USB interface is enumerating */\r
- Status_USBReady = 2, /**< USB interface is connected and ready */\r
- };\r
+ /* Macros: */\r
+ #define LEDMASK_USB_NOTREADY LEDS_LED1\r
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)\r
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)\r
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)\r
\r
/* Function Prototypes: */\r
+ void SetupHardware(void);\r
+\r
void EVENT_USB_Connect(void);\r
void EVENT_USB_Disconnect(void);\r
void EVENT_USB_ConfigurationChanged(void);\r
void EVENT_USB_UnhandledControlPacket(void);\r
+ void EVENT_USB_StartOfFrame(void);\r
\r
- void CreateKeyboardReport(USB_KeyboardReport_Data_t* ReportData);\r
- void ProcessLEDReport(uint8_t LEDReport);\r
- void SendNextReport(void);\r
- void ReceiveNextReport(void);\r
- void UpdateStatus(uint8_t CurrentStatus);\r
+ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);\r
+ void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo,\r
+ void* ReportData, uint16_t ReportSize);\r
\r
#endif\r
# List C source files here. (C dependencies are automatically generated.)\r
SRC = $(TARGET).c \\r
Descriptors.c \\r
- $(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Endpoint.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Host.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \\r
- $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \\r
+ $(LUFA_PATH)/LUFA/Drivers/USB/Class/Device/HID.c \\r
\r
\r
# List C++ source files here. (C dependencies are automatically generated.)\r
\r
# Place -D or -U options here for C sources\r
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)\r
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY\r
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY\r
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION\r
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"\r
\r
#define _DESCRIPTORS_H_\r
\r
/* Includes: */\r
- #include <LUFA/Drivers/USB/USB.h>\r
-\r
#include <avr/pgmspace.h>\r
\r
- /* Type Defines: */\r
- /** Type define for the HID class specific HID descriptor, to describe the HID device's specifications. Refer to the HID\r
- * specification for details on the structure elements.\r
- */\r
- typedef struct\r
- {\r
- USB_Descriptor_Header_t Header;\r
- \r
- uint16_t HIDSpec;\r
- uint8_t CountryCode;\r
- \r
- uint8_t TotalReportDescriptors;\r
-\r
- uint8_t HIDReportType;\r
- uint16_t HIDReportLength;\r
- } USB_Descriptor_HID_t;\r
-\r
- /** Type define for the data type used to store HID report descriptor elements. */\r
- typedef uint8_t USB_Descriptor_HIDReport_Datatype_t;\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>\r
\r
+ /* Type Defines: */\r
/** Type define for the device configuration descriptor structure. This must be defined in the\r
* application code, as the configuration descriptor contains several sub-descriptors which\r
* vary between devices, and which describe the device's usage to the host.\r
/** Size in bytes of each of the HID reporting IN and OUT endpoints. */\r
#define HID_EPSIZE 8\r
\r
- /** Descriptor header type value, to indicate a HID class HID descriptor. */\r
- #define DTYPE_HID 0x21\r
- \r
- /** Descriptor header type value, to indicate a HID class HID report descriptor. */\r
- #define DTYPE_Report 0x22\r
-\r
/* Function Prototypes: */\r
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)\r
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);\r
arising out of or in connection with the use or performance of\r
this software.\r
*/\r
-\r
-/** \file\r
- *\r
- * Main source file for the KeyboardMouse demo. This file contains the main tasks of the demo and\r
- * is responsible for the initial application hardware configuration.\r
- */\r
\r
#include "KeyboardMouse.h"\r
\r
-/* Scheduler Task List */\r
-TASK_LIST\r
-{\r
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },\r
- { .Task = USB_Mouse , .TaskStatus = TASK_RUN },\r
- { .Task = USB_Keyboard , .TaskStatus = TASK_RUN },\r
-};\r
+USB_ClassInfo_HID_t Keyboard_HID_Interface =\r
+ {\r
+ .InterfaceNumber = 0,\r
+\r
+ .ReportINEndpointNumber = KEYBOARD_IN_EPNUM,\r
+ .ReportINEndpointSize = HID_EPSIZE,\r
+\r
+ .ReportOUTEndpointNumber = KEYBOARD_OUT_EPNUM,\r
+ .ReportOUTEndpointSize = HID_EPSIZE,\r
+ \r
+ .ReportBufferSize = sizeof(USB_KeyboardReport_Data_t),\r
+\r
+ .IdleCount = 500,\r
+ };\r
+ \r
+USB_ClassInfo_HID_t Mouse_HID_Interface =\r
+ {\r
+ .InterfaceNumber = 0,\r
\r
-/* Global Variables */\r
-/** Global structure to hold the current keyboard interface HID report, for transmission to the host */\r
-USB_KeyboardReport_Data_t KeyboardReportData;\r
+ .ReportINEndpointNumber = MOUSE_IN_EPNUM,\r
+ .ReportINEndpointSize = HID_EPSIZE,\r
\r
-/** Global structure to hold the current mouse interface HID report, for transmission to the host */\r
-USB_MouseReport_Data_t MouseReportData;\r
+ .ReportBufferSize = sizeof(USB_MouseReport_Data_t),\r
\r
-/** Main program entry point. This routine configures the hardware required by the application, then\r
- * starts the scheduler to run the USB management task.\r
- */\r
+ .ReportOUTEndpointNumber = 0,\r
+ .ReportOUTEndpointSize = 0,\r
+ };\r
+ \r
int main(void)\r
{\r
+ SetupHardware();\r
+\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
+\r
+ for (;;)\r
+ {\r
+ USB_HID_USBTask(&Keyboard_HID_Interface);\r
+ USB_HID_USBTask(&Mouse_HID_Interface);\r
+ USB_USBTask();\r
+ }\r
+}\r
+\r
+void SetupHardware()\r
+{\r
/* Disable watchdog if enabled by bootloader/fuses */\r
MCUSR &= ~(1 << WDRF);\r
wdt_disable();\r
/* Hardware Initialization */\r
Joystick_Init();\r
LEDs_Init();\r
- \r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
- \r
- /* Initialize Scheduler so that it can be used */\r
- Scheduler_Init();\r
-\r
- /* Initialize USB Subsystem */\r
- USB_Init();\r
- \r
- /* Scheduling - routine never returns, so put this last in the main function */\r
- Scheduler_Start();\r
+ USB_Init(); \r
}\r
\r
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and\r
- * starts the library USB task to begin the enumeration and USB management process.\r
- */\r
void EVENT_USB_Connect(void)\r
{\r
- /* Start USB management task */\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);\r
-\r
- /* Indicate USB enumerating */\r
- UpdateStatus(Status_USBEnumerating);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);\r
}\r
\r
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via\r
- * the status LEDs and stops the USB management task.\r
- */\r
void EVENT_USB_Disconnect(void)\r
{\r
- /* Stop running HID reporting and USB management tasks */\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);\r
-\r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
}\r
\r
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host sets the current configuration\r
- * of the USB device after enumeration, and configures the keyboard and mouse device endpoints.\r
- */\r
void EVENT_USB_ConfigurationChanged(void)\r
{\r
- /* Setup Keyboard Report Endpoint */\r
- Endpoint_ConfigureEndpoint(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT,\r
- ENDPOINT_DIR_IN, HID_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- /* Setup Keyboard LED Report Endpoint */\r
- Endpoint_ConfigureEndpoint(KEYBOARD_OUT_EPNUM, EP_TYPE_INTERRUPT,\r
- ENDPOINT_DIR_OUT, HID_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
\r
- /* Setup Mouse Report Endpoint */\r
- Endpoint_ConfigureEndpoint(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT,\r
- ENDPOINT_DIR_IN, HID_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- /* Indicate USB connected and ready */\r
- UpdateStatus(Status_USBReady);\r
+ if (!(USB_HID_ConfigureEndpoints(&Keyboard_HID_Interface)))\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
+ \r
+ if (!(USB_HID_ConfigureEndpoints(&Mouse_HID_Interface)))\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
}\r
\r
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific\r
- * control requests that are not handled internally by the USB library (including the HID commands, which are\r
- * all issued via the control endpoint), so that they can be handled appropriately for the application.\r
- */\r
void EVENT_USB_UnhandledControlPacket(void)\r
{\r
- uint8_t* ReportData;\r
- uint8_t ReportSize;\r
-\r
- /* Handle HID Class specific requests */\r
- switch (USB_ControlRequest.bRequest)\r
- {\r
- case REQ_GetReport:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- Endpoint_ClearSETUP();\r
- \r
- /* Determine if it is the mouse or the keyboard data that is being requested */\r
- if (!(USB_ControlRequest.wIndex))\r
- {\r
- ReportData = (uint8_t*)&KeyboardReportData;\r
- ReportSize = sizeof(KeyboardReportData);\r
- }\r
- else\r
- {\r
- ReportData = (uint8_t*)&MouseReportData;\r
- ReportSize = sizeof(MouseReportData);\r
- }\r
-\r
- /* Write the report data to the control endpoint */\r
- Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);\r
-\r
- /* Clear the report data afterwards */\r
- memset(ReportData, 0, ReportSize);\r
- \r
- /* Finalize the stream transfer to send the last packet or clear the host abort */\r
- Endpoint_ClearOUT();\r
- }\r
- \r
- break;\r
- case REQ_SetReport:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- Endpoint_ClearSETUP();\r
- \r
- /* Wait until the LED report has been sent by the host */\r
- while (!(Endpoint_IsOUTReceived()));\r
-\r
- /* Read in the LED report from the host */\r
- uint8_t LEDStatus = Endpoint_Read_Byte();\r
- uint8_t LEDMask = LEDS_LED2;\r
- \r
- if (LEDStatus & 0x01) // NUM Lock\r
- LEDMask |= LEDS_LED1;\r
- \r
- if (LEDStatus & 0x02) // CAPS Lock\r
- LEDMask |= LEDS_LED3;\r
-\r
- if (LEDStatus & 0x04) // SCROLL Lock\r
- LEDMask |= LEDS_LED4;\r
-\r
- /* Set the status LEDs to the current HID LED status */\r
- LEDs_SetAllLEDs(LEDMask);\r
-\r
- /* Clear the endpoint data */\r
- Endpoint_ClearOUT();\r
-\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
- }\r
- \r
- break;\r
- }\r
+ USB_HID_ProcessControlPacket(&Keyboard_HID_Interface);\r
+ USB_HID_ProcessControlPacket(&Mouse_HID_Interface);\r
}\r
\r
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to\r
- * log to a serial port, or anything else that is suitable for status updates.\r
- *\r
- * \param CurrentStatus Current status of the system, from the KeyboardMouse_StatusCodes_t enum\r
- */\r
-void UpdateStatus(uint8_t CurrentStatus)\r
+void EVENT_USB_StartOfFrame(void)\r
{\r
- uint8_t LEDMask = LEDS_NO_LEDS;\r
- \r
- /* Set the LED mask to the appropriate LED mask based on the given status code */\r
- switch (CurrentStatus)\r
- {\r
- case Status_USBNotReady:\r
- LEDMask = (LEDS_LED1);\r
- break;\r
- case Status_USBEnumerating:\r
- LEDMask = (LEDS_LED1 | LEDS_LED2);\r
- break;\r
- case Status_USBReady:\r
- LEDMask = (LEDS_LED2 | LEDS_LED4);\r
- break;\r
- }\r
- \r
- /* Set the board LEDs to the new LED mask */\r
- LEDs_SetAllLEDs(LEDMask);\r
+ USB_HID_RegisterStartOfFrame(&Keyboard_HID_Interface);\r
+ USB_HID_RegisterStartOfFrame(&Mouse_HID_Interface);\r
}\r
\r
-/** Keyboard task. This generates the next keyboard HID report for the host, and transmits it via the\r
- * keyboard IN endpoint when the host is ready for more data. Additionally, it processes host LED status\r
- * reports sent to the device via the keyboard OUT reporting endpoint.\r
- */\r
-TASK(USB_Keyboard)\r
+uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData)\r
{\r
- uint8_t JoyStatus_LCL = Joystick_GetStatus();\r
+ uint8_t JoyStatus_LCL = Joystick_GetStatus();\r
+ uint8_t ButtonStatus_LCL = Buttons_GetStatus();\r
\r
- /* Check if board button is not pressed, if so mouse mode enabled */\r
- if (!(Buttons_GetStatus() & BUTTONS_BUTTON1))\r
+ if (HIDInterfaceInfo == &Keyboard_HID_Interface)\r
{\r
+ USB_KeyboardReport_Data_t* KeyboardReport = (USB_KeyboardReport_Data_t*)ReportData;\r
+ \r
+ /* If first board button not being held down, no keyboard report */\r
+ if (!(ButtonStatus_LCL & BUTTONS_BUTTON1))\r
+ return 0;\r
+ \r
if (JoyStatus_LCL & JOY_UP)\r
- KeyboardReportData.KeyCode[0] = 0x04; // A\r
+ KeyboardReport->KeyCode[0] = 0x04; // A\r
else if (JoyStatus_LCL & JOY_DOWN)\r
- KeyboardReportData.KeyCode[0] = 0x05; // B\r
+ KeyboardReport->KeyCode[0] = 0x05; // B\r
\r
if (JoyStatus_LCL & JOY_LEFT)\r
- KeyboardReportData.KeyCode[0] = 0x06; // C\r
+ KeyboardReport->KeyCode[0] = 0x06; // C\r
else if (JoyStatus_LCL & JOY_RIGHT)\r
- KeyboardReportData.KeyCode[0] = 0x07; // D\r
+ KeyboardReport->KeyCode[0] = 0x07; // D\r
\r
if (JoyStatus_LCL & JOY_PRESS)\r
- KeyboardReportData.KeyCode[0] = 0x08; // E\r
+ KeyboardReport->KeyCode[0] = 0x08; // E\r
+ \r
+ return sizeof(USB_KeyboardReport_Data_t);\r
}\r
- \r
- /* Check if the USB system is connected to a host and report protocol mode is enabled */\r
- if (USB_IsConnected)\r
+ else\r
{\r
- /* Select the Keyboard Report Endpoint */\r
- Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);\r
-\r
- /* Check if Keyboard Endpoint Ready for Read/Write */\r
- if (Endpoint_IsReadWriteAllowed())\r
- {\r
- /* Write Keyboard Report Data */\r
- Endpoint_Write_Stream_LE(&KeyboardReportData, sizeof(KeyboardReportData));\r
-\r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearIN();\r
-\r
- /* Clear the report data afterwards */\r
- memset(&KeyboardReportData, 0, sizeof(KeyboardReportData));\r
- }\r
+ USB_MouseReport_Data_t* MouseReport = (USB_MouseReport_Data_t*)ReportData;\r
\r
- /* Select the Keyboard LED Report Endpoint */\r
- Endpoint_SelectEndpoint(KEYBOARD_OUT_EPNUM);\r
-\r
- /* Check if Keyboard LED Endpoint Ready for Read/Write */\r
- if (Endpoint_IsReadWriteAllowed())\r
- { \r
- /* Read in the LED report from the host */\r
- uint8_t LEDStatus = Endpoint_Read_Byte();\r
- uint8_t LEDMask = LEDS_LED2;\r
- \r
- if (LEDStatus & 0x01) // NUM Lock\r
- LEDMask |= LEDS_LED1;\r
- \r
- if (LEDStatus & 0x02) // CAPS Lock\r
- LEDMask |= LEDS_LED3;\r
-\r
- if (LEDStatus & 0x04) // SCROLL Lock\r
- LEDMask |= LEDS_LED4;\r
-\r
- /* Set the status LEDs to the current Keyboard LED status */\r
- LEDs_SetAllLEDs(LEDMask);\r
-\r
- /* Handshake the OUT Endpoint - clear endpoint and ready for next report */\r
- Endpoint_ClearOUT();\r
- }\r
- }\r
-}\r
-\r
-/** Mouse task. This generates the next mouse HID report for the host, and transmits it via the\r
- * mouse IN endpoint when the host is ready for more data.\r
- */\r
-TASK(USB_Mouse)\r
-{\r
- uint8_t JoyStatus_LCL = Joystick_GetStatus();\r
-\r
- /* Check if board button is pressed, if so mouse mode enabled */\r
- if (Buttons_GetStatus() & BUTTONS_BUTTON1)\r
- {\r
+ /* If first board button being held down, no mouse report */\r
+ if (ButtonStatus_LCL & BUTTONS_BUTTON1)\r
+ return 0;\r
+ \r
if (JoyStatus_LCL & JOY_UP)\r
- MouseReportData.Y = 1;\r
+ MouseReport->Y = -1;\r
else if (JoyStatus_LCL & JOY_DOWN)\r
- MouseReportData.Y = -1;\r
+ MouseReport->Y = 1;\r
\r
if (JoyStatus_LCL & JOY_RIGHT)\r
- MouseReportData.X = 1;\r
+ MouseReport->X = 1;\r
else if (JoyStatus_LCL & JOY_LEFT)\r
- MouseReportData.X = -1;\r
+ MouseReport->X = -1;\r
\r
if (JoyStatus_LCL & JOY_PRESS)\r
- MouseReportData.Button = (1 << 0);\r
+ MouseReport->Button = (1 << 0);\r
+ \r
+ return sizeof(USB_MouseReport_Data_t); \r
}\r
+}\r
\r
- /* Check if the USB system is connected to a host and report protocol mode is enabled */\r
- if (USB_IsConnected)\r
+void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize)\r
+{\r
+ if (HIDInterfaceInfo == &Keyboard_HID_Interface)\r
{\r
- /* Select the Mouse Report Endpoint */\r
- Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);\r
-\r
- /* Check if Mouse Endpoint Ready for Read/Write */\r
- if (Endpoint_IsReadWriteAllowed())\r
- {\r
- /* Write Mouse Report Data */\r
- Endpoint_Write_Stream_LE(&MouseReportData, sizeof(MouseReportData));\r
+ uint8_t LEDMask = LEDS_NO_LEDS;\r
+ uint8_t* LEDReport = (uint8_t*)ReportData;\r
\r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearIN();\r
+ if (*LEDReport & 0x01) // NUM Lock\r
+ LEDMask |= LEDS_LED1;\r
+ \r
+ if (*LEDReport & 0x02) // CAPS Lock\r
+ LEDMask |= LEDS_LED3;\r
\r
- /* Clear the report data afterwards */\r
- memset(&MouseReportData, 0, sizeof(MouseReportData));\r
- }\r
+ if (*LEDReport & 0x04) // SCROLL Lock\r
+ LEDMask |= LEDS_LED4;\r
+ \r
+ LEDs_SetAllLEDs(LEDMask);\r
}\r
-}\r
+}
\ No newline at end of file
\r
#include "Descriptors.h"\r
\r
- #include <LUFA/Version.h> // Library Version Information\r
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
- #include <LUFA/Drivers/Board/Joystick.h> // Joystick driver\r
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver\r
- #include <LUFA/Drivers/Board/Buttons.h> // Board Buttons driver\r
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management\r
- \r
- /* Task Definitions: */\r
- TASK(USB_Keyboard);\r
- TASK(USB_Mouse);\r
+ #include <LUFA/Version.h>\r
+ #include <LUFA/Drivers/Board/Joystick.h>\r
+ #include <LUFA/Drivers/Board/LEDs.h>\r
+ #include <LUFA/Drivers/Board/Buttons.h>\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>\r
\r
- /* Enums: */\r
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */\r
- enum KeyboardMouse_StatusCodes_t\r
- {\r
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */\r
- Status_USBEnumerating = 1, /**< USB interface is enumerating */\r
- Status_USBReady = 2, /**< USB interface is connected and ready */\r
- };\r
- \r
/* Macros: */\r
- /** HID Class specific request to get the next HID report from the device. */\r
- #define REQ_GetReport 0x01\r
-\r
- /** HID Class specific request to send the next HID report to the device. */\r
- #define REQ_SetReport 0x09\r
-\r
- /** HID Class specific request to get the current HID protocol in use, either report or boot. */\r
- #define REQ_GetProtocol 0x03\r
-\r
- /** HID Class specific request to set the current HID protocol in use, either report or boot. */\r
- #define REQ_SetProtocol 0x0B\r
+ #define LEDMASK_USB_NOTREADY LEDS_LED1\r
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)\r
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)\r
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)\r
\r
/* Type Defines: */\r
/** Type define for the keyboard HID report structure, for creating and sending HID reports to the host PC.\r
} USB_MouseReport_Data_t;\r
\r
/* Function Prototypes: */\r
+ void SetupHardware(void);\r
+\r
void EVENT_USB_Connect(void);\r
void EVENT_USB_Disconnect(void);\r
void EVENT_USB_ConfigurationChanged(void);\r
void EVENT_USB_UnhandledControlPacket(void);\r
+ void EVENT_USB_StartOfFrame(void);\r
\r
- void UpdateStatus(uint8_t CurrentStatus);\r
+ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);\r
+ void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo,\r
+ void* ReportData, uint16_t ReportSize);\r
\r
#endif\r
# List C source files here. (C dependencies are automatically generated.)\r
SRC = $(TARGET).c \\r
Descriptors.c \\r
- $(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Endpoint.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Host.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \\r
- $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \\r
+ $(LUFA_PATH)/LUFA/Drivers/USB/Class/Device/HID.c \\r
\r
\r
# List C++ source files here. (C dependencies are automatically generated.)\r
\r
# Place -D or -U options here for C sources\r
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)\r
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY\r
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY\r
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION\r
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"\r
\r
\r
# Place -D or -U options here for C sources\r
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)\r
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY\r
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY\r
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION\r
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"\r
\r
* \param BlockAddress Data block starting address for the write sequence\r
* \param TotalBlocks Number of blocks of data to write\r
*/\r
-void DataflashManager_WriteBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks)\r
+void DataflashManager_WriteBlocks(USB_ClassInfo_MS_t* MSInterfaceInfo, const uint32_t BlockAddress, uint16_t TotalBlocks)\r
{\r
uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);\r
uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
BytesInBlockDiv16++;\r
\r
/* Check if the current command is being aborted by the host */\r
- if (IsMassStoreReset)\r
+ if (MSInterfaceInfo->IsMassStoreReset)\r
return; \r
}\r
\r
* \param BlockAddress Data block starting address for the read sequence\r
* \param TotalBlocks Number of blocks of data to read\r
*/\r
-void DataflashManager_ReadBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks)\r
+void DataflashManager_ReadBlocks(USB_ClassInfo_MS_t* MSInterfaceInfo, const uint32_t BlockAddress, uint16_t TotalBlocks)\r
{\r
uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);\r
uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
BytesInBlockDiv16++;\r
\r
/* Check if the current command is being aborted by the host */\r
- if (IsMassStoreReset)\r
+ if (MSInterfaceInfo->IsMassStoreReset)\r
return;\r
}\r
\r
CurrDFPageByteDiv16++;\r
\r
/* Increment the block 16 byte block counter */\r
- BytesInBlockDiv16++;\r
-\r
- /* Check if the current command is being aborted by the host */\r
- if (IsMassStoreReset)\r
- return; \r
+ BytesInBlockDiv16++; \r
}\r
\r
/* Decrement the blocks remaining counter and reset the sub block counter */\r
\r
/* Increment the block 16 byte block counter */\r
BytesInBlockDiv16++;\r
-\r
- /* Check if the current command is being aborted by the host */\r
- if (IsMassStoreReset)\r
- return;\r
}\r
\r
/* Decrement the blocks remaining counter */\r
#define VIRTUAL_MEMORY_BLOCKS (VIRTUAL_MEMORY_BYTES / VIRTUAL_MEMORY_BLOCK_SIZE)\r
\r
/* Function Prototypes: */\r
- void DataflashManager_WriteBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks);\r
- void DataflashManager_ReadBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks);\r
+ void DataflashManager_WriteBlocks(USB_ClassInfo_MS_t* MSInterfaceInfo, const uint32_t BlockAddress, uint16_t TotalBlocks);\r
+ void DataflashManager_ReadBlocks(USB_ClassInfo_MS_t* MSInterfaceInfo, const uint32_t BlockAddress, uint16_t TotalBlocks);\r
void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks,\r
uint8_t* BufferPtr) ATTR_NON_NULL_PTR_ARG(3);\r
void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks,\r
* to the appropriate SCSI command handling routine if the issued command is supported by the device, else it returns\r
* a command failure due to a ILLEGAL REQUEST.\r
*/\r
-void SCSI_DecodeSCSICommand(void)\r
+bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_t* MSInterfaceInfo)\r
{\r
bool CommandSuccess = false;\r
\r
/* Run the appropriate SCSI command hander function based on the passed command */\r
- switch (CommandBlock.SCSICommandData[0])\r
+ switch (MSInterfaceInfo->CommandBlock.SCSICommandData[0])\r
{\r
case SCSI_CMD_INQUIRY:\r
- CommandSuccess = SCSI_Command_Inquiry(); \r
+ CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo); \r
break;\r
case SCSI_CMD_REQUEST_SENSE:\r
- CommandSuccess = SCSI_Command_Request_Sense();\r
+ CommandSuccess = SCSI_Command_Request_Sense(MSInterfaceInfo);\r
break;\r
case SCSI_CMD_READ_CAPACITY_10:\r
- CommandSuccess = SCSI_Command_Read_Capacity_10(); \r
+ CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo); \r
break;\r
case SCSI_CMD_SEND_DIAGNOSTIC:\r
- CommandSuccess = SCSI_Command_Send_Diagnostic();\r
+ CommandSuccess = SCSI_Command_Send_Diagnostic(MSInterfaceInfo);\r
break;\r
case SCSI_CMD_WRITE_10:\r
- CommandSuccess = SCSI_Command_ReadWrite_10(DATA_WRITE);\r
+ CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);\r
break;\r
case SCSI_CMD_READ_10:\r
- CommandSuccess = SCSI_Command_ReadWrite_10(DATA_READ);\r
+ CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);\r
break;\r
case SCSI_CMD_TEST_UNIT_READY:\r
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:\r
case SCSI_CMD_VERIFY_10:\r
/* These commands should just succeed, no handling required */\r
CommandSuccess = true;\r
- CommandBlock.DataTransferLength = 0;\r
+ MSInterfaceInfo->CommandBlock.DataTransferLength = 0;\r
break;\r
default:\r
/* Update the SENSE key to reflect the invalid command */\r
SCSI_ASENSEQ_NO_QUALIFIER);\r
break;\r
}\r
- \r
+\r
/* Check if command was successfully processed */\r
if (CommandSuccess)\r
{\r
- /* Command succeeded - set the CSW status and update the SENSE key */\r
- CommandStatus.Status = Command_Pass;\r
- \r
SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,\r
SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,\r
- SCSI_ASENSEQ_NO_QUALIFIER); \r
- }\r
- else\r
- {\r
- /* Command failed - set the CSW status - failed command function updates the SENSE key */\r
- CommandStatus.Status = Command_Fail;\r
+ SCSI_ASENSEQ_NO_QUALIFIER);\r
+ \r
+ return true;\r
}\r
+\r
+ return false;\r
}\r
\r
/** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features\r
*\r
* \return Boolean true if the command completed successfully, false otherwise.\r
*/\r
-static bool SCSI_Command_Inquiry(void)\r
+static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_t* MSInterfaceInfo)\r
{\r
- uint16_t AllocationLength = (((uint16_t)CommandBlock.SCSICommandData[3] << 8) |\r
- CommandBlock.SCSICommandData[4]);\r
+ uint16_t AllocationLength = (((uint16_t)MSInterfaceInfo->CommandBlock.SCSICommandData[3] << 8) |\r
+ MSInterfaceInfo->CommandBlock.SCSICommandData[4]);\r
uint16_t BytesTransferred = (AllocationLength < sizeof(InquiryData))? AllocationLength :\r
sizeof(InquiryData);\r
\r
/* Only the standard INQUIRY data is supported, check if any optional INQUIRY bits set */\r
- if ((CommandBlock.SCSICommandData[1] & ((1 << 0) | (1 << 1))) ||\r
- CommandBlock.SCSICommandData[2])\r
+ if ((MSInterfaceInfo->CommandBlock.SCSICommandData[1] & ((1 << 0) | (1 << 1))) ||\r
+ MSInterfaceInfo->CommandBlock.SCSICommandData[2])\r
{\r
/* Optional but unsupported bits set - update the SENSE key and fail the request */\r
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,\r
\r
return false;\r
}\r
-\r
- /* Write the INQUIRY data to the endpoint */\r
- Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, StreamCallback_AbortOnMassStoreReset);\r
+ \r
+ Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NO_STREAM_CALLBACK);\r
\r
uint8_t PadBytes[AllocationLength - BytesTransferred];\r
\r
/* Pad out remaining bytes with 0x00 */\r
- Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), StreamCallback_AbortOnMassStoreReset);\r
+ Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), NO_STREAM_CALLBACK);\r
\r
/* Finalize the stream transfer to send the last packet */\r
Endpoint_ClearIN();\r
\r
/* Succeed the command and update the bytes transferred counter */\r
- CommandBlock.DataTransferLength -= BytesTransferred;\r
+ MSInterfaceInfo->CommandBlock.DataTransferLength -= BytesTransferred;\r
\r
return true;\r
}\r
*\r
* \return Boolean true if the command completed successfully, false otherwise.\r
*/\r
-static bool SCSI_Command_Request_Sense(void)\r
+static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_t* MSInterfaceInfo)\r
{\r
- uint8_t AllocationLength = CommandBlock.SCSICommandData[4];\r
+ uint8_t AllocationLength = MSInterfaceInfo->CommandBlock.SCSICommandData[4];\r
uint8_t BytesTransferred = (AllocationLength < sizeof(SenseData))? AllocationLength : sizeof(SenseData);\r
\r
- /* Send the SENSE data - this indicates to the host the status of the last command */\r
- Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, StreamCallback_AbortOnMassStoreReset);\r
- \r
uint8_t PadBytes[AllocationLength - BytesTransferred];\r
- \r
- /* Pad out remaining bytes with 0x00 */\r
- Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), StreamCallback_AbortOnMassStoreReset);\r
\r
- /* Finalize the stream transfer to send the last packet */\r
+ Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, NO_STREAM_CALLBACK);\r
+ Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), NO_STREAM_CALLBACK);\r
Endpoint_ClearIN();\r
\r
/* Succeed the command and update the bytes transferred counter */\r
- CommandBlock.DataTransferLength -= BytesTransferred;\r
+ MSInterfaceInfo->CommandBlock.DataTransferLength -= BytesTransferred;\r
\r
return true;\r
}\r
*\r
* \return Boolean true if the command completed successfully, false otherwise.\r
*/\r
-static bool SCSI_Command_Read_Capacity_10(void)\r
+static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_t* MSInterfaceInfo)\r
{\r
- /* Send the total number of logical blocks in the current LUN */\r
- Endpoint_Write_DWord_BE(LUN_MEDIA_BLOCKS - 1);\r
+ uint32_t TotalLUNs = (LUN_MEDIA_BLOCKS - 1);\r
+ uint32_t MediaBlockSize = VIRTUAL_MEMORY_BLOCK_SIZE;\r
\r
- /* Send the logical block size of the device (must be 512 bytes) */\r
- Endpoint_Write_DWord_BE(VIRTUAL_MEMORY_BLOCK_SIZE);\r
-\r
- /* Check if the current command is being aborted by the host */\r
- if (IsMassStoreReset)\r
- return false;\r
-\r
- /* Send the endpoint data packet to the host */\r
+ Endpoint_Write_Stream_BE(&TotalLUNs, sizeof(TotalLUNs), NO_STREAM_CALLBACK);\r
+ Endpoint_Write_Stream_BE(&MediaBlockSize, sizeof(MediaBlockSize), NO_STREAM_CALLBACK);\r
Endpoint_ClearIN();\r
-\r
+ \r
/* Succeed the command and update the bytes transferred counter */\r
- CommandBlock.DataTransferLength -= 8;\r
+ MSInterfaceInfo->CommandBlock.DataTransferLength -= 8;\r
\r
return true;\r
}\r
*\r
* \return Boolean true if the command completed successfully, false otherwise.\r
*/\r
-static bool SCSI_Command_Send_Diagnostic(void)\r
+static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_t* MSInterfaceInfo)\r
{\r
uint8_t ReturnByte;\r
\r
/* Check to see if the SELF TEST bit is not set */\r
- if (!(CommandBlock.SCSICommandData[1] & (1 << 2)))\r
+ if (!(MSInterfaceInfo->CommandBlock.SCSICommandData[1] & (1 << 2)))\r
{\r
/* Only self-test supported - update SENSE key and fail the command */\r
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,\r
#endif\r
\r
/* Succeed the command and update the bytes transferred counter */\r
- CommandBlock.DataTransferLength = 0;\r
+ MSInterfaceInfo->CommandBlock.DataTransferLength = 0;\r
\r
return true;\r
}\r
*\r
* \return Boolean true if the command completed successfully, false otherwise.\r
*/\r
-static bool SCSI_Command_ReadWrite_10(const bool IsDataRead)\r
+static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_t* MSInterfaceInfo, const bool IsDataRead)\r
{\r
uint32_t BlockAddress;\r
uint16_t TotalBlocks;\r
\r
/* Load in the 32-bit block address (SCSI uses big-endian, so have to do it byte-by-byte) */\r
- ((uint8_t*)&BlockAddress)[3] = CommandBlock.SCSICommandData[2];\r
- ((uint8_t*)&BlockAddress)[2] = CommandBlock.SCSICommandData[3];\r
- ((uint8_t*)&BlockAddress)[1] = CommandBlock.SCSICommandData[4];\r
- ((uint8_t*)&BlockAddress)[0] = CommandBlock.SCSICommandData[5];\r
+ ((uint8_t*)&BlockAddress)[3] = MSInterfaceInfo->CommandBlock.SCSICommandData[2];\r
+ ((uint8_t*)&BlockAddress)[2] = MSInterfaceInfo->CommandBlock.SCSICommandData[3];\r
+ ((uint8_t*)&BlockAddress)[1] = MSInterfaceInfo->CommandBlock.SCSICommandData[4];\r
+ ((uint8_t*)&BlockAddress)[0] = MSInterfaceInfo->CommandBlock.SCSICommandData[5];\r
\r
/* Load in the 16-bit total blocks (SCSI uses big-endian, so have to do it byte-by-byte) */\r
- ((uint8_t*)&TotalBlocks)[1] = CommandBlock.SCSICommandData[7];\r
- ((uint8_t*)&TotalBlocks)[0] = CommandBlock.SCSICommandData[8];\r
+ ((uint8_t*)&TotalBlocks)[1] = MSInterfaceInfo->CommandBlock.SCSICommandData[7];\r
+ ((uint8_t*)&TotalBlocks)[0] = MSInterfaceInfo->CommandBlock.SCSICommandData[8];\r
\r
/* Check if the block address is outside the maximum allowable value for the LUN */\r
if (BlockAddress >= LUN_MEDIA_BLOCKS)\r
\r
#if (TOTAL_LUNS > 1)\r
/* Adjust the given block address to the real media address based on the selected LUN */\r
- BlockAddress += ((uint32_t)CommandBlock.LUN * LUN_MEDIA_BLOCKS);\r
+ BlockAddress += ((uint32_t)MSInterfaceInfo->CommandBlock.LUN * LUN_MEDIA_BLOCKS);\r
#endif\r
\r
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */\r
if (IsDataRead == DATA_READ)\r
- DataflashManager_ReadBlocks(BlockAddress, TotalBlocks);\r
+ DataflashManager_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);\r
else\r
- DataflashManager_WriteBlocks(BlockAddress, TotalBlocks);\r
+ DataflashManager_WriteBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);\r
\r
/* Update the bytes transferred counter and succeed the command */\r
- CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);\r
+ MSInterfaceInfo->CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);\r
\r
return true;\r
}\r
#include <avr/io.h>\r
#include <avr/pgmspace.h>\r
\r
- #include <LUFA/Common/Common.h> // Function Attribute, Atomic, Debug and ISR Macros\r
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/MassStorage.h>\r
\r
#include "MassStorage.h"\r
#include "Descriptors.h"\r
SenseData.AdditionalSenseQualifier = aqual; }MACROE\r
\r
/** Macro for the SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */\r
- #define DATA_READ true\r
+ #define DATA_READ true\r
\r
/** Macro for the SCSI_Command_ReadWrite_10() function, to indicate that data is to be written to the storage medium. */\r
- #define DATA_WRITE false\r
+ #define DATA_WRITE false\r
\r
/** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a Block Media device. */\r
- #define DEVICE_TYPE_BLOCK 0x00\r
+ #define DEVICE_TYPE_BLOCK 0x00\r
\r
/** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a CD-ROM device. */\r
- #define DEVICE_TYPE_CDROM 0x05\r
+ #define DEVICE_TYPE_CDROM 0x05\r
\r
/* Type Defines: */\r
/** Type define for a SCSI response structure to a SCSI INQUIRY command. For details of the\r
} SCSI_Request_Sense_Response_t;\r
\r
/* Function Prototypes: */\r
- void SCSI_DecodeSCSICommand(void);\r
+ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_t* MSInterfaceInfo);\r
\r
#if defined(INCLUDE_FROM_SCSI_C)\r
- static bool SCSI_Command_Inquiry(void);\r
- static bool SCSI_Command_Request_Sense(void);\r
- static bool SCSI_Command_Read_Capacity_10(void);\r
- static bool SCSI_Command_Send_Diagnostic(void);\r
- static bool SCSI_Command_ReadWrite_10(const bool IsDataRead);\r
+ static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_t* MSInterfaceInfo);\r
+ static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_t* MSInterfaceInfo);\r
+ static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_t* MSInterfaceInfo);\r
+ static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_t* MSInterfaceInfo);\r
+ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_t* MSInterfaceInfo, const bool IsDataRead);\r
#endif\r
\r
#endif\r
this software.\r
*/\r
\r
-/** \file\r
- *\r
- * Main source file for the Mass Storage demo. This file contains the main tasks of the demo and\r
- * is responsible for the initial application hardware configuration.\r
- */\r
-\r
-#define INCLUDE_FROM_MASSSTORAGE_C\r
#include "MassStorage.h"\r
\r
-/* Scheduler Task List */\r
-TASK_LIST\r
-{\r
- { .Task = USB_MassStorage , .TaskStatus = TASK_STOP },\r
-};\r
+USB_ClassInfo_MS_t Disk_MS_Interface =\r
+ {\r
+ .InterfaceNumber = 0,\r
\r
-/* Global Variables */\r
-/** Structure to hold the latest Command Block Wrapper issued by the host, containing a SCSI command to execute. */\r
-CommandBlockWrapper_t CommandBlock;\r
+ .DataINEndpointNumber = MASS_STORAGE_IN_EPNUM,\r
+ .DataINEndpointSize = MASS_STORAGE_IO_EPSIZE,\r
\r
-/** Structure to hold the latest Command Status Wrapper to return to the host, containing the status of the last issued command. */\r
-CommandStatusWrapper_t CommandStatus = { .Signature = CSW_SIGNATURE };\r
+ .DataOUTEndpointNumber = MASS_STORAGE_OUT_EPNUM,\r
+ .DataOUTEndpointSize = MASS_STORAGE_IO_EPSIZE,\r
\r
-/** Flag to asynchronously abort any in-progress data transfers upon the reception of a mass storage reset command. */\r
-volatile bool IsMassStoreReset = false;\r
+ .TotalLUNs = TOTAL_LUNS,\r
+ };\r
\r
-/** Main program entry point. This routine configures the hardware required by the application, then\r
- * starts the scheduler to run the application tasks.\r
- */\r
int main(void)\r
{\r
+ SetupHardware();\r
+\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
+\r
+ for (;;)\r
+ {\r
+ USB_MS_USBTask(&Disk_MS_Interface);\r
+ USB_USBTask();\r
+ }\r
+}\r
+\r
+void SetupHardware(void)\r
+{\r
/* Disable watchdog if enabled by bootloader/fuses */\r
MCUSR &= ~(1 << WDRF);\r
wdt_disable();\r
/* Hardware Initialization */\r
LEDs_Init();\r
Dataflash_Init(SPI_SPEED_FCPU_DIV_2);\r
+ USB_Init();\r
\r
/* Clear Dataflash sector protections, if enabled */\r
DataflashManager_ResetDataflashProtections();\r
- \r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
- \r
- /* Initialize Scheduler so that it can be used */\r
- Scheduler_Init();\r
-\r
- /* Initialize USB Subsystem */\r
- USB_Init();\r
-\r
- /* Scheduling - routine never returns, so put this last in the main function */\r
- Scheduler_Start();\r
}\r
\r
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */\r
void EVENT_USB_Connect(void)\r
{\r
- /* Indicate USB enumerating */\r
- UpdateStatus(Status_USBEnumerating);\r
- \r
- /* Reset the MSReset flag upon connection */\r
- IsMassStoreReset = false;\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);\r
}\r
\r
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via\r
- * the status LEDs and stops the Mass Storage management task.\r
- */\r
void EVENT_USB_Disconnect(void)\r
{\r
- /* Stop running mass storage task */\r
- Scheduler_SetTaskMode(USB_MassStorage, TASK_STOP);\r
-\r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
}\r
\r
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration\r
- * of the USB device after enumeration - the device endpoints are configured and the Mass Storage management task started.\r
- */\r
void EVENT_USB_ConfigurationChanged(void)\r
{\r
- /* Setup Mass Storage In and Out Endpoints */\r
- Endpoint_ConfigureEndpoint(MASS_STORAGE_IN_EPNUM, EP_TYPE_BULK,\r
- ENDPOINT_DIR_IN, MASS_STORAGE_IO_EPSIZE,\r
- ENDPOINT_BANK_DOUBLE);\r
-\r
- Endpoint_ConfigureEndpoint(MASS_STORAGE_OUT_EPNUM, EP_TYPE_BULK,\r
- ENDPOINT_DIR_OUT, MASS_STORAGE_IO_EPSIZE,\r
- ENDPOINT_BANK_DOUBLE);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
\r
- /* Indicate USB connected and ready */\r
- UpdateStatus(Status_USBReady);\r
- \r
- /* Start mass storage task */\r
- Scheduler_SetTaskMode(USB_MassStorage, TASK_RUN);\r
+ if (!(USB_MS_ConfigureEndpoints(&Disk_MS_Interface)))\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
}\r
\r
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific\r
- * control requests that are not handled internally by the USB library (including the Mass Storage class-specific\r
- * requests) so that they can be handled appropriately for the application.\r
- */\r
void EVENT_USB_UnhandledControlPacket(void)\r
{\r
- /* Process UFI specific control requests */\r
- switch (USB_ControlRequest.bRequest)\r
- {\r
- case REQ_MassStorageReset:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- Endpoint_ClearSETUP();\r
-\r
- /* Indicate that the current transfer should be aborted */\r
- IsMassStoreReset = true; \r
-\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
- }\r
-\r
- break;\r
- case REQ_GetMaxLUN:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- Endpoint_ClearSETUP();\r
-\r
- /* Indicate to the host the number of supported LUNs (virtual disks) on the device */\r
- Endpoint_Write_Byte(TOTAL_LUNS - 1);\r
- \r
- Endpoint_ClearIN();\r
- \r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
- }\r
- \r
- break;\r
- }\r
-}\r
-\r
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to\r
- * log to a serial port, or anything else that is suitable for status updates.\r
- *\r
- * \param CurrentStatus Current status of the system, from the MassStorage_StatusCodes_t enum\r
- */\r
-void UpdateStatus(uint8_t CurrentStatus)\r
-{\r
- uint8_t LEDMask = LEDS_NO_LEDS;\r
- \r
- /* Set the LED mask to the appropriate LED mask based on the given status code */\r
- switch (CurrentStatus)\r
- {\r
- case Status_USBNotReady:\r
- LEDMask = (LEDS_LED1);\r
- break;\r
- case Status_USBEnumerating:\r
- LEDMask = (LEDS_LED1 | LEDS_LED2);\r
- break;\r
- case Status_USBReady:\r
- LEDMask = (LEDS_LED2 | LEDS_LED4);\r
- break;\r
- case Status_CommandBlockError:\r
- LEDMask = (LEDS_LED1);\r
- break;\r
- case Status_ProcessingCommandBlock:\r
- LEDMask = (LEDS_LED1 | LEDS_LED2);\r
- break;\r
- }\r
- \r
- /* Set the board LEDs to the new LED mask */\r
- LEDs_SetAllLEDs(LEDMask);\r
-}\r
-\r
-/** Task to manage the Mass Storage interface, reading in Command Block Wrappers from the host, processing the SCSI commands they\r
- * contain, and returning Command Status Wrappers back to the host to indicate the success or failure of the last issued command.\r
- */\r
-TASK(USB_MassStorage)\r
-{\r
- /* Check if the USB System is connected to a Host */\r
- if (USB_IsConnected)\r
- {\r
- /* Select the Data Out Endpoint */\r
- Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);\r
- \r
- /* Check to see if a command from the host has been issued */\r
- if (Endpoint_IsReadWriteAllowed())\r
- { \r
- /* Indicate busy */\r
- UpdateStatus(Status_ProcessingCommandBlock);\r
-\r
- /* Process sent command block from the host */\r
- if (ReadInCommandBlock())\r
- {\r
- /* Check direction of command, select Data IN endpoint if data is from the device */\r
- if (CommandBlock.Flags & COMMAND_DIRECTION_DATA_IN)\r
- Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);\r
-\r
- /* Decode the received SCSI command */\r
- SCSI_DecodeSCSICommand();\r
-\r
- /* Load in the CBW tag into the CSW to link them together */\r
- CommandStatus.Tag = CommandBlock.Tag;\r
-\r
- /* Load in the data residue counter into the CSW */\r
- CommandStatus.DataTransferResidue = CommandBlock.DataTransferLength;\r
-\r
- /* Stall the selected data pipe if command failed (if data is still to be transferred) */\r
- if ((CommandStatus.Status == Command_Fail) && (CommandStatus.DataTransferResidue))\r
- Endpoint_StallTransaction();\r
-\r
- /* Return command status block to the host */\r
- ReturnCommandStatus();\r
- \r
- /* Check if a Mass Storage Reset occurred */\r
- if (IsMassStoreReset)\r
- {\r
- /* Reset the data endpoint banks */\r
- Endpoint_ResetFIFO(MASS_STORAGE_OUT_EPNUM);\r
- Endpoint_ResetFIFO(MASS_STORAGE_IN_EPNUM);\r
- \r
- Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);\r
- Endpoint_ClearStall();\r
- Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);\r
- Endpoint_ClearStall();\r
-\r
- /* Clear the abort transfer flag */\r
- IsMassStoreReset = false;\r
- }\r
-\r
- /* Indicate ready */\r
- UpdateStatus(Status_USBReady);\r
- }\r
- else\r
- {\r
- /* Indicate error reading in the command block from the host */\r
- UpdateStatus(Status_CommandBlockError);\r
- }\r
- }\r
- }\r
-}\r
-\r
-/** Function to read in a command block from the host, via the bulk data OUT endpoint. This function reads in the next command block\r
- * if one has been issued, and performs validation to ensure that the block command is valid.\r
- *\r
- * \return Boolean true if a valid command block has been read in from the endpoint, false otherwise\r
- */\r
-static bool ReadInCommandBlock(void)\r
-{\r
- /* Select the Data Out endpoint */\r
- Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);\r
-\r
- /* Read in command block header */\r
- Endpoint_Read_Stream_LE(&CommandBlock, (sizeof(CommandBlock) - sizeof(CommandBlock.SCSICommandData)),\r
- StreamCallback_AbortOnMassStoreReset);\r
-\r
- /* Check if the current command is being aborted by the host */\r
- if (IsMassStoreReset)\r
- return false;\r
-\r
- /* Verify the command block - abort if invalid */\r
- if ((CommandBlock.Signature != CBW_SIGNATURE) ||\r
- (CommandBlock.LUN >= TOTAL_LUNS) ||\r
- (CommandBlock.SCSICommandLength > MAX_SCSI_COMMAND_LENGTH))\r
- {\r
- /* Stall both data pipes until reset by host */\r
- Endpoint_StallTransaction();\r
- Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);\r
- Endpoint_StallTransaction();\r
- \r
- return false;\r
- }\r
-\r
- /* Read in command block command data */\r
- Endpoint_Read_Stream_LE(&CommandBlock.SCSICommandData,\r
- CommandBlock.SCSICommandLength,\r
- StreamCallback_AbortOnMassStoreReset);\r
- \r
- /* Check if the current command is being aborted by the host */\r
- if (IsMassStoreReset)\r
- return false;\r
-\r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearOUT();\r
- \r
- return true;\r
+ USB_MS_ProcessControlPacket(&Disk_MS_Interface);\r
}\r
\r
-/** Returns the filled Command Status Wrapper back to the host via the bulk data IN endpoint, waiting for the host to clear any\r
- * stalled data endpoints as needed.\r
- */\r
-static void ReturnCommandStatus(void)\r
+bool CALLBACK_USB_MS_SCSICommandReceived(USB_ClassInfo_MS_t* MSInterfaceInfo)\r
{\r
- /* Select the Data Out endpoint */\r
- Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);\r
-\r
- /* While data pipe is stalled, wait until the host issues a control request to clear the stall */\r
- while (Endpoint_IsStalled())\r
- {\r
- /* Check if the current command is being aborted by the host */\r
- if (IsMassStoreReset)\r
- return;\r
- }\r
-\r
- /* Select the Data In endpoint */\r
- Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);\r
-\r
- /* While data pipe is stalled, wait until the host issues a control request to clear the stall */\r
- while (Endpoint_IsStalled())\r
- {\r
- /* Check if the current command is being aborted by the host */\r
- if (IsMassStoreReset)\r
- return;\r
- }\r
+ bool CommandSuccess;\r
\r
- /* Write the CSW to the endpoint */\r
- Endpoint_Write_Stream_LE(&CommandStatus, sizeof(CommandStatus),\r
- StreamCallback_AbortOnMassStoreReset);\r
- \r
- /* Check if the current command is being aborted by the host */\r
- if (IsMassStoreReset)\r
- return;\r
-\r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearIN();\r
-}\r
-\r
-/** Stream callback function for the Endpoint stream read and write functions. This callback will abort the current stream transfer\r
- * if a Mass Storage Reset request has been issued to the control endpoint.\r
- */\r
-uint8_t StreamCallback_AbortOnMassStoreReset(void)\r
-{ \r
- /* Abort if a Mass Storage reset command was received */\r
- if (IsMassStoreReset)\r
- return STREAMCALLBACK_Abort;\r
+ LEDs_SetAllLEDs(LEDMASK_USB_BUSY);\r
+ CommandSuccess = SCSI_DecodeSCSICommand(MSInterfaceInfo);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
\r
- /* Continue with the current stream operation */\r
- return STREAMCALLBACK_Continue;\r
+ return CommandSuccess;\r
}\r
#include "Lib/SCSI.h"\r
#include "Lib/DataflashManager.h"\r
\r
- #include <LUFA/Version.h> // Library Version Information\r
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver\r
- #include <LUFA/Drivers/Board/Dataflash.h> // Dataflash chip driver\r
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management\r
+ #include <LUFA/Version.h>\r
+ #include <LUFA/Drivers/Board/Joystick.h>\r
+ #include <LUFA/Drivers/Board/LEDs.h>\r
+ #include <LUFA/Drivers/Board/Buttons.h>\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/MassStorage.h>
\r
/* Macros: */\r
- /** Mass Storage Class specific request to reset the Mass Storage interface, ready for the next command. */\r
- #define REQ_MassStorageReset 0xFF\r
-\r
- /** Mass Storage Class specific request to retrieve the total number of Logical Units (drives) in the SCSI device. */\r
- #define REQ_GetMaxLUN 0xFE\r
-\r
- /** Maximum length of a SCSI command which can be issued by the device or host in a Mass Storage bulk wrapper. */\r
- #define MAX_SCSI_COMMAND_LENGTH 16\r
+ #define LEDMASK_USB_NOTREADY LEDS_LED1\r
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)\r
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)\r
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)\r
+ #define LEDMASK_USB_BUSY LEDS_LED2\r
\r
- /** Total number of Logical Units (drives) in the device. The total device capacity is shared equally between\r
- * each drive - this can be set to any positive non-zero amount.\r
- */\r
- #define TOTAL_LUNS 2\r
+ #define TOTAL_LUNS 2\r
\r
/** Blocks in each LUN, calculated from the total capacity divided by the total number of Logical Units in the device. */\r
- #define LUN_MEDIA_BLOCKS (VIRTUAL_MEMORY_BLOCKS / TOTAL_LUNS) \r
- \r
- /** Magic signature for a Command Block Wrapper used in the Mass Storage Bulk-Only transport protocol. */\r
- #define CBW_SIGNATURE 0x43425355UL\r
-\r
- /** Magic signature for a Command Status Wrapper used in the Mass Storage Bulk-Only transport protocol. */\r
- #define CSW_SIGNATURE 0x53425355UL\r
- \r
- /** Mask for a Command Block Wrapper's flags attribute to specify a command with data sent from host-to-device. */\r
- #define COMMAND_DIRECTION_DATA_OUT (0 << 7)\r
-\r
- /** Mask for a Command Block Wrapper's flags attribute to specify a command with data sent from device-to-host. */\r
- #define COMMAND_DIRECTION_DATA_IN (1 << 7)\r
-\r
- /* Type defines: */\r
- /** Type define for a Command Block Wrapper, used in the Mass Storage Bulk-Only Transport protocol. */\r
- typedef struct\r
- {\r
- uint32_t Signature; /**< Command block signature, must be CBW_SIGNATURE to indicate a valid Command Block */\r
- uint32_t Tag; /**< Unique command ID value, to associate a command block wrapper with its command status wrapper */\r
- uint32_t DataTransferLength; /** Length of the optional data portion of the issued command, in bytes */\r
- uint8_t Flags; /**< Command block flags, indicating command data direction */\r
- uint8_t LUN; /**< Logical Unit number this command is issued to */\r
- uint8_t SCSICommandLength; /**< Length of the issued SCSI command within the SCSI command data array */\r
- uint8_t SCSICommandData[MAX_SCSI_COMMAND_LENGTH]; /**< Issued SCSI command in the Command Block */\r
- } CommandBlockWrapper_t;\r
- \r
- /** Type define for a Command Status Wrapper, used in the Mass Storage Bulk-Only Transport protocol. */\r
- typedef struct\r
- {\r
- uint32_t Signature; /**< Status block signature, must be CSW_SIGNATURE to indicate a valid Command Status */\r
- uint32_t Tag; /**< Unique command ID value, to associate a command block wrapper with its command status wrapper */\r
- uint32_t DataTransferResidue; /**< Number of bytes of data not processed in the SCSI command */\r
- uint8_t Status; /**< Status code of the issued command - a value from the MassStorage_CommandStatusCodes_t enum */\r
- } CommandStatusWrapper_t;\r
- \r
- /* Enums: */\r
- /** Enum for the possible command status wrapper return status codes. */\r
- enum MassStorage_CommandStatusCodes_t\r
- {\r
- Command_Pass = 0, /**< Command completed with no error */\r
- Command_Fail = 1, /**< Command failed to complete - host may check the exact error via a SCSI REQUEST SENSE command */\r
- Phase_Error = 2 /**< Command failed due to being invalid in the current phase */\r
- };\r
-\r
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */\r
- enum MassStorage_StatusCodes_t\r
- {\r
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */\r
- Status_USBEnumerating = 1, /**< USB interface is enumerating */\r
- Status_USBReady = 2, /**< USB interface is connected and ready */\r
- Status_CommandBlockError = 3, /**< Processing a SCSI command block from the host */\r
- Status_ProcessingCommandBlock = 4, /**< Error during the processing of a SCSI command block from the host */\r
- };\r
- \r
- /* Global Variables: */\r
- extern CommandBlockWrapper_t CommandBlock;\r
- extern CommandStatusWrapper_t CommandStatus;\r
- extern volatile bool IsMassStoreReset;\r
-\r
- /* Task Definitions: */\r
- TASK(USB_MassStorage);\r
+ #define LUN_MEDIA_BLOCKS (VIRTUAL_MEMORY_BLOCKS / TOTAL_LUNS)\r
\r
/* Function Prototypes: */\r
+ void SetupHardware(void);\r
+\r
void EVENT_USB_Connect(void);\r
void EVENT_USB_Disconnect(void);\r
void EVENT_USB_ConfigurationChanged(void);\r
void EVENT_USB_UnhandledControlPacket(void);\r
\r
- void UpdateStatus(uint8_t CurrentStatus);\r
-\r
- #if defined(INCLUDE_FROM_MASSSTORAGE_C)\r
- static bool ReadInCommandBlock(void);\r
- static void ReturnCommandStatus(void);\r
- #endif\r
-\r
- uint8_t StreamCallback_AbortOnMassStoreReset(void);\r
+ bool CALLBACK_USB_MS_SCSICommandReceived(USB_ClassInfo_MS_t* MSInterfaceInfo);\r
\r
#endif\r
Descriptors.c \\r
Lib/SCSI.c \\r
Lib/DataflashManager.c \\r
- $(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Endpoint.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Host.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \\r
- $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \\r
+ $(LUFA_PATH)/LUFA/Drivers/USB/Class/Device/MassStorage.c \\r
\r
\r
# List C++ source files here. (C dependencies are automatically generated.)\r
CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY\r
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION\r
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"\r
-CDEFS += -DINTERRUPT_CONTROL_ENDPOINT\r
\r
\r
# Place -D or -U options here for ASM sources\r
#define _DESCRIPTORS_H_\r
\r
/* Includes: */\r
- #include <LUFA/Drivers/USB/USB.h>\r
-\r
#include <avr/pgmspace.h>\r
\r
- /* Type Defines: */\r
- /** Type define for the HID class specific HID descriptor, to describe the HID device's specifications. Refer to the HID\r
- * specification for details on the structure elements.\r
- */\r
- typedef struct\r
- {\r
- USB_Descriptor_Header_t Header;\r
- \r
- uint16_t HIDSpec;\r
- uint8_t CountryCode;\r
- \r
- uint8_t TotalReportDescriptors;\r
-\r
- uint8_t HIDReportType;\r
- uint16_t HIDReportLength;\r
- } USB_Descriptor_HID_t;\r
-\r
- /** Type define for the data type used to store HID report descriptor elements. */\r
- typedef uint8_t USB_Descriptor_HIDReport_Datatype_t;\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>\r
\r
+ /* Type Defines: */\r
/** Type define for the device configuration descriptor structure. This must be defined in the\r
* application code, as the configuration descriptor contains several sub-descriptors which\r
* vary between devices, and which describe the device's usage to the host.\r
/** Size in bytes of the Mouse HID reporting IN endpoint. */\r
#define MOUSE_EPSIZE 8\r
\r
- /** Descriptor header type value, to indicate a HID class HID descriptor. */\r
- #define DTYPE_HID 0x21\r
- \r
- /** Descriptor header type value, to indicate a HID class HID report descriptor. */\r
- #define DTYPE_Report 0x22\r
-\r
/* Function Prototypes: */\r
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)\r
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);\r
arising out of or in connection with the use or performance of\r
this software.\r
*/\r
-\r
-/** \file\r
- *\r
- * Main source file for the Mouse demo. This file contains the main tasks of the demo and\r
- * is responsible for the initial application hardware configuration.\r
- */\r
\r
#include "Mouse.h"\r
\r
-/* Scheduler Task List */\r
-TASK_LIST\r
-{\r
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },\r
- { .Task = USB_Mouse_Report , .TaskStatus = TASK_STOP },\r
-};\r
+USB_ClassInfo_HID_t Mouse_HID_Interface =\r
+ {\r
+ .InterfaceNumber = 0,\r
\r
-/* Global Variables */\r
-/** Indicates what report mode the host has requested, true for normal HID reporting mode, false for special boot\r
- * protocol reporting mode.\r
- */\r
-bool UsingReportProtocol = true;\r
+ .ReportINEndpointNumber = MOUSE_EPNUM,\r
+ .ReportINEndpointSize = MOUSE_EPSIZE,\r
\r
-/** Current Idle period. This is set by the host via a Set Idle HID class request to silence the device's reports\r
- * for either the entire idle duration, or until the report status changes (e.g. the user moves the mouse).\r
- */\r
-uint16_t IdleCount = HID_IDLE_CHANGESONLY;\r
+ .ReportBufferSize = sizeof(USB_MouseReport_Data_t),\r
+ };\r
\r
-/** Current Idle period remaining. When the IdleCount value is set, this tracks the remaining number of idle\r
- * milliseconds. This is separate to the IdleCount timer and is incremented and compared as the host may request \r
- * the current idle period via a Get Idle HID class request, thus its value must be preserved.\r
- */\r
-uint16_t IdleMSRemaining = 0;\r
+int main(void)\r
+{ \r
+ SetupHardware();\r
+ \r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
\r
+ for (;;)\r
+ {\r
+ USB_HID_USBTask(&Mouse_HID_Interface);\r
+ USB_USBTask();\r
+ }\r
+}\r
\r
-/** Main program entry point. This routine configures the hardware required by the application, then\r
- * starts the scheduler to run the application tasks.\r
- */\r
-int main(void)\r
+void SetupHardware(void)\r
{\r
/* Disable watchdog if enabled by bootloader/fuses */\r
MCUSR &= ~(1 << WDRF);\r
Joystick_Init();\r
LEDs_Init();\r
Buttons_Init();\r
- \r
- /* Millisecond timer initialization, with output compare interrupt enabled for the idle timing */\r
- OCR0A = 0x7D;\r
- TCCR0A = (1 << WGM01);\r
- TCCR0B = ((1 << CS01) | (1 << CS00));\r
- TIMSK0 = (1 << OCIE0A);\r
-\r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
- \r
- /* Initialize Scheduler so that it can be used */\r
- Scheduler_Init();\r
-\r
- /* Initialize USB Subsystem */\r
USB_Init();\r
-\r
- /* Scheduling - routine never returns, so put this last in the main function */\r
- Scheduler_Start();\r
}\r
\r
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and\r
- * starts the library USB task to begin the enumeration and USB management process.\r
- */\r
void EVENT_USB_Connect(void)\r
{\r
- /* Start USB management task */\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);\r
- \r
- /* Indicate USB enumerating */\r
- UpdateStatus(Status_USBEnumerating);\r
-\r
- /* Default to report protocol on connect */\r
- UsingReportProtocol = true;\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);\r
}\r
\r
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via\r
- * the status LEDs and stops the USB management and Mouse reporting tasks.\r
- */\r
void EVENT_USB_Disconnect(void)\r
{\r
- /* Stop running mouse reporting and USB management tasks */\r
- Scheduler_SetTaskMode(USB_Mouse_Report, TASK_STOP);\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);\r
-\r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
}\r
\r
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host sets the current configuration\r
- * of the USB device after enumeration - the device endpoints are configured and the mouse reporting task started.\r
- */ \r
void EVENT_USB_ConfigurationChanged(void)\r
{\r
- /* Setup Mouse Report Endpoint */\r
- Endpoint_ConfigureEndpoint(MOUSE_EPNUM, EP_TYPE_INTERRUPT,\r
- ENDPOINT_DIR_IN, MOUSE_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- /* Indicate USB connected and ready */\r
- UpdateStatus(Status_USBReady);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
\r
- /* Start running mouse reporting task */\r
- Scheduler_SetTaskMode(USB_Mouse_Report, TASK_RUN);\r
+ if (!(USB_HID_ConfigureEndpoints(&Mouse_HID_Interface)))\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
}\r
\r
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific\r
- * control requests that are not handled internally by the USB library (including the HID commands, which are\r
- * all issued via the control endpoint), so that they can be handled appropriately for the application.\r
- */\r
void EVENT_USB_UnhandledControlPacket(void)\r
{\r
- /* Handle HID Class specific requests */\r
- switch (USB_ControlRequest.bRequest)\r
- {\r
- case REQ_GetReport:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- USB_MouseReport_Data_t MouseReportData;\r
-\r
- Endpoint_ClearSETUP();\r
-\r
- /* Create the next mouse report for transmission to the host */\r
- CreateMouseReport(&MouseReportData);\r
- \r
- /* Write the report data to the control endpoint */\r
- Endpoint_Write_Control_Stream_LE(&MouseReportData, sizeof(MouseReportData));\r
- \r
- /* Clear the report data afterwards */\r
- memset(&MouseReportData, 0, sizeof(MouseReportData));\r
-\r
- /* Finalize the stream transfer to send the last packet or clear the host abort */\r
- Endpoint_ClearOUT();\r
- }\r
- \r
- break;\r
- case REQ_GetProtocol:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- Endpoint_ClearSETUP();\r
- \r
- /* Write the current protocol flag to the host */\r
- Endpoint_Write_Byte(UsingReportProtocol);\r
- \r
- /* Send the flag to the host */\r
- Endpoint_ClearIN();\r
-\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
- }\r
- \r
- break;\r
- case REQ_SetProtocol:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- Endpoint_ClearSETUP();\r
- \r
- /* Set or clear the flag depending on what the host indicates that the current Protocol should be */\r
- UsingReportProtocol = (USB_ControlRequest.wValue != 0);\r
- \r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
- }\r
- \r
- break;\r
- case REQ_SetIdle:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- Endpoint_ClearSETUP();\r
- \r
- /* Get idle period in MSB */\r
- IdleCount = (USB_ControlRequest.wValue >> 8);\r
- \r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
- }\r
- \r
- break;\r
- case REQ_GetIdle:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
- { \r
- Endpoint_ClearSETUP();\r
- \r
- /* Write the current idle duration to the host */\r
- Endpoint_Write_Byte(IdleCount);\r
- \r
- /* Send the flag to the host */\r
- Endpoint_ClearIN();\r
-\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
- }\r
-\r
- break;\r
- }\r
+ USB_HID_ProcessControlPacket(&Mouse_HID_Interface);\r
}\r
\r
-/** ISR for the timer 0 compare vector. This ISR fires once each millisecond, and increments the\r
- * scheduler elapsed idle period counter when the host has set an idle period.\r
- */\r
-ISR(TIMER0_COMPA_vect, ISR_BLOCK)\r
+void EVENT_USB_StartOfFrame(void)\r
{\r
- /* One millisecond has elapsed, decrement the idle time remaining counter if it has not already elapsed */\r
- if (IdleMSRemaining)\r
- IdleMSRemaining--;\r
+ USB_HID_RegisterStartOfFrame(&Mouse_HID_Interface);\r
}\r
\r
-/** Fills the given HID report data structure with the next HID report to send to the host.\r
- *\r
- * \param ReportData Pointer to a HID report data structure to be filled\r
- */\r
-void CreateMouseReport(USB_MouseReport_Data_t* ReportData)\r
+uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData)\r
{\r
+ USB_MouseReport_Data_t* MouseReport = (USB_MouseReport_Data_t*)ReportData;\r
+ \r
uint8_t JoyStatus_LCL = Joystick_GetStatus();\r
uint8_t ButtonStatus_LCL = Buttons_GetStatus();\r
- \r
- /* Clear the report contents */\r
- memset(ReportData, 0, sizeof(USB_MouseReport_Data_t));\r
\r
if (JoyStatus_LCL & JOY_UP)\r
- ReportData->Y = -1;\r
+ MouseReport->Y = -1;\r
else if (JoyStatus_LCL & JOY_DOWN)\r
- ReportData->Y = 1;\r
+ MouseReport->Y = 1;\r
\r
if (JoyStatus_LCL & JOY_RIGHT)\r
- ReportData->X = 1;\r
+ MouseReport->X = 1;\r
else if (JoyStatus_LCL & JOY_LEFT)\r
- ReportData->X = -1;\r
+ MouseReport->X = -1;\r
\r
if (JoyStatus_LCL & JOY_PRESS)\r
- ReportData->Button = (1 << 0);\r
+ MouseReport->Button = (1 << 0);\r
\r
if (ButtonStatus_LCL & BUTTONS_BUTTON1)\r
- ReportData->Button |= (1 << 1);\r
-}\r
-\r
-/** Sends the next HID report to the host, via the keyboard data endpoint. */\r
-void SendNextReport(void)\r
-{\r
- static USB_MouseReport_Data_t PrevMouseReportData;\r
- USB_MouseReport_Data_t MouseReportData;\r
- bool SendReport;\r
- \r
- /* Create the next mouse report for transmission to the host */\r
- CreateMouseReport(&MouseReportData);\r
- \r
- /* Check to see if the report data has changed - if so a report MUST be sent */\r
- SendReport = (memcmp(&PrevMouseReportData, &MouseReportData, sizeof(USB_MouseReport_Data_t)) != 0);\r
- \r
- /* Override the check if the Y or X values are non-zero - we want continuous movement while the joystick\r
- * is being held down (via continuous reports), otherwise the cursor will only move once per joystick toggle */\r
- if ((MouseReportData.Y != 0) || (MouseReportData.X != 0))\r
- SendReport = true;\r
- \r
- /* Save the current report data for later comparison to check for changes */\r
- PrevMouseReportData = MouseReportData;\r
- \r
- /* Check if the idle period is set and has elapsed */\r
- if ((IdleCount != HID_IDLE_CHANGESONLY) && (!(IdleMSRemaining)))\r
- {\r
- /* Reset the idle time remaining counter, must multiply by 4 to get the duration in milliseconds */\r
- IdleMSRemaining = (IdleCount << 2);\r
- \r
- /* Idle period is set and has elapsed, must send a report to the host */\r
- SendReport = true;\r
- }\r
+ MouseReport->Button |= (1 << 1);\r
\r
- /* Select the Mouse Report Endpoint */\r
- Endpoint_SelectEndpoint(MOUSE_EPNUM);\r
-\r
- /* Check if Mouse Endpoint Ready for Read/Write and if we should send a new report */\r
- if (Endpoint_IsReadWriteAllowed() && SendReport)\r
- {\r
- /* Write Mouse Report Data */\r
- Endpoint_Write_Stream_LE(&MouseReportData, sizeof(MouseReportData));\r
- \r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearIN();\r
- }\r
+ return sizeof(USB_MouseReport_Data_t);\r
}\r
\r
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to\r
- * log to a serial port, or anything else that is suitable for status updates.\r
- *\r
- * \param CurrentStatus Current status of the system, from the Mouse_StatusCodes_t enum\r
- */\r
-void UpdateStatus(uint8_t CurrentStatus)\r
+void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize)\r
{\r
- uint8_t LEDMask = LEDS_NO_LEDS;\r
- \r
- /* Set the LED mask to the appropriate LED mask based on the given status code */\r
- switch (CurrentStatus)\r
- {\r
- case Status_USBNotReady:\r
- LEDMask = (LEDS_LED1);\r
- break;\r
- case Status_USBEnumerating:\r
- LEDMask = (LEDS_LED1 | LEDS_LED2);\r
- break;\r
- case Status_USBReady:\r
- LEDMask = (LEDS_LED2 | LEDS_LED4);\r
- break;\r
- }\r
- \r
- /* Set the board LEDs to the new LED mask */\r
- LEDs_SetAllLEDs(LEDMask);\r
-}\r
-\r
-/** Task to manage HID report generation and transmission to the host, when in report mode. */\r
-TASK(USB_Mouse_Report)\r
-{\r
- /* Check if the USB system is connected to a host */\r
- if (USB_IsConnected)\r
- {\r
- /* Send the next mouse report to the host */\r
- SendNextReport();\r
- }\r
+ // Unused (but mandatory for the HID class driver) in this demo, since there are no Host->Device reports\r
}\r
\r
#include "Descriptors.h"\r
\r
- #include <LUFA/Version.h> // Library Version Information\r
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
- #include <LUFA/Drivers/Board/Joystick.h> // Joystick driver\r
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver\r
- #include <LUFA/Drivers/Board/Buttons.h> // Board Buttons driver\r
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management\r
- \r
- /* Task Definitions: */\r
- TASK(USB_Mouse_Report);\r
-\r
- /* Macros: */\r
- /** Idle period indicating that reports should be sent only when the inputs have changed */\r
- #define HID_IDLE_CHANGESONLY 0\r
- \r
- /** HID Class specific request to get the next HID report from the device. */\r
- #define REQ_GetReport 0x01\r
-\r
- /** HID Class specific request to get the idle timeout period of the device. */\r
- #define REQ_GetIdle 0x02\r
-\r
- /** HID Class specific request to send the next HID report to the device. */\r
- #define REQ_SetReport 0x09\r
-\r
- /** HID Class specific request to set the idle timeout period of the device. */\r
- #define REQ_SetIdle 0x0A\r
-\r
- /** HID Class specific request to get the current HID protocol in use, either report or boot. */\r
- #define REQ_GetProtocol 0x03\r
-\r
- /** HID Class specific request to set the current HID protocol in use, either report or boot. */\r
- #define REQ_SetProtocol 0x0B\r
+ #include <LUFA/Version.h>\r
+ #include <LUFA/Drivers/Board/Joystick.h>\r
+ #include <LUFA/Drivers/Board/LEDs.h>\r
+ #include <LUFA/Drivers/Board/Buttons.h>\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>\r
\r
/* Type Defines: */\r
/** Type define for the mouse HID report structure, for creating and sending HID reports to the host PC.\r
int8_t Y; /**< Current mouse delta Y movement, as a signed 8-bit integer */\r
} USB_MouseReport_Data_t;\r
\r
- /* Enums: */\r
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */\r
- enum Mouse_StatusCodes_t\r
- {\r
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */\r
- Status_USBEnumerating = 1, /**< USB interface is enumerating */\r
- Status_USBReady = 2, /**< USB interface is connected and ready */\r
- };\r
+ /* Macros: */\r
+ #define LEDMASK_USB_NOTREADY LEDS_LED1\r
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)\r
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)\r
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)\r
\r
/* Function Prototypes: */\r
+ void SetupHardware(void);\r
+\r
void EVENT_USB_Connect(void);\r
void EVENT_USB_Disconnect(void);\r
void EVENT_USB_ConfigurationChanged(void);\r
void EVENT_USB_UnhandledControlPacket(void);\r
+ void EVENT_USB_StartOfFrame(void);\r
\r
- void CreateMouseReport(USB_MouseReport_Data_t* ReportData);\r
- void UpdateStatus(uint8_t CurrentStatus);\r
+ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);\r
+ void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo,\r
+ void* ReportData, uint16_t ReportSize);\r
\r
#endif\r
# List C source files here. (C dependencies are automatically generated.)\r
SRC = $(TARGET).c \\r
Descriptors.c \\r
- $(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Endpoint.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Host.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \\r
- $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \\r
+ $(LUFA_PATH)/LUFA/Drivers/USB/Class/Device/HID.c \\r
\r
# List C++ source files here. (C dependencies are automatically generated.)\r
CPPSRC = \r
\r
# Place -D or -U options here for C sources\r
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)\r
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY\r
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY\r
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION\r
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"\r
\r
\r
/* Includes: */\r
#include <avr/io.h>\r
- #include <string.h>\r
- \r
- #include <LUFA/Scheduler/Scheduler.h>\r
+ #include <string.h>
\r
#include "EthernetProtocols.h"\r
#include "Ethernet.h"\r
#include "Ethernet.h"\r
\r
/* Global Variables: */\r
-/** Ethernet Frame buffer structure, to hold the incoming Ethernet frame from the host. */\r
-Ethernet_Frame_Info_t FrameIN;\r
-\r
-/** Ethernet Frame buffer structure, to hold the outgoing Ethernet frame to the host. */\r
-Ethernet_Frame_Info_t FrameOUT;\r
-\r
/** Constant for convenience when checking against or setting a MAC address to the virtual server MAC address. */\r
const MAC_Address_t ServerMACAddress = {SERVER_MAC_ADDRESS};\r
\r
/** Processes an incoming Ethernet frame, and writes the appropriate response to the output Ethernet\r
* frame buffer if the sub protocol handlers create a valid response.\r
*/\r
-void Ethernet_ProcessPacket(void)\r
+void Ethernet_ProcessPacket(Ethernet_Frame_Info_t* FrameIN, Ethernet_Frame_Info_t* FrameOUT)\r
{\r
- DecodeEthernetFrameHeader(FrameIN.FrameData);\r
+ DecodeEthernetFrameHeader(FrameIN->FrameData);\r
\r
/* Cast the incoming Ethernet frame to the Ethernet header type */\r
- Ethernet_Frame_Header_t* FrameINHeader = (Ethernet_Frame_Header_t*)&FrameIN.FrameData;\r
- Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&FrameOUT.FrameData;\r
+ Ethernet_Frame_Header_t* FrameINHeader = (Ethernet_Frame_Header_t*)&FrameIN->FrameData;\r
+ Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&FrameOUT->FrameData;\r
\r
int16_t RetSize = NO_RESPONSE;\r
\r
/* Ensure frame is addressed to either all (broadcast) or the virtual webserver, and is a type II frame */\r
if ((MAC_COMPARE(&FrameINHeader->Destination, &ServerMACAddress) ||\r
- MAC_COMPARE(&FrameINHeader->Destination, &BroadcastMACAddress)) &&\r
- (SwapEndian_16(FrameIN.FrameLength) > ETHERNET_VER2_MINSIZE))\r
+ MAC_COMPARE(&FrameINHeader->Destination, &BroadcastMACAddress)))\r
{\r
/* Process the packet depending on its protocol */\r
switch (SwapEndian_16(FrameINHeader->EtherType))\r
{\r
case ETHERTYPE_ARP:\r
- RetSize = ARP_ProcessARPPacket(&FrameIN.FrameData[sizeof(Ethernet_Frame_Header_t)],\r
- &FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)]);\r
+ RetSize = ARP_ProcessARPPacket(&FrameIN->FrameData[sizeof(Ethernet_Frame_Header_t)],\r
+ &FrameOUT->FrameData[sizeof(Ethernet_Frame_Header_t)]);\r
break; \r
case ETHERTYPE_IPV4:\r
- RetSize = IP_ProcessIPPacket(&FrameIN.FrameData[sizeof(Ethernet_Frame_Header_t)],\r
- &FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)]);\r
+ RetSize = IP_ProcessIPPacket(FrameIN,\r
+ &FrameIN->FrameData[sizeof(Ethernet_Frame_Header_t)],\r
+ &FrameOUT->FrameData[sizeof(Ethernet_Frame_Header_t)]);\r
break;\r
}\r
\r
FrameOUTHeader->EtherType = FrameINHeader->EtherType;\r
\r
/* Set the response length in the buffer and indicate that a response is ready to be sent */\r
- FrameOUT.FrameLength = (sizeof(Ethernet_Frame_Header_t) + RetSize);\r
- FrameOUT.FrameInBuffer = true;\r
+ FrameOUT->FrameLength = (sizeof(Ethernet_Frame_Header_t) + RetSize);\r
+ FrameOUT->FrameInBuffer = true;\r
}\r
}\r
\r
if (RetSize != NO_PROCESS)\r
{\r
/* Clear the frame buffer */\r
- FrameIN.FrameInBuffer = false;\r
+ FrameIN->FrameInBuffer = false;\r
}\r
}\r
\r
/* Includes: */\r
#include <avr/io.h>\r
#include <string.h>\r
+ \r
+ #include <LUFA/Drivers/USB/Class/Device/RNDIS.h>\r
\r
#include "EthernetProtocols.h"\r
#include "ProtocolDecoders.h"\r
#include "IP.h"\r
\r
/* Macros: */\r
+ /** Physical MAC address of the USB RNDIS network adapter */\r
+ #define ADAPTER_MAC_ADDRESS {0x00, 0x02, 0x00, 0x02, 0x00, 0x02} \r
+\r
/** Physical MAC address of the virtual server on the network */\r
#define SERVER_MAC_ADDRESS {0x00, 0x01, 0x00, 0x01, 0x00, 0x01} \r
\r
* \return True if the addresses match, false otherwise\r
*/\r
#define MAC_COMPARE(MAC1, MAC2) (memcmp(MAC1, MAC2, sizeof(MAC_Address_t)) == 0)\r
-\r
- /** Maximum size of an incoming or outgoing Ethernet frame in bytes */\r
- #define ETHERNET_FRAME_SIZE_MAX 1500\r
- \r
- /** Minimum size of an Ethernet packet in bytes, to conform to the Ethernet V2 packet standard */\r
- #define ETHERNET_VER2_MINSIZE 0x0600\r
\r
/** Return value for all sub protocol handling routines, indicating that no response packet has been generated */\r
#define NO_RESPONSE 0 \r
#define NO_PROCESS -1\r
\r
/* Type Defines: */\r
- /** Type define for an Ethernet frame buffer. */\r
- typedef struct\r
- {\r
- uint8_t FrameData[ETHERNET_FRAME_SIZE_MAX]; /**< Ethernet frame contents */\r
- uint16_t FrameLength; /**< Length in bytes of the Ethernet frame stored in the buffer */\r
- bool FrameInBuffer; /**< Indicates if a frame is currently stored in the buffer */\r
- } Ethernet_Frame_Info_t;\r
-\r
/** Type define for an Ethernet frame header */\r
typedef struct\r
{\r
} Ethernet_Frame_Header_t;\r
\r
/* External Variables: */\r
- extern Ethernet_Frame_Info_t FrameIN;\r
- extern Ethernet_Frame_Info_t FrameOUT;\r
-\r
extern const MAC_Address_t ServerMACAddress;\r
extern const IP_Address_t ServerIPAddress;\r
extern const MAC_Address_t BroadcastMACAddress;\r
extern const IP_Address_t ClientIPAddress;\r
\r
/* Function Prototypes: */\r
- void Ethernet_ProcessPacket(void);\r
+ void Ethernet_ProcessPacket(Ethernet_Frame_Info_t* FrameIN, Ethernet_Frame_Info_t* FrameOUT);\r
uint16_t Ethernet_Checksum16(void* Data, uint16_t Bytes);\r
\r
#endif\r
#define PROTOCOL_OSPF 89\r
#define PROTOCOL_SCTP 132\r
\r
- /* Type Defines: */\r
- /** Type define for a physical MAC address of a device on a network */\r
- typedef struct\r
- {\r
- uint8_t Octets[6]; /**< Individual bytes of a MAC address */\r
- } MAC_Address_t;\r
- \r
+ /* Type Defines: */ \r
/** Type define for a protocol IP address of a device on a network */\r
typedef struct\r
{\r
*\r
* \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise\r
*/\r
-int16_t ICMP_ProcessICMPPacket(void* InDataStart, void* OutDataStart)\r
+int16_t ICMP_ProcessICMPPacket(Ethernet_Frame_Info_t* FrameIN, void* InDataStart, void* OutDataStart)\r
{\r
ICMP_Header_t* ICMPHeaderIN = (ICMP_Header_t*)InDataStart;\r
ICMP_Header_t* ICMPHeaderOUT = (ICMP_Header_t*)OutDataStart;\r
ICMPHeaderOUT->Id = ICMPHeaderIN->Id;\r
ICMPHeaderOUT->Sequence = ICMPHeaderIN->Sequence;\r
\r
- uint16_t DataSize = FrameIN.FrameLength - ((((uint16_t)InDataStart + sizeof(ICMP_Header_t)) - (uint16_t)FrameIN.FrameData));\r
+ uint16_t DataSize = FrameIN->FrameLength - ((((uint16_t)InDataStart + sizeof(ICMP_Header_t)) - (uint16_t)FrameIN->FrameData));\r
\r
/* Copy the remaining payload to the response - echo requests should echo back any sent data */\r
memcpy(&((uint8_t*)OutDataStart)[sizeof(ICMP_Header_t)],\r
} ICMP_Header_t;\r
\r
/* Function Prototypes: */\r
- int16_t ICMP_ProcessICMPPacket(void* InDataStart, void* OutDataStart);\r
+ int16_t ICMP_ProcessICMPPacket(Ethernet_Frame_Info_t* FrameIN, void* InDataStart, void* OutDataStart);\r
\r
#endif\r
* response was generated, NO_PROCESS if the packet processing was deferred until the\r
* next Ethernet packet handler iteration\r
*/\r
-int16_t IP_ProcessIPPacket(void* InDataStart, void* OutDataStart)\r
+int16_t IP_ProcessIPPacket(Ethernet_Frame_Info_t* FrameIN, void* InDataStart, void* OutDataStart)\r
{\r
DecodeIPHeader(InDataStart);\r
\r
switch (IPHeaderIN->Protocol)\r
{\r
case PROTOCOL_ICMP:\r
- RetSize = ICMP_ProcessICMPPacket(&((uint8_t*)InDataStart)[HeaderLengthBytes],\r
+ RetSize = ICMP_ProcessICMPPacket(FrameIN,\r
+ &((uint8_t*)InDataStart)[HeaderLengthBytes],\r
&((uint8_t*)OutDataStart)[sizeof(IP_Header_t)]);\r
break;\r
case PROTOCOL_TCP:\r
} IP_Header_t;\r
\r
/* Function Prototypes: */\r
- int16_t IP_ProcessIPPacket(void* InDataStart, void* OutDataStart);\r
+ int16_t IP_ProcessIPPacket(Ethernet_Frame_Info_t* FrameIN, void* InDataStart, void* OutDataStart);\r
\r
#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * RNDIS command handler functions. This handles RNDIS commands according to\r
- * the Microsoft RNDIS specification, creating a USB Ethernet network adapter.\r
- */\r
- \r
-#define INCLUDE_FROM_RNDIS_C\r
-#include "RNDIS.h"\r
-\r
-/* Global Variables: */\r
-/** Physical MAC address of the network adapter, which becomes the MAC address of the host for packets sent to the adapter. */\r
-static MAC_Address_t PROGMEM AdapterMACAddress = {ADAPTER_MAC_ADDRESS};\r
-\r
-/** Vendor description of the adapter. This is overridden by the INF file required to install the appropriate RNDIS drivers for\r
- * the device, but may still be used by the OS in some circumstances.\r
- */\r
-static char PROGMEM AdapterVendorDescription[] = "LUFA RNDIS Adapter";\r
-\r
-/** List of RNDIS OID commands supported by this adapter. */\r
-static const uint32_t PROGMEM AdapterSupportedOIDList[] =\r
- {\r
- OID_GEN_SUPPORTED_LIST,\r
- OID_GEN_PHYSICAL_MEDIUM,\r
- OID_GEN_HARDWARE_STATUS,\r
- OID_GEN_MEDIA_SUPPORTED,\r
- OID_GEN_MEDIA_IN_USE,\r
- OID_GEN_MAXIMUM_FRAME_SIZE,\r
- OID_GEN_MAXIMUM_TOTAL_SIZE,\r
- OID_GEN_LINK_SPEED,\r
- OID_GEN_TRANSMIT_BLOCK_SIZE,\r
- OID_GEN_RECEIVE_BLOCK_SIZE,\r
- OID_GEN_VENDOR_ID,\r
- OID_GEN_VENDOR_DESCRIPTION,\r
- OID_GEN_CURRENT_PACKET_FILTER,\r
- OID_GEN_MAXIMUM_TOTAL_SIZE,\r
- OID_GEN_MEDIA_CONNECT_STATUS,\r
- OID_GEN_XMIT_OK,\r
- OID_GEN_RCV_OK,\r
- OID_GEN_XMIT_ERROR,\r
- OID_GEN_RCV_ERROR,\r
- OID_GEN_RCV_NO_BUFFER,\r
- OID_802_3_PERMANENT_ADDRESS,\r
- OID_802_3_CURRENT_ADDRESS,\r
- OID_802_3_MULTICAST_LIST,\r
- OID_802_3_MAXIMUM_LIST_SIZE,\r
- OID_802_3_RCV_ERROR_ALIGNMENT,\r
- OID_802_3_XMIT_ONE_COLLISION,\r
- OID_802_3_XMIT_MORE_COLLISIONS,\r
- };\r
-\r
-/** Buffer for RNDIS messages (as distinct from Ethernet frames sent through the adapter. This must be big enough to hold the entire\r
- * Supported OID list, plus the response header. The buffer is half-duplex, and is written to as it is read to save on SRAM - for this\r
- * reason, care must be taken when constructing RNDIS responses that unread data is not overwritten when writing in responses.\r
- */\r
-uint8_t RNDISMessageBuffer[sizeof(AdapterSupportedOIDList) + sizeof(RNDIS_QUERY_CMPLT_t)];\r
-\r
-/** Pointer to the RNDIS message header at the top of the RNDIS message buffer, for convenience. */\r
-RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISMessageBuffer;\r
-\r
-/** Indicates if a RNDIS message response is ready to be sent back to the host. */\r
-bool ResponseReady = false;\r
-\r
-/** Current RNDIS adapter state, a value from the RNDIS_States_t enum. */\r
-uint8_t CurrRNDISState = RNDIS_Uninitialized;\r
-\r
-/** Current Ethernet packet filter mask. This is non-zero when the adapter is initialized, or zero when disabled. */\r
-uint32_t CurrPacketFilter = 0; \r
-\r
-\r
-/** Processes the RNDIS message received by the host and stored in the RNDISMessageBuffer global buffer. If a response is\r
- * created, the ResponseReady global is updated so that the response is written back to the host upon request.\r
- */\r
-void ProcessRNDISControlMessage(void)\r
-{\r
- /* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of\r
- this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */\r
-\r
- switch (MessageHeader->MessageType)\r
- {\r
- case REMOTE_NDIS_INITIALIZE_MSG:\r
- /* Initialize the adapter - return information about the supported RNDIS version and buffer sizes */\r
-\r
- ResponseReady = true;\r
- \r
- RNDIS_INITIALIZE_MSG_t* INITIALIZE_Message = (RNDIS_INITIALIZE_MSG_t*)&RNDISMessageBuffer;\r
- RNDIS_INITIALIZE_CMPLT_t* INITIALIZE_Response = (RNDIS_INITIALIZE_CMPLT_t*)&RNDISMessageBuffer;\r
- \r
- INITIALIZE_Response->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;\r
- INITIALIZE_Response->MessageLength = sizeof(RNDIS_INITIALIZE_CMPLT_t);\r
- INITIALIZE_Response->RequestId = INITIALIZE_Message->RequestId;\r
- INITIALIZE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
- \r
- INITIALIZE_Response->MajorVersion = REMOTE_NDIS_VERSION_MAJOR;\r
- INITIALIZE_Response->MinorVersion = REMOTE_NDIS_VERSION_MINOR; \r
- INITIALIZE_Response->DeviceFlags = REMOTE_NDIS_DF_CONNECTIONLESS;\r
- INITIALIZE_Response->Medium = REMOTE_NDIS_MEDIUM_802_3;\r
- INITIALIZE_Response->MaxPacketsPerTransfer = 1;\r
- INITIALIZE_Response->MaxTransferSize = (sizeof(RNDIS_PACKET_MSG_t) + ETHERNET_FRAME_SIZE_MAX);\r
- INITIALIZE_Response->PacketAlignmentFactor = 0;\r
- INITIALIZE_Response->AFListOffset = 0;\r
- INITIALIZE_Response->AFListSize = 0;\r
- \r
- CurrRNDISState = RNDIS_Initialized;\r
- \r
- break;\r
- case REMOTE_NDIS_HALT_MSG:\r
- /* Halt the adapter, reset the adapter state - note that no response should be returned when completed */\r
-\r
- ResponseReady = false;\r
- MessageHeader->MessageLength = 0;\r
-\r
- CurrRNDISState = RNDIS_Uninitialized;\r
-\r
- break;\r
- case REMOTE_NDIS_QUERY_MSG:\r
- /* Request for information about a parameter about the adapter, specified as an OID token */\r
-\r
- ResponseReady = true;\r
- \r
- RNDIS_QUERY_MSG_t* QUERY_Message = (RNDIS_QUERY_MSG_t*)&RNDISMessageBuffer;\r
- RNDIS_QUERY_CMPLT_t* QUERY_Response = (RNDIS_QUERY_CMPLT_t*)&RNDISMessageBuffer;\r
- uint32_t Query_Oid = QUERY_Message->Oid;\r
- \r
- void* QueryData = &RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +\r
- QUERY_Message->InformationBufferOffset];\r
- void* ResponseData = &RNDISMessageBuffer[sizeof(RNDIS_QUERY_CMPLT_t)]; \r
- uint16_t ResponseSize;\r
-\r
- QUERY_Response->MessageType = REMOTE_NDIS_QUERY_CMPLT;\r
- QUERY_Response->MessageLength = sizeof(RNDIS_QUERY_CMPLT_t);\r
- \r
- if (ProcessNDISQuery(Query_Oid, QueryData, QUERY_Message->InformationBufferLength,\r
- ResponseData, &ResponseSize))\r
- {\r
- QUERY_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
- QUERY_Response->MessageLength += ResponseSize;\r
- \r
- QUERY_Response->InformationBufferLength = ResponseSize;\r
- QUERY_Response->InformationBufferOffset = (sizeof(RNDIS_QUERY_CMPLT_t) - sizeof(RNDIS_Message_Header_t));\r
- }\r
- else\r
- { \r
- QUERY_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;\r
-\r
- QUERY_Response->InformationBufferLength = 0;\r
- QUERY_Response->InformationBufferOffset = 0;\r
- }\r
- \r
- break;\r
- case REMOTE_NDIS_SET_MSG:\r
- /* Request to set a parameter of the adapter, specified as an OID token */\r
- \r
- ResponseReady = true;\r
- \r
- RNDIS_SET_MSG_t* SET_Message = (RNDIS_SET_MSG_t*)&RNDISMessageBuffer;\r
- RNDIS_SET_CMPLT_t* SET_Response = (RNDIS_SET_CMPLT_t*)&RNDISMessageBuffer;\r
- uint32_t SET_Oid = SET_Message->Oid;\r
-\r
- SET_Response->MessageType = REMOTE_NDIS_SET_CMPLT;\r
- SET_Response->MessageLength = sizeof(RNDIS_SET_CMPLT_t);\r
- SET_Response->RequestId = SET_Message->RequestId;\r
-\r
- void* SetData = &RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +\r
- SET_Message->InformationBufferOffset];\r
- \r
- if (ProcessNDISSet(SET_Oid, SetData, SET_Message->InformationBufferLength))\r
- SET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
- else\r
- SET_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;\r
-\r
- break;\r
- case REMOTE_NDIS_RESET_MSG:\r
- /* Soft reset the adapter */\r
- \r
- ResponseReady = true;\r
- \r
- RNDIS_RESET_CMPLT_t* RESET_Response = (RNDIS_RESET_CMPLT_t*)&RNDISMessageBuffer;\r
-\r
- RESET_Response->MessageType = REMOTE_NDIS_RESET_CMPLT;\r
- RESET_Response->MessageLength = sizeof(RNDIS_RESET_CMPLT_t);\r
- RESET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
- RESET_Response->AddressingReset = 0;\r
-\r
- break;\r
- case REMOTE_NDIS_KEEPALIVE_MSG:\r
- /* Keep alive message sent to the adapter every 5 seconds when idle to ensure it is still responding */\r
- \r
- ResponseReady = true;\r
- \r
- RNDIS_KEEPALIVE_MSG_t* KEEPALIVE_Message = (RNDIS_KEEPALIVE_MSG_t*)&RNDISMessageBuffer;\r
- RNDIS_KEEPALIVE_CMPLT_t* KEEPALIVE_Response = (RNDIS_KEEPALIVE_CMPLT_t*)&RNDISMessageBuffer;\r
-\r
- KEEPALIVE_Response->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;\r
- KEEPALIVE_Response->MessageLength = sizeof(RNDIS_KEEPALIVE_CMPLT_t);\r
- KEEPALIVE_Response->RequestId = KEEPALIVE_Message->RequestId;\r
- KEEPALIVE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
- \r
- break;\r
- }\r
-}\r
-\r
-/** Processes RNDIS query commands, retrieving information from the adapter and reporting it back to the host. The requested\r
- * parameter is given as an OID value.\r
- *\r
- * \param OId OId value of the parameter being queried\r
- * \param QueryData Pointer to any extra query data being sent by the host to the device inside the RNDIS message buffer\r
- * \param QuerySize Size in bytes of the extra query data being sent by the host\r
- * \param ResponseData Pointer to the start of the query response inside the RNDIS message buffer\r
- * \param ResponseSize Pointer to the size in bytes of the response data being sent to the host\r
- *\r
- * \return Boolean true if the query was handled, false otherwise\r
- */\r
-static bool ProcessNDISQuery(uint32_t OId, void* QueryData, uint16_t QuerySize,\r
- void* ResponseData, uint16_t* ResponseSize)\r
-{\r
- /* Handler for REMOTE_NDIS_QUERY_MSG messages */\r
-\r
- switch (OId)\r
- {\r
- case OID_GEN_SUPPORTED_LIST:\r
- *ResponseSize = sizeof(AdapterSupportedOIDList);\r
- \r
- /* Copy the list of supported NDIS OID tokens to the response buffer */\r
- memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));\r
- \r
- return true;\r
- case OID_GEN_PHYSICAL_MEDIUM:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Indicate that the device is a true ethernet link */\r
- *((uint32_t*)ResponseData) = 0;\r
- \r
- return true;\r
- case OID_GEN_HARDWARE_STATUS:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Always indicate hardware ready */\r
- *((uint32_t*)ResponseData) = NdisHardwareStatusReady;\r
- \r
- return true;\r
- case OID_GEN_MEDIA_SUPPORTED:\r
- case OID_GEN_MEDIA_IN_USE:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Indicate 802.3 (Ethernet) supported by the adapter */\r
- *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIUM_802_3;\r
- \r
- return true;\r
- case OID_GEN_VENDOR_ID:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */\r
- *((uint32_t*)ResponseData) = 0x00FFFFFF;\r
- \r
- return true;\r
- case OID_GEN_MAXIMUM_FRAME_SIZE:\r
- case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
- case OID_GEN_RECEIVE_BLOCK_SIZE:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Indicate that the maximum frame size is the size of the ethernet frame buffer */\r
- *((uint32_t*)ResponseData) = ETHERNET_FRAME_SIZE_MAX;\r
- \r
- return true;\r
- case OID_GEN_VENDOR_DESCRIPTION:\r
- *ResponseSize = sizeof(AdapterVendorDescription);\r
- \r
- /* Copy vendor description string to the response buffer */\r
- memcpy_P(ResponseData, AdapterVendorDescription, sizeof(AdapterVendorDescription));\r
- \r
- return true;\r
- case OID_GEN_MEDIA_CONNECT_STATUS:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Always indicate that the adapter is connected to a network */\r
- *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIA_STATE_CONNECTED;\r
- \r
- return true;\r
- case OID_GEN_LINK_SPEED:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Indicate 10Mb/s link speed */\r
- *((uint32_t*)ResponseData) = 100000;\r
-\r
- return true;\r
- case OID_802_3_PERMANENT_ADDRESS:\r
- case OID_802_3_CURRENT_ADDRESS:\r
- *ResponseSize = sizeof(MAC_Address_t);\r
- \r
- /* Copy over the fixed adapter MAC to the response buffer */\r
- memcpy_P(ResponseData, &AdapterMACAddress, sizeof(MAC_Address_t));\r
-\r
- return true;\r
- case OID_802_3_MAXIMUM_LIST_SIZE:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Indicate only one multicast address supported */\r
- *((uint32_t*)ResponseData) = 1;\r
- \r
- return true;\r
- case OID_GEN_CURRENT_PACKET_FILTER:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Indicate the current packet filter mask */\r
- *((uint32_t*)ResponseData) = CurrPacketFilter;\r
- \r
- return true; \r
- case OID_GEN_XMIT_OK:\r
- case OID_GEN_RCV_OK:\r
- case OID_GEN_XMIT_ERROR:\r
- case OID_GEN_RCV_ERROR:\r
- case OID_GEN_RCV_NO_BUFFER:\r
- case OID_802_3_RCV_ERROR_ALIGNMENT:\r
- case OID_802_3_XMIT_ONE_COLLISION:\r
- case OID_802_3_XMIT_MORE_COLLISIONS:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Unused statistic OIDs - always return 0 for each */\r
- *((uint32_t*)ResponseData) = 0;\r
- \r
- return true;\r
- case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */\r
- *((uint32_t*)ResponseData) = (sizeof(RNDISMessageBuffer) + ETHERNET_FRAME_SIZE_MAX);\r
- \r
- return true;\r
- default:\r
- return false;\r
- }\r
-}\r
-\r
-/** Processes RNDIS set commands, setting adapter parameters to values given by the host. The requested parameter is given \r
- * as an OID value.\r
- *\r
- * \param OId OId value of the parameter being set\r
- * \param SetData Pointer to the parameter value in the RNDIS message buffer\r
- * \param SetSize Size in bytes of the parameter value being sent by the host\r
- *\r
- * \return Boolean true if the set was handled, false otherwise\r
- */\r
-static bool ProcessNDISSet(uint32_t OId, void* SetData, uint16_t SetSize)\r
-{\r
- /* Handler for REMOTE_NDIS_SET_MSG messages */\r
-\r
- switch (OId)\r
- {\r
- case OID_GEN_CURRENT_PACKET_FILTER:\r
- /* Save the packet filter mask in case the host queries it again later */\r
- CurrPacketFilter = *((uint32_t*)SetData);\r
- \r
- /* Set the RNDIS state to initialized if the packet filter is non-zero */\r
- CurrRNDISState = ((CurrPacketFilter) ? RNDIS_Data_Initialized : RNDIS_Data_Initialized);\r
- \r
- return true;\r
- case OID_802_3_MULTICAST_LIST:\r
- /* Do nothing - throw away the value from the host as it is unused */\r
- \r
- return true;\r
- default:\r
- return false;\r
- }\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header file for RNDIS.c.\r
- */\r
-\r
-#ifndef _RNDIS_H_\r
-#define _RNDIS_H_\r
-\r
- /* Includes: */\r
- #include <avr/io.h>\r
- #include <stdbool.h>\r
- \r
- #include "RNDISEthernet.h"\r
- #include "RNDISConstants.h"\r
- #include "Ethernet.h"\r
-\r
- /* Macros: */\r
- /** Physical MAC Address of the USB network adapter */\r
- #define ADAPTER_MAC_ADDRESS {0x02, 0x00, 0x02, 0x00, 0x02, 0x00}\r
- \r
- /** Implemented RNDIS Version Major */\r
- #define REMOTE_NDIS_VERSION_MAJOR 0x01\r
-\r
- /** Implemented RNDIS Version Minor */\r
- #define REMOTE_NDIS_VERSION_MINOR 0x00\r
- \r
- /** RNDIS request to issue a host-to-device NDIS command */\r
- #define REQ_SendEncapsulatedCommand 0x00\r
-\r
- /** RNDIS request to issue a device-to-host NDIS response */\r
- #define REQ_GetEncapsulatedResponse 0x01\r
- \r
- /* Enums: */\r
- /** Enum for the possible NDIS adapter states. */\r
- enum RNDIS_States_t\r
- {\r
- RNDIS_Uninitialized = 0, /**< Adapter currently uninitialized */\r
- RNDIS_Initialized = 1, /**< Adapter currently initialized but not ready for data transfers */\r
- RNDIS_Data_Initialized = 2, /**< Adapter currently initialized and ready for data transfers */\r
- };\r
-\r
- /** Enum for the NDIS hardware states */\r
- enum NDIS_Hardware_Status_t\r
- {\r
- NdisHardwareStatusReady, /**< Hardware Ready to accept commands from the host */\r
- NdisHardwareStatusInitializing, /**< Hardware busy initializing */\r
- NdisHardwareStatusReset, /**< Hardware reset */\r
- NdisHardwareStatusClosing, /**< Hardware currently closing */\r
- NdisHardwareStatusNotReady /**< Hardware not ready to accept commands from the host */\r
- };\r
-\r
- /* Type Defines: */\r
- /** Type define for a RNDIS message header, sent before RNDIS messages */\r
- typedef struct\r
- {\r
- uint32_t MessageType; /**< RNDIS message type, a REMOTE_NDIS_*_MSG constant */\r
- uint32_t MessageLength; /**< Total length of the RNDIS message, in bytes */\r
- } RNDIS_Message_Header_t;\r
-\r
- /** Type define for a RNDIS packet message, used to encapsulate Ethernet packets sent to and from the adapter */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t DataOffset;\r
- uint32_t DataLength;\r
- uint32_t OOBDataOffset;\r
- uint32_t OOBDataLength;\r
- uint32_t NumOOBDataElements;\r
- uint32_t PerPacketInfoOffset;\r
- uint32_t PerPacketInfoLength;\r
- uint32_t VcHandle;\r
- uint32_t Reserved;\r
- } RNDIS_PACKET_MSG_t;\r
- \r
- /** Type define for a RNDIS Initialize command message */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t RequestId;\r
- \r
- uint32_t MajorVersion;\r
- uint32_t MinorVersion;\r
- uint32_t MaxTransferSize;\r
- } RNDIS_INITIALIZE_MSG_t;\r
- \r
- /** Type define for a RNDIS Initialize complete response message */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t RequestId;\r
- uint32_t Status;\r
- \r
- uint32_t MajorVersion;\r
- uint32_t MinorVersion;\r
- uint32_t DeviceFlags;\r
- uint32_t Medium;\r
- uint32_t MaxPacketsPerTransfer;\r
- uint32_t MaxTransferSize;\r
- uint32_t PacketAlignmentFactor;\r
- uint32_t AFListOffset;\r
- uint32_t AFListSize;\r
- } RNDIS_INITIALIZE_CMPLT_t;\r
- \r
- /** Type define for a RNDIS Keepalive command message */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t RequestId;\r
- } RNDIS_KEEPALIVE_MSG_t;\r
-\r
- /** Type define for a RNDIS Keepalive complete message */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t RequestId;\r
- uint32_t Status;\r
- } RNDIS_KEEPALIVE_CMPLT_t;\r
-\r
- /** Type define for a RNDIS Reset complete message */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t Status;\r
-\r
- uint32_t AddressingReset;\r
- } RNDIS_RESET_CMPLT_t;\r
- \r
- /** Type define for a RNDIS Set command message */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t RequestId;\r
- \r
- uint32_t Oid;\r
- uint32_t InformationBufferLength;\r
- uint32_t InformationBufferOffset;\r
- uint32_t DeviceVcHandle;\r
- } RNDIS_SET_MSG_t;\r
-\r
- /** Type define for a RNDIS Set complete response message */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t RequestId;\r
- uint32_t Status;\r
- } RNDIS_SET_CMPLT_t;\r
- \r
- /** Type define for a RNDIS Query command message */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t RequestId;\r
- \r
- uint32_t Oid;\r
- uint32_t InformationBufferLength;\r
- uint32_t InformationBufferOffset;\r
- uint32_t DeviceVcHandle;\r
- } RNDIS_QUERY_MSG_t;\r
- \r
- /** Type define for a RNDIS Query complete response message */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t RequestId;\r
- uint32_t Status;\r
- \r
- uint32_t InformationBufferLength;\r
- uint32_t InformationBufferOffset;\r
- } RNDIS_QUERY_CMPLT_t;\r
- \r
- /* External Variables: */\r
- extern uint8_t RNDISMessageBuffer[];\r
- extern RNDIS_Message_Header_t* MessageHeader;\r
- extern bool ResponseReady;\r
- extern uint8_t CurrRNDISState;\r
-\r
- /* Function Prototypes: */\r
- void ProcessRNDISControlMessage(void);\r
-\r
- #if defined(INCLUDE_FROM_RNDIS_C)\r
- static bool ProcessNDISQuery(uint32_t OId, void* QueryData, uint16_t QuerySize,\r
- void* ResponseData, uint16_t* ResponseSize);\r
- static bool ProcessNDISSet(uint32_t OId, void* SetData, uint16_t SetSize); \r
- #endif\r
- \r
-#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * RNDIS specification related constants. For more information on these\r
- * constants, please refer to the Microsoft RNDIS specification.\r
- */\r
- \r
-#ifndef _RNDIS_CONSTANTS_H_\r
-#define _RNDIS_CONSTANTS_H_\r
-\r
- /* Macros: */\r
- #define REMOTE_NDIS_PACKET_MSG 0x00000001UL\r
- #define REMOTE_NDIS_INITIALIZE_MSG 0x00000002UL\r
- #define REMOTE_NDIS_HALT_MSG 0x00000003UL\r
- #define REMOTE_NDIS_QUERY_MSG 0x00000004UL\r
- #define REMOTE_NDIS_SET_MSG 0x00000005UL\r
- #define REMOTE_NDIS_RESET_MSG 0x00000006UL\r
- #define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007UL\r
- #define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008UL\r
-\r
- #define REMOTE_NDIS_INITIALIZE_CMPLT 0x80000002UL\r
- #define REMOTE_NDIS_QUERY_CMPLT 0x80000004UL\r
- #define REMOTE_NDIS_SET_CMPLT 0x80000005UL\r
- #define REMOTE_NDIS_RESET_CMPLT 0x80000006UL\r
- #define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008UL\r
- \r
- #define REMOTE_NDIS_STATUS_SUCCESS 0x00000000UL\r
- #define REMOTE_NDIS_STATUS_FAILURE 0xC0000001UL\r
- #define REMOTE_NDIS_STATUS_INVALID_DATA 0xC0010015UL\r
- #define REMOTE_NDIS_STATUS_NOT_SUPPORTED 0xC00000BBUL\r
- #define REMOTE_NDIS_STATUS_MEDIA_CONNECT 0x4001000BUL\r
- #define REMOTE_NDIS_STATUS_MEDIA_DISCONNECT 0x4001000CUL\r
- \r
- #define REMOTE_NDIS_MEDIA_STATE_CONNECTED 0x00000000UL\r
- #define REMOTE_NDIS_MEDIA_STATE_DISCONNECTED 0x00000001UL\r
- \r
- #define REMOTE_NDIS_MEDIUM_802_3 0x00000000UL\r
- \r
- #define REMOTE_NDIS_DF_CONNECTIONLESS 0x00000001UL\r
- #define REMOTE_NDIS_DF_CONNECTION_ORIENTED 0x00000002UL\r
- \r
- #define OID_GEN_SUPPORTED_LIST 0x00010101UL\r
- #define OID_GEN_HARDWARE_STATUS 0x00010102UL\r
- #define OID_GEN_MEDIA_SUPPORTED 0x00010103UL\r
- #define OID_GEN_MEDIA_IN_USE 0x00010104UL\r
- #define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106UL\r
- #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL\r
- #define OID_GEN_LINK_SPEED 0x00010107UL\r
- #define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010AUL\r
- #define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010BUL\r
- #define OID_GEN_VENDOR_ID 0x0001010CUL\r
- #define OID_GEN_VENDOR_DESCRIPTION 0x0001010DUL\r
- #define OID_GEN_CURRENT_PACKET_FILTER 0x0001010EUL\r
- #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL\r
- #define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114UL\r
- #define OID_GEN_PHYSICAL_MEDIUM 0x00010202UL\r
- #define OID_GEN_XMIT_OK 0x00020101UL\r
- #define OID_GEN_RCV_OK 0x00020102UL\r
- #define OID_GEN_XMIT_ERROR 0x00020103UL\r
- #define OID_GEN_RCV_ERROR 0x00020104UL\r
- #define OID_GEN_RCV_NO_BUFFER 0x00020105UL\r
- #define OID_802_3_PERMANENT_ADDRESS 0x01010101UL\r
- #define OID_802_3_CURRENT_ADDRESS 0x01010102UL\r
- #define OID_802_3_MULTICAST_LIST 0x01010103UL\r
- #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104UL\r
- #define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101UL\r
- #define OID_802_3_XMIT_ONE_COLLISION 0x01020102UL\r
- #define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103UL\r
-\r
-#endif\r
* level. If an application produces a response, this task constructs the appropriate Ethernet frame and places it into the Ethernet OUT\r
* buffer for later transmission.\r
*/\r
-TASK(TCP_Task)\r
+void TCP_TCPTask(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo)\r
{\r
/* Task to hand off TCP packets to and from the listening applications. */\r
\r
}\r
\r
/* Bail out early if there is already a frame waiting to be sent in the Ethernet OUT buffer */\r
- if (FrameOUT.FrameInBuffer)\r
+ if (RNDISInterfaceInfo->FrameOUT.FrameInBuffer)\r
return;\r
\r
/* Send response packets from each application as the TCP packet buffers are filled by the applications */\r
if ((ConnectionStateTable[CSTableEntry].Info.Buffer.Direction == TCP_PACKETDIR_OUT) &&\r
(ConnectionStateTable[CSTableEntry].Info.Buffer.Ready))\r
{\r
- Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&FrameOUT.FrameData;\r
- IP_Header_t* IPHeaderOUT = (IP_Header_t*)&FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)];\r
- TCP_Header_t* TCPHeaderOUT = (TCP_Header_t*)&FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) +\r
- sizeof(IP_Header_t)]; \r
- void* TCPDataOUT = &FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) +\r
- sizeof(IP_Header_t) +\r
- sizeof(TCP_Header_t)];\r
+ Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&RNDISInterfaceInfo->FrameOUT.FrameData;\r
+ IP_Header_t* IPHeaderOUT = (IP_Header_t*)&RNDISInterfaceInfo->FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)];\r
+ TCP_Header_t* TCPHeaderOUT = (TCP_Header_t*)&RNDISInterfaceInfo->FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) +\r
+ sizeof(IP_Header_t)]; \r
+ void* TCPDataOUT = &RNDISInterfaceInfo->FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) +\r
+ sizeof(IP_Header_t) +\r
+ sizeof(TCP_Header_t)];\r
\r
uint16_t PacketSize = ConnectionStateTable[CSTableEntry].Info.Buffer.Length;\r
\r
PacketSize += sizeof(Ethernet_Frame_Header_t);\r
\r
/* Set the response length in the buffer and indicate that a response is ready to be sent */\r
- FrameOUT.FrameLength = PacketSize;\r
- FrameOUT.FrameInBuffer = true;\r
+ RNDISInterfaceInfo->FrameOUT.FrameLength = PacketSize;\r
+ RNDISInterfaceInfo->FrameOUT.FrameInBuffer = true;\r
\r
ConnectionStateTable[CSTableEntry].Info.Buffer.Ready = false;\r
\r
\r
/* Includes: */\r
#include <avr/io.h>\r
- #include <stdbool.h>\r
- \r
- #include <LUFA/Scheduler/Scheduler.h>\r
+ #include <stdbool.h>
\r
#include "EthernetProtocols.h"\r
#include "Ethernet.h"\r
uint16_t Checksum; /**< TCP checksum */\r
uint16_t UrgentPointer; /**< Urgent data pointer */\r
} TCP_Header_t;\r
-\r
- /* Tasks: */\r
- TASK(TCP_Task);\r
\r
/* External Variables: */\r
TCP_PortState_t PortStateTable[MAX_OPEN_TCP_PORTS];\r
\r
/* Function Prototypes: */\r
+ void TCP_TCPTask(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo);\r
void TCP_Init(void);\r
bool TCP_SetPortState(uint16_t Port, uint8_t State, void (*Handler)(TCP_ConnectionState_t*, TCP_ConnectionBuffer_t*));\r
uint8_t TCP_GetPortState(uint16_t Port);\r
this software.\r
*/\r
\r
-/** \file\r
- *\r
- * Main source file for the RNDISEthernet demo. This file contains the main tasks of the demo and\r
- * is responsible for the initial application hardware configuration.\r
- */\r
-\r
#include "RNDISEthernet.h"\r
\r
-/* Scheduler Task List */\r
-TASK_LIST\r
-{\r
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },\r
- { .Task = Ethernet_Task , .TaskStatus = TASK_STOP },\r
- { .Task = TCP_Task , .TaskStatus = TASK_STOP },\r
- { .Task = RNDIS_Task , .TaskStatus = TASK_STOP },\r
-};\r
+USB_ClassInfo_RNDIS_t Ethernet_RNDIS_Interface =\r
+ {\r
+ .ControlInterfaceNumber = 0,\r
\r
-/** Main program entry point. This routine configures the hardware required by the application, then\r
- * starts the scheduler to run the USB management task.\r
- */\r
+ .DataINEndpointNumber = CDC_TX_EPNUM,\r
+ .DataINEndpointSize = CDC_TXRX_EPSIZE,\r
+\r
+ .DataOUTEndpointNumber = CDC_RX_EPNUM,\r
+ .DataOUTEndpointSize = CDC_TXRX_EPSIZE,\r
+\r
+ .NotificationEndpointNumber = CDC_NOTIFICATION_EPNUM,\r
+ .NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE,\r
+ \r
+ .AdapterVendorDescription = "LUFA RNDIS Demo Adapter",\r
+ .AdapterMACAddress = {ADAPTER_MAC_ADDRESS},\r
+ };\r
+ \r
int main(void)\r
{\r
+ SetupHardware();\r
+\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
+ \r
+ printf_P(PSTR("\r\n\r\n****** RNDIS Demo running. ******\r\n"));\r
+\r
+ for (;;)\r
+ {\r
+ if (Ethernet_RNDIS_Interface.FrameIN.FrameInBuffer)\r
+ {\r
+ LEDs_SetAllLEDs(LEDMASK_USB_BUSY);\r
+ Ethernet_ProcessPacket(&Ethernet_RNDIS_Interface.FrameIN, &Ethernet_RNDIS_Interface.FrameOUT);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
+ }\r
+\r
+ TCP_TCPTask(&Ethernet_RNDIS_Interface);\r
+\r
+ USB_RNDIS_USBTask(&Ethernet_RNDIS_Interface);\r
+ USB_USBTask();\r
+ }\r
+}\r
+\r
+void SetupHardware(void)\r
+{\r
/* Disable watchdog if enabled by bootloader/fuses */\r
MCUSR &= ~(1 << WDRF);\r
wdt_disable();\r
/* Hardware Initialization */\r
LEDs_Init();\r
SerialStream_Init(9600, false);\r
- \r
- /* Webserver Initialization */\r
- TCP_Init();\r
- Webserver_Init();\r
-\r
- printf_P(PSTR("\r\n\r\n****** RNDIS Demo running. ******\r\n"));\r
-\r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
- \r
- /* Initialize Scheduler so that it can be used */\r
- Scheduler_Init();\r
-\r
- /* Initialize USB Subsystem */\r
USB_Init();\r
\r
- /* Scheduling - routine never returns, so put this last in the main function */\r
- Scheduler_Start();\r
+ /* Initialize TCP and Webserver modules */\r
+ TCP_Init();\r
+ Webserver_Init();\r
}\r
\r
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and\r
- * starts the library USB task to begin the enumeration and USB management process.\r
- */\r
void EVENT_USB_Connect(void)\r
{\r
- /* Start USB management task */\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);\r
-\r
- /* Indicate USB enumerating */\r
- UpdateStatus(Status_USBEnumerating);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);\r
}\r
\r
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via\r
- * the status LEDs and stops all the relevant tasks.\r
- */\r
void EVENT_USB_Disconnect(void)\r
{\r
- /* Stop running TCP/IP and USB management tasks */\r
- Scheduler_SetTaskMode(RNDIS_Task, TASK_STOP);\r
- Scheduler_SetTaskMode(Ethernet_Task, TASK_STOP);\r
- Scheduler_SetTaskMode(TCP_Task, TASK_STOP);\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);\r
-\r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
}\r
\r
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host sets the current configuration\r
- * of the USB device after enumeration, and configures the RNDIS device endpoints and starts the relevant tasks.\r
- */\r
void EVENT_USB_ConfigurationChanged(void)\r
{\r
- /* Setup CDC Notification, Rx and Tx Endpoints */\r
- Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK,\r
- ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
\r
- Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK,\r
- ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,\r
- ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- /* Indicate USB connected and ready */\r
- UpdateStatus(Status_USBReady);\r
-\r
- /* Start TCP/IP tasks */\r
- Scheduler_SetTaskMode(RNDIS_Task, TASK_RUN);\r
- Scheduler_SetTaskMode(Ethernet_Task, TASK_RUN);\r
- Scheduler_SetTaskMode(TCP_Task, TASK_RUN);\r
+ if (!(USB_RNDIS_ConfigureEndpoints(&Ethernet_RNDIS_Interface)))\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
}\r
\r
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific\r
- * control requests that are not handled internally by the USB library (including the RNDIS control commands,\r
- * which set up the USB RNDIS network adapter), so that they can be handled appropriately for the application.\r
- */\r
void EVENT_USB_UnhandledControlPacket(void)\r
{\r
- /* Process RNDIS class commands */\r
- switch (USB_ControlRequest.bRequest)\r
- {\r
- case REQ_SendEncapsulatedCommand:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- /* Clear the SETUP packet, ready for data transfer */\r
- Endpoint_ClearSETUP();\r
- \r
- /* Read in the RNDIS message into the message buffer */\r
- Endpoint_Read_Control_Stream_LE(RNDISMessageBuffer, USB_ControlRequest.wLength);\r
-\r
- /* Finalize the stream transfer to clear the last packet from the host */\r
- Endpoint_ClearIN();\r
-\r
- /* Process the RNDIS message */\r
- ProcessRNDISControlMessage();\r
- }\r
- \r
- break;\r
- case REQ_GetEncapsulatedResponse:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- /* Clear the SETUP packet, ready for data transfer */\r
- Endpoint_ClearSETUP();\r
- \r
- /* Check if a response to the last message is ready */\r
- if (!(MessageHeader->MessageLength))\r
- {\r
- /* Set the response to a single 0x00 byte to indicate that no response is ready */\r
- RNDISMessageBuffer[0] = 0;\r
- MessageHeader->MessageLength = 1;\r
- }\r
-\r
- /* Write the message response data to the endpoint */\r
- Endpoint_Write_Control_Stream_LE(RNDISMessageBuffer, MessageHeader->MessageLength);\r
- \r
- /* Finalize the stream transfer to send the last packet or clear the host abort */\r
- Endpoint_ClearOUT();\r
-\r
- /* Reset the message header once again after transmission */\r
- MessageHeader->MessageLength = 0;\r
- }\r
- \r
- break;\r
- }\r
-}\r
-\r
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to\r
- * log to a serial port, or anything else that is suitable for status updates.\r
- *\r
- * \param CurrentStatus Current status of the system, from the RNDISEthernet_StatusCodes_t enum\r
- */\r
-void UpdateStatus(uint8_t CurrentStatus)\r
-{\r
- uint8_t LEDMask = LEDS_NO_LEDS;\r
- \r
- /* Set the LED mask to the appropriate LED mask based on the given status code */\r
- switch (CurrentStatus)\r
- {\r
- case Status_USBNotReady:\r
- LEDMask = (LEDS_LED1);\r
- break;\r
- case Status_USBEnumerating:\r
- LEDMask = (LEDS_LED1 | LEDS_LED2);\r
- break;\r
- case Status_USBReady:\r
- LEDMask = (LEDS_LED2 | LEDS_LED4);\r
- break;\r
- case Status_ProcessingEthernetFrame:\r
- LEDMask = (LEDS_LED2 | LEDS_LED3);\r
- break; \r
- }\r
- \r
- /* Set the board LEDs to the new LED mask */\r
- LEDs_SetAllLEDs(LEDMask);\r
-}\r
-\r
-/** Task to manage the sending and receiving of encapsulated RNDIS data and notifications. This removes the RNDIS\r
- * wrapper from received Ethernet frames and places them in the FrameIN global buffer, or adds the RNDIS wrapper\r
- * to a frame in the FrameOUT global before sending the buffer contents to the host.\r
- */\r
-TASK(RNDIS_Task)\r
-{\r
- /* Select the notification endpoint */\r
- Endpoint_SelectEndpoint(CDC_NOTIFICATION_EPNUM);\r
-\r
- /* Check if a message response is ready for the host */\r
- if (Endpoint_IsINReady() && ResponseReady)\r
- {\r
- USB_Notification_t Notification = (USB_Notification_t)\r
- {\r
- .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),\r
- .bNotification = NOTIF_RESPONSE_AVAILABLE,\r
- .wValue = 0,\r
- .wIndex = 0,\r
- .wLength = 0,\r
- };\r
- \r
- /* Indicate that a message response is ready for the host */\r
- Endpoint_Write_Stream_LE(&Notification, sizeof(Notification));\r
-\r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearIN();\r
-\r
- /* Indicate a response is no longer ready */\r
- ResponseReady = false;\r
- }\r
- \r
- /* Don't process the data endpoints until the system is in the data initialized state, and the buffer is free */\r
- if ((CurrRNDISState == RNDIS_Data_Initialized) && !(MessageHeader->MessageLength))\r
- {\r
- /* Create a new packet header for reading/writing */\r
- RNDIS_PACKET_MSG_t RNDISPacketHeader;\r
-\r
- /* Select the data OUT endpoint */\r
- Endpoint_SelectEndpoint(CDC_RX_EPNUM);\r
- \r
- /* Check if the data OUT endpoint contains data, and that the IN buffer is empty */\r
- if (Endpoint_IsOUTReceived() && !(FrameIN.FrameInBuffer))\r
- {\r
- /* Read in the packet message header */\r
- Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_PACKET_MSG_t));\r
-\r
- /* Stall the request if the data is too large */\r
- if (RNDISPacketHeader.DataLength > ETHERNET_FRAME_SIZE_MAX)\r
- {\r
- Endpoint_StallTransaction();\r
- return;\r
- }\r
- \r
- /* Read in the Ethernet frame into the buffer */\r
- Endpoint_Read_Stream_LE(FrameIN.FrameData, RNDISPacketHeader.DataLength);\r
-\r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearOUT();\r
- \r
- /* Store the size of the Ethernet frame */\r
- FrameIN.FrameLength = RNDISPacketHeader.DataLength;\r
-\r
- /* Indicate Ethernet IN buffer full */\r
- FrameIN.FrameInBuffer = true;\r
- }\r
- \r
- /* Select the data IN endpoint */\r
- Endpoint_SelectEndpoint(CDC_TX_EPNUM);\r
- \r
- /* Check if the data IN endpoint is ready for more data, and that the IN buffer is full */\r
- if (Endpoint_IsINReady() && FrameOUT.FrameInBuffer)\r
- {\r
- /* Clear the packet header with all 0s so that the relevant fields can be filled */\r
- memset(&RNDISPacketHeader, 0, sizeof(RNDIS_PACKET_MSG_t));\r
-\r
- /* Construct the required packet header fields in the buffer */\r
- RNDISPacketHeader.MessageType = REMOTE_NDIS_PACKET_MSG;\r
- RNDISPacketHeader.MessageLength = (sizeof(RNDIS_PACKET_MSG_t) + FrameOUT.FrameLength);\r
- RNDISPacketHeader.DataOffset = (sizeof(RNDIS_PACKET_MSG_t) - sizeof(RNDIS_Message_Header_t));\r
- RNDISPacketHeader.DataLength = FrameOUT.FrameLength;\r
-\r
- /* Send the packet header to the host */\r
- Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_PACKET_MSG_t));\r
-\r
- /* Send the Ethernet frame data to the host */\r
- Endpoint_Write_Stream_LE(FrameOUT.FrameData, RNDISPacketHeader.DataLength);\r
- \r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearIN();\r
- \r
- /* Indicate Ethernet OUT buffer no longer full */\r
- FrameOUT.FrameInBuffer = false;\r
- }\r
- }\r
-}\r
-\r
-/** Ethernet frame processing task. This task checks to see if a frame has been received, and if so hands off the processing\r
- * of the frame to the Ethernet processing routines.\r
- */\r
-TASK(Ethernet_Task)\r
-{\r
- /* Task for Ethernet processing. Incoming ethernet frames are loaded into the FrameIN structure, and\r
- outgoing frames should be loaded into the FrameOUT structure. Both structures can only hold a single\r
- Ethernet frame at a time, so the FrameInBuffer bool is used to indicate when the buffers contain data. */\r
-\r
- /* Check if a frame has been written to the IN frame buffer */\r
- if (FrameIN.FrameInBuffer)\r
- {\r
- /* Indicate packet processing started */\r
- UpdateStatus(Status_ProcessingEthernetFrame);\r
-\r
- /* Process the ethernet frame - replace this with your own Ethernet handler code as desired */\r
- Ethernet_ProcessPacket();\r
-\r
- /* Indicate packet processing complete */\r
- UpdateStatus(Status_USBReady);\r
- }\r
+ USB_RNDIS_ProcessControlPacket(&Ethernet_RNDIS_Interface);\r
}\r
#include <stdio.h>\r
\r
#include "Descriptors.h"\r
-\r
- #include "Lib/RNDIS.h"\r
+
#include "Lib/Ethernet.h"\r
#include "Lib/TCP.h"\r
#include "Lib/ARP.h"\r
#include "Lib/Webserver.h"\r
\r
- #include <LUFA/Version.h> // Library Version Information\r
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver\r
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management\r
- #include <LUFA/Drivers/Peripheral/SerialStream.h> // Serial stream driver\r
- \r
- /* Macros: */\r
- /** Notification value to indicate that a frame is ready to be read by the host. */\r
- #define NOTIF_RESPONSE_AVAILABLE 0x01\r
+ #include <LUFA/Version.h>\r
+ #include <LUFA/Drivers/Board/LEDs.h>\r
+ #include <LUFA/Drivers/Board/Joystick.h>\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/RNDIS.h>\r
\r
- /* Type Defines: */\r
- /** Type define for a RNDIS notification message, for transmission to the RNDIS host via the notification\r
- * Endpoint.\r
- */\r
- typedef struct\r
- {\r
- uint8_t bmRequestType; /**< Notification type, a mask of values from SrdRequestType.h */\r
- uint8_t bNotification; /**< Notification index, indicating what the RNDIS notification relates to */\r
- uint16_t wValue; /**< Two byte notification value parameter */\r
- uint16_t wIndex; /**< Two byte notification index parameter */\r
- uint16_t wLength; /**< Size of data payload following the notification header */\r
- } USB_Notification_t;\r
-\r
- /* Enums: */\r
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */\r
- enum RNDISEthernet_StatusCodes_t\r
- {\r
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */\r
- Status_USBEnumerating = 1, /**< USB interface is enumerating */\r
- Status_USBReady = 2, /**< USB interface is connected and ready */\r
- Status_ProcessingEthernetFrame = 3, /**< Currently processing an ethernet frame from the host */\r
- };\r
+ /* Macros: */\r
+ #define LEDMASK_USB_NOTREADY LEDS_LED1\r
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)\r
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)\r
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)\r
+ #define LEDMASK_USB_BUSY LEDS_LED2\r
\r
- /* Tasks: */\r
- TASK(RNDIS_Task);\r
- TASK(Ethernet_Task);\r
-\r
/* Function Prototypes: */\r
+ void SetupHardware(void);\r
+\r
void EVENT_USB_Connect(void);\r
void EVENT_USB_Disconnect(void);\r
void EVENT_USB_ConfigurationChanged(void);\r
void EVENT_USB_UnhandledControlPacket(void);\r
-\r
- void UpdateStatus(uint8_t CurrentStatus);\r
+ void EVENT_USB_StartOfFrame(void);\r
+ \r
+ void CALLBACK_USB_RNDIS_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo);\r
\r
#endif\r
# List C source files here. (C dependencies are automatically generated.)\r
SRC = $(TARGET).c \\r
Descriptors.c \\r
- Lib/RNDIS.c \\r
Lib/Ethernet.c \\r
Lib/ProtocolDecoders.c \\r
Lib/ICMP.c \\r
Lib/ARP.c \\r
Lib/IP.c \\r
Lib/Webserver.c \\r
- $(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \\r
$(LUFA_PATH)/LUFA/Drivers/Peripheral/SerialStream.c \\r
$(LUFA_PATH)/LUFA/Drivers/Peripheral/Serial.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \\r
- $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \\r
+ $(LUFA_PATH)/LUFA/Drivers/USB/Class/Device/RNDIS.c \\r
\r
\r
# List C++ source files here. (C dependencies are automatically generated.)\r
\r
# Place -D or -U options here for C sources\r
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)\r
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY\r
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY\r
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION\r
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"\r
CDEFS += -DNO_DECODE_ETHERNET -DNO_DECODE_ARP -DNO_DECODE_ICMP -DNO_DECODE_IP -DNO_DECODE_TCP -DNO_DECODE_UDP -DNO_DECODE_DHCP\r
#define _DESCRIPTORS_H_\r
\r
/* Includes: */\r
- #include <LUFA/Drivers/USB/USB.h>\r
-\r
#include <avr/pgmspace.h>\r
\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/CDC.h>\r
+\r
/* Macros: */\r
- /** Macro to define a CDC class-specific functional descriptor. CDC functional descriptors have a\r
- * uniform structure but variable sized data payloads, thus cannot be represented accurately by\r
- * a single typedef struct. A macro is used instead so that functional descriptors can be created\r
- * easily by specifying the size of the payload. This allows sizeof() to work correctly.\r
- *\r
- * \param DataSize Size in bytes of the CDC functional descriptor's data payload\r
- */\r
- #define CDC_FUNCTIONAL_DESCRIPTOR(DataSize) \\r
- struct \\r
- { \\r
- USB_Descriptor_Header_t Header; \\r
- uint8_t SubType; \\r
- uint8_t Data[DataSize]; \\r
- }\r
- \r
/** Endpoint number of the CDC device-to-host notification IN endpoint. */\r
#define CDC_NOTIFICATION_EPNUM 2\r
\r
\r
#include "USBtoSerial.h"\r
\r
-/* Scheduler Task List */\r
-TASK_LIST\r
-{\r
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },\r
- { .Task = CDC_Task , .TaskStatus = TASK_STOP },\r
-};\r
+RingBuff_t Rx_Buffer;\r
+RingBuff_t Tx_Buffer;\r
\r
-/* Globals: */\r
-/** Contains the current baud rate and other settings of the virtual serial port.\r
- *\r
- * These values are set by the host via a class-specific request, and the physical USART should be reconfigured to match the\r
- * new settings each time they are changed by the host.\r
- */\r
-CDC_Line_Coding_t LineCoding = { .BaudRateBPS = 9600,\r
- .CharFormat = OneStopBit,\r
- .ParityType = Parity_None,\r
- .DataBits = 8 };\r
+USB_ClassInfo_CDC_t VirtualSerial_CDC_Interface =\r
+ {\r
+ .ControlInterfaceNumber = 0,\r
\r
-/** Ring (circular) buffer to hold the RX data - data from the host to the attached device on the serial port. */\r
-RingBuff_t Rx_Buffer;\r
+ .DataINEndpointNumber = CDC_TX_EPNUM,\r
+ .DataINEndpointSize = CDC_TXRX_EPSIZE,\r
\r
-/** Ring (circular) buffer to hold the TX data - data from the attached device on the serial port to the host. */\r
-RingBuff_t Tx_Buffer;\r
+ .DataOUTEndpointNumber = CDC_RX_EPNUM,\r
+ .DataOUTEndpointSize = CDC_TXRX_EPSIZE,\r
\r
-/** Flag to indicate if the USART is currently transmitting data from the Rx_Buffer circular buffer. */\r
-volatile bool Transmitting = false;\r
+ .NotificationEndpointNumber = CDC_NOTIFICATION_EPNUM,\r
+ .NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE,\r
+ };\r
\r
-/** Main program entry point. This routine configures the hardware required by the application, then\r
- * starts the scheduler to run the application tasks.\r
- */\r
int main(void)\r
{\r
+ SetupHardware();\r
+ \r
+ Buffer_Initialize(&Rx_Buffer);\r
+ Buffer_Initialize(&Tx_Buffer);\r
+\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
+\r
+ for (;;)\r
+ {\r
+ for (uint8_t DataBytesRem = USB_CDC_BytesReceived(&VirtualSerial_CDC_Interface); DataBytesRem != 0; DataBytesRem--)\r
+ {\r
+ if (!(BUFF_STATICSIZE - Rx_Buffer.Elements))\r
+ break;\r
+ \r
+ Buffer_StoreElement(&Rx_Buffer, USB_CDC_ReceiveByte(&VirtualSerial_CDC_Interface));\r
+ }\r
+ \r
+ if (Tx_Buffer.Elements)\r
+ USB_CDC_SendByte(&VirtualSerial_CDC_Interface, Buffer_GetElement(&Rx_Buffer));\r
+ \r
+ if (Rx_Buffer.Elements)\r
+ Serial_TxByte(Buffer_GetElement(&Rx_Buffer));\r
+ \r
+ USB_CDC_USBTask(&VirtualSerial_CDC_Interface);\r
+ USB_USBTask();\r
+ }\r
+}\r
+\r
+void SetupHardware(void)\r
+{\r
/* Disable watchdog if enabled by bootloader/fuses */\r
MCUSR &= ~(1 << WDRF);\r
wdt_disable();\r
clock_prescale_set(clock_div_1);\r
\r
/* Hardware Initialization */\r
+ Joystick_Init();\r
LEDs_Init();\r
- ReconfigureUSART();\r
- \r
- /* Ring buffer Initialization */\r
- Buffer_Initialize(&Rx_Buffer);\r
- Buffer_Initialize(&Tx_Buffer);\r
- \r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
- \r
- /* Initialize Scheduler so that it can be used */\r
- Scheduler_Init();\r
-\r
- /* Initialize USB Subsystem */\r
USB_Init();\r
-\r
- /* Scheduling - routine never returns, so put this last in the main function */\r
- Scheduler_Start();\r
}\r
\r
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and\r
- * starts the library USB task to begin the enumeration and USB management process.\r
- */\r
void EVENT_USB_Connect(void)\r
{\r
- /* Start USB management task */\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);\r
-\r
- /* Indicate USB enumerating */\r
- UpdateStatus(Status_USBEnumerating);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);\r
}\r
\r
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via\r
- * the status LEDs and stops the USB management and CDC management tasks.\r
- */\r
void EVENT_USB_Disconnect(void)\r
{\r
- /* Stop running CDC and USB management tasks */\r
- Scheduler_SetTaskMode(CDC_Task, TASK_STOP);\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);\r
- \r
- /* Reset Tx and Rx buffers, device disconnected */\r
- Buffer_Initialize(&Rx_Buffer);\r
- Buffer_Initialize(&Tx_Buffer);\r
-\r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
}\r
\r
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration\r
- * of the USB device after enumeration - the device endpoints are configured and the CDC management task started.\r
- */\r
void EVENT_USB_ConfigurationChanged(void)\r
{\r
- /* Setup CDC Notification, Rx and Tx Endpoints */\r
- Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,\r
- ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK,\r
- ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
\r
- Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK,\r
- ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- /* Indicate USB connected and ready */\r
- UpdateStatus(Status_USBReady);\r
-\r
- /* Start CDC task */\r
- Scheduler_SetTaskMode(CDC_Task, TASK_RUN);\r
+ if (!(USB_CDC_ConfigureEndpoints(&VirtualSerial_CDC_Interface)))\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
}\r
\r
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific\r
- * control requests that are not handled internally by the USB library (including the CDC control commands,\r
- * which are all issued via the control endpoint), so that they can be handled appropriately for the application.\r
- */\r
void EVENT_USB_UnhandledControlPacket(void)\r
{\r
- uint8_t* LineCodingData = (uint8_t*)&LineCoding;\r
-\r
- /* Process CDC specific control requests */\r
- switch (USB_ControlRequest.bRequest)\r
- {\r
- case REQ_GetLineEncoding:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
- { \r
- /* Acknowledge the SETUP packet, ready for data transfer */\r
- Endpoint_ClearSETUP();\r
-\r
- /* Write the line coding data to the control endpoint */\r
- Endpoint_Write_Control_Stream_LE(LineCodingData, sizeof(LineCoding));\r
- \r
- /* Finalize the stream transfer to send the last packet or clear the host abort */\r
- Endpoint_ClearOUT();\r
- }\r
- \r
- break;\r
- case REQ_SetLineEncoding:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- /* Acknowledge the SETUP packet, ready for data transfer */\r
- Endpoint_ClearSETUP();\r
-\r
- /* Read the line coding data in from the host into the global struct */\r
- Endpoint_Read_Control_Stream_LE(LineCodingData, sizeof(LineCoding));\r
-\r
- /* Finalize the stream transfer to clear the last packet from the host */\r
- Endpoint_ClearIN();\r
- \r
- /* Reconfigure the USART with the new settings */\r
- ReconfigureUSART();\r
- }\r
- \r
- break;\r
- case REQ_SetControlLineState:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- { \r
- /* Acknowledge the SETUP packet, ready for data transfer */\r
- Endpoint_ClearSETUP();\r
- \r
- /* NOTE: Here you can read in the line state mask from the host, to get the current state of the output handshake\r
- lines. The mask is read in from the wValue parameter in USB_ControlRequest, and can be masked against the\r
- CONTROL_LINE_OUT_* masks to determine the RTS and DTR line states using the following code:\r
- */\r
-\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
- }\r
- \r
- break;\r
- }\r
-}\r
-\r
-/** Task to manage CDC data transmission and reception to and from the host, from and to the physical USART. */\r
-TASK(CDC_Task)\r
-{\r
- if (USB_IsConnected)\r
- {\r
-#if 0\r
- /* NOTE: Here you can use the notification endpoint to send back line state changes to the host, for the special RS-232\r
- handshake signal lines (and some error states), via the CONTROL_LINE_IN_* masks and the following code:\r
- */\r
-\r
- USB_Notification_Header_t Notification = (USB_Notification_Header_t)\r
- {\r
- .NotificationType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),\r
- .Notification = NOTIF_SerialState,\r
- .wValue = 0,\r
- .wIndex = 0,\r
- .wLength = sizeof(uint16_t),\r
- };\r
- \r
- uint16_t LineStateMask;\r
- \r
- // Set LineStateMask here to a mask of CONTROL_LINE_IN_* masks to set the input handshake line states to send to the host\r
- \r
- Endpoint_SelectEndpoint(CDC_NOTIFICATION_EPNUM);\r
- Endpoint_Write_Stream_LE(&Notification, sizeof(Notification));\r
- Endpoint_Write_Stream_LE(&LineStateMask, sizeof(LineStateMask));\r
- Endpoint_ClearIN();\r
-#endif\r
-\r
- /* Select the Serial Rx Endpoint */\r
- Endpoint_SelectEndpoint(CDC_RX_EPNUM);\r
- \r
- /* Check to see if a packet has been received from the host */\r
- if (Endpoint_IsOUTReceived())\r
- {\r
- /* Read the bytes in from the endpoint into the buffer while space is available */\r
- while (Endpoint_BytesInEndpoint() && (BUFF_STATICSIZE - Rx_Buffer.Elements))\r
- {\r
- /* Store each character from the endpoint */\r
- Buffer_StoreElement(&Rx_Buffer, Endpoint_Read_Byte());\r
- }\r
- \r
- /* Check to see if all bytes in the current packet have been read */\r
- if (!(Endpoint_BytesInEndpoint()))\r
- {\r
- /* Clear the endpoint buffer */\r
- Endpoint_ClearOUT();\r
- }\r
- }\r
- \r
- /* Check if Rx buffer contains data - if so, send it */\r
- if (Rx_Buffer.Elements)\r
- Serial_TxByte(Buffer_GetElement(&Rx_Buffer));\r
-\r
- /* Select the Serial Tx Endpoint */\r
- Endpoint_SelectEndpoint(CDC_TX_EPNUM);\r
-\r
- /* Check if the Tx buffer contains anything to be sent to the host */\r
- if (Tx_Buffer.Elements)\r
- {\r
- /* Wait until Serial Tx Endpoint Ready for Read/Write */\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
- \r
- /* Write the bytes from the buffer to the endpoint while space is available */\r
- while (Tx_Buffer.Elements && (Endpoint_BytesInEndpoint() < CDC_TXRX_EPSIZE))\r
- {\r
- /* Write each byte retreived from the buffer to the endpoint */\r
- Endpoint_Write_Byte(Buffer_GetElement(&Tx_Buffer));\r
- }\r
- \r
- /* Remember if the packet to send completely fills the endpoint */\r
- bool IsFull = (Endpoint_BytesInEndpoint() == CDC_TXRX_EPSIZE);\r
- \r
- /* Send the data */\r
- Endpoint_ClearIN();\r
-\r
- /* If no more data to send and the last packet filled the endpoint, send an empty packet to release\r
- * the buffer on the receiver (otherwise all data will be cached until a non-full packet is received) */\r
- if (IsFull && !(Tx_Buffer.Elements))\r
- {\r
- /* Wait until Serial Tx Endpoint Ready for Read/Write */\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
-\r
- /* Send an empty packet to terminate the transfer */\r
- Endpoint_ClearIN();\r
- }\r
- }\r
- }\r
+ USB_CDC_ProcessControlPacket(&VirtualSerial_CDC_Interface);\r
}\r
\r
-/** ISR to handle the USART receive complete interrupt, fired each time the USART has received a character. This stores the received\r
- * character into the Tx_Buffer circular buffer for later transmission to the host.\r
- */\r
ISR(USART1_RX_vect, ISR_BLOCK)\r
{\r
- /* Only store received characters if the USB interface is connected */\r
if (USB_IsConnected)\r
- {\r
- /* Character received, store it into the buffer */\r
- Buffer_StoreElement(&Tx_Buffer, UDR1);\r
- }\r
+ Buffer_StoreElement(&Tx_Buffer, UDR1);\r
}\r
\r
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to\r
- * log to a serial port, or anything else that is suitable for status updates.\r
- *\r
- * \param CurrentStatus Current status of the system, from the USBtoSerial_StatusCodes_t enum\r
- */\r
-void UpdateStatus(uint8_t CurrentStatus)\r
-{\r
- uint8_t LEDMask = LEDS_NO_LEDS;\r
- \r
- /* Set the LED mask to the appropriate LED mask based on the given status code */\r
- switch (CurrentStatus)\r
- {\r
- case Status_USBNotReady:\r
- LEDMask = (LEDS_LED1);\r
- break;\r
- case Status_USBEnumerating:\r
- LEDMask = (LEDS_LED1 | LEDS_LED2);\r
- break;\r
- case Status_USBReady:\r
- LEDMask = (LEDS_LED2 | LEDS_LED4);\r
- break;\r
- }\r
- \r
- /* Set the board LEDs to the new LED mask */\r
- LEDs_SetAllLEDs(LEDMask);\r
-}\r
-\r
-/** Reconfigures the USART to match the current serial port settings issued by the host as closely as possible. */\r
-void ReconfigureUSART(void)\r
+void EVENT_USB_CDC_LineEncodingChanged(USB_ClassInfo_CDC_t* CDCInterfaceInfo)\r
{\r
uint8_t ConfigMask = 0;\r
\r
- /* Determine parity - non odd/even parity mode defaults to no parity */\r
- if (LineCoding.ParityType == Parity_Odd)\r
+ if (CDCInterfaceInfo->LineEncoding.ParityType == Parity_Odd)\r
ConfigMask = ((1 << UPM11) | (1 << UPM10));\r
- else if (LineCoding.ParityType == Parity_Even)\r
+ else if (CDCInterfaceInfo->LineEncoding.ParityType == Parity_Even)\r
ConfigMask = (1 << UPM11);\r
\r
- /* Determine stop bits - 1.5 stop bits is set as 1 stop bit due to hardware limitations */\r
- if (LineCoding.CharFormat == TwoStopBits)\r
+ if (CDCInterfaceInfo->LineEncoding.CharFormat == TwoStopBits)\r
ConfigMask |= (1 << USBS1);\r
\r
- /* Determine data size - 5, 6, 7, or 8 bits are supported */\r
- if (LineCoding.DataBits == 6)\r
+ if (CDCInterfaceInfo->LineEncoding.DataBits == 6)\r
ConfigMask |= (1 << UCSZ10);\r
- else if (LineCoding.DataBits == 7)\r
+ else if (CDCInterfaceInfo->LineEncoding.DataBits == 7)\r
ConfigMask |= (1 << UCSZ11);\r
- else if (LineCoding.DataBits == 8)\r
+ else if (CDCInterfaceInfo->LineEncoding.DataBits == 8)\r
ConfigMask |= ((1 << UCSZ11) | (1 << UCSZ10));\r
\r
- /* Enable double speed, gives better error percentages at 8MHz */\r
- UCSR1A = (1 << U2X1);\r
- \r
- /* Enable transmit and receive modules and interrupts */\r
+ UCSR1A = (1 << U2X1); \r
UCSR1B = ((1 << RXCIE1) | (1 << TXEN1) | (1 << RXEN1));\r
-\r
- /* Set the USART mode to the mask generated by the Line Coding options */\r
- UCSR1C = ConfigMask;\r
- \r
- /* Set the USART baud rate register to the desired baud rate value */\r
- UBRR1 = SERIAL_2X_UBBRVAL((uint16_t)LineCoding.BaudRateBPS);\r
+ UCSR1C = ConfigMask; \r
+ UBRR1 = SERIAL_2X_UBBRVAL((uint16_t)CDCInterfaceInfo->LineEncoding.BaudRateBPS);\r
}\r
\r
#include "Lib/RingBuff.h"\r
\r
- #include <LUFA/Version.h> // Library Version Information\r
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
- #include <LUFA/Drivers/Peripheral/Serial.h> // USART driver\r
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver\r
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management\r
+ #include <LUFA/Version.h>\r
+ #include <LUFA/Drivers/Board/LEDs.h>\r
+ #include <LUFA/Drivers/Board/Joystick.h>\r
+ #include <LUFA/Drivers/Peripheral/Serial.h>\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/CDC.h>\r
\r
/* Macros: */\r
- /** CDC Class specific request to get the current virtual serial port configuration settings. */\r
- #define REQ_GetLineEncoding 0x21\r
-\r
- /** CDC Class specific request to set the current virtual serial port configuration settings. */\r
- #define REQ_SetLineEncoding 0x20\r
-\r
- /** CDC Class specific request to set the current virtual serial port handshake line states. */\r
- #define REQ_SetControlLineState 0x22\r
- \r
- /** Notification type constant for a change in the virtual serial port handshake line states, for\r
- * use with a USB_Notification_Header_t notification structure when sent to the host via the CDC \r
- * notification endpoint.\r
- */\r
- #define NOTIF_SerialState 0x20\r
-\r
- /** Mask for the DTR handshake line for use with the REQ_SetControlLineState class specific request\r
- * from the host, to indicate that the DTR line state should be high.\r
- */\r
- #define CONTROL_LINE_OUT_DTR (1 << 0)\r
-\r
- /** Mask for the RTS handshake line for use with the REQ_SetControlLineState class specific request\r
- * from the host, to indicate that theRTS line state should be high.\r
- */\r
- #define CONTROL_LINE_OUT_RTS (1 << 1)\r
+ #define LEDMASK_USB_NOTREADY LEDS_LED1\r
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)\r
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)\r
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)\r
\r
- /** Mask for the DCD handshake line for use with the a NOTIF_SerialState class specific notification\r
- * from the device to the host, to indicate that the DCD line state is currently high.\r
- */\r
- #define CONTROL_LINE_IN_DCD (1 << 0)\r
-\r
- /** Mask for the DSR handshake line for use with the a NOTIF_SerialState class specific notification\r
- * from the device to the host, to indicate that the DSR line state is currently high.\r
- */\r
- #define CONTROL_LINE_IN_DSR (1 << 1)\r
-\r
- /** Mask for the BREAK handshake line for use with the a NOTIF_SerialState class specific notification\r
- * from the device to the host, to indicate that the BREAK line state is currently high.\r
- */\r
- #define CONTROL_LINE_IN_BREAK (1 << 2)\r
-\r
- /** Mask for the RING handshake line for use with the a NOTIF_SerialState class specific notification\r
- * from the device to the host, to indicate that the RING line state is currently high.\r
- */\r
- #define CONTROL_LINE_IN_RING (1 << 3)\r
-\r
- /** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,\r
- * to indicate that a framing error has occurred on the virtual serial port.\r
- */\r
- #define CONTROL_LINE_IN_FRAMEERROR (1 << 4)\r
-\r
- /** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,\r
- * to indicate that a parity error has occurred on the virtual serial port.\r
- */\r
- #define CONTROL_LINE_IN_PARITYERROR (1 << 5)\r
-\r
- /** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,\r
- * to indicate that a data overrun error has occurred on the virtual serial port.\r
- */\r
- #define CONTROL_LINE_IN_OVERRUNERROR (1 << 6)\r
- \r
- /* Type Defines: */\r
- /** Type define for the virtual serial port line encoding settings, for storing the current USART configuration\r
- * as set by the host via a class specific request.\r
- */\r
- typedef struct\r
- {\r
- uint32_t BaudRateBPS; /**< Baud rate of the virtual serial port, in bits per second */\r
- uint8_t CharFormat; /**< Character format of the virtual serial port, a value from the\r
- * CDCDevice_CDC_LineCodingFormats_t enum\r
- */\r
- uint8_t ParityType; /**< Parity setting of the virtual serial port, a value from the\r
- * CDCDevice_LineCodingParity_t enum\r
- */\r
- uint8_t DataBits; /**< Bits of data per character of the virtual serial port */\r
- } CDC_Line_Coding_t;\r
- \r
- /** Type define for a CDC notification, sent to the host via the CDC notification endpoint to indicate a\r
- * change in the device state asynchronously.\r
- */\r
- typedef struct\r
- {\r
- uint8_t NotificationType; /**< Notification type, a mask of REQDIR_*, REQTYPE_* and REQREC_* constants\r
- * from the library StdRequestType.h header\r
- */\r
- uint8_t Notification; /**< Notification value, a NOTIF_* constant */\r
- uint16_t wValue; /**< Notification wValue, notification-specific */\r
- uint16_t wIndex; /**< Notification wIndex, notification-specific */\r
- uint16_t wLength; /**< Notification wLength, notification-specific */\r
- } USB_Notification_Header_t;\r
- \r
- /* Enums: */\r
- /** Enum for the possible line encoding formats of a virtual serial port. */\r
- enum CDCDevice_CDC_LineCodingFormats_t\r
- {\r
- OneStopBit = 0, /**< Each frame contains one stop bit */\r
- OneAndAHalfStopBits = 1, /**< Each frame contains one and a half stop bits */\r
- TwoStopBits = 2, /**< Each frame contains two stop bits */\r
- };\r
- \r
- /** Enum for the possible line encoding parity settings of a virtual serial port. */\r
- enum CDCDevice_LineCodingParity_t\r
- {\r
- Parity_None = 0, /**< No parity bit mode on each frame */\r
- Parity_Odd = 1, /**< Odd parity bit mode on each frame */\r
- Parity_Even = 2, /**< Even parity bit mode on each frame */\r
- Parity_Mark = 3, /**< Mark parity bit mode on each frame */\r
- Parity_Space = 4, /**< Space parity bit mode on each frame */\r
- };\r
-\r
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */\r
- enum USBtoSerial_StatusCodes_t\r
- {\r
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */\r
- Status_USBEnumerating = 1, /**< USB interface is enumerating */\r
- Status_USBReady = 2, /**< USB interface is connected and ready */\r
- };\r
- \r
- /* Tasks: */\r
- TASK(CDC_Task);\r
-\r
/* Function Prototypes: */\r
+ void SetupHardware(void);\r
+\r
void EVENT_USB_Connect(void);\r
void EVENT_USB_Disconnect(void);\r
void EVENT_USB_ConfigurationChanged(void);\r
void EVENT_USB_UnhandledControlPacket(void);\r
-\r
- void ReconfigureUSART(void);\r
- void UpdateStatus(uint8_t CurrentStatus);\r
+ void EVENT_USB_StartOfFrame(void);\r
+ \r
+ void EVENT_USB_CDC_LineEncodingChanged(USB_ClassInfo_CDC_t* CDCInterfaceInfo);\r
\r
#endif\r
SRC = $(TARGET).c \\r
Descriptors.c \\r
Lib/RingBuff.c \\r
- $(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Endpoint.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Host.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \\r
- $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \\r
+ $(LUFA_PATH)/LUFA/Drivers/USB/Class/Device/CDC.c \\r
\r
\r
# List C++ source files here. (C dependencies are automatically generated.)\r
\r
# Place -D or -U options here for C sources\r
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)\r
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY\r
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY\r
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION\r
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"\r
\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \\r
- $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \\r
+ $(LUFA_PATH)/LUFA/Drivers/USB/Class/Host/HIDParser.c \\r
\r
\r
# List C++ source files here. (C dependencies are automatically generated.)\r
while (!(Pipe_IsINReceived()))\r
{\r
/* Check to see if a new frame has been issued (1ms elapsed) */\r
- if (USB_INT_HasOccurred(USB_INT_HSOFI))\r
+ if (FrameElapsed)\r
{\r
/* Clear the flag and decrement the timeout period counter */\r
- USB_INT_Clear(USB_INT_HSOFI);\r
+ FrameElapsed = false;\r
TimeoutMSRem--;\r
\r
/* Check to see if the timeout period for the command has elapsed */\r
while (!(Pipe_IsReadWriteAllowed()))\r
{\r
/* Check to see if a new frame has been issued (1ms elapsed) */\r
- if (USB_INT_HasOccurred(USB_INT_HSOFI))\r
+ if (FrameElapsed)\r
{\r
/* Clear the flag and decrement the timeout period counter */\r
- USB_INT_Clear(USB_INT_HSOFI);\r
+ FrameElapsed = false;\r
TimeoutMSRem--;\r
\r
/* Check to see if the timeout period for the command has elapsed */\r
#include <LUFA/Version.h> // Library Version Information\r
#include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
#include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management\r
- #include <LUFA/MemoryAllocator/DynAlloc.h> // Auto-defragmenting Dynamic Memory allocation\r
#include <LUFA/Drivers/Misc/TerminalCodes.h> // ANSI Terminal Escape Codes\r
#include <LUFA/Drivers/Peripheral/ADC.h> // ADC driver\r
#include <LUFA/Drivers/Peripheral/SerialStream.h> // USART Stream driver\r
TestEvents.c \\r
Descriptors.c \\r
$(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \\r
- $(LUFA_PATH)/LUFA/MemoryAllocator/DynAlloc.c \\r
$(LUFA_PATH)/LUFA/Drivers/Board/Temperature.c \\r
$(LUFA_PATH)/LUFA/Drivers/Peripheral/SerialStream.c \\r
$(LUFA_PATH)/LUFA/Drivers/Peripheral/Serial.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \\r
- $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \\r
\r
\r
# List C++ source files here. (C dependencies are automatically generated.)\r
# Place -D or -U options here for C sources\r
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)\r
CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES\r
-CDEFS += -DNUM_BLOCKS=100 -DBLOCK_SIZE=8 -DNUM_HANDLES=20\r
\r
\r
# Place -D or -U options here for ASM sources\r
-<Project name="LUFA"><Folder name="Demos"><Folder name="Device"><Folder name="AudioInput"><File path="Demos\Device\AudioInput\AudioInput.c"></File><File path="Demos\Device\AudioInput\AudioInput.h"></File><File path="Demos\Device\AudioInput\AudioInput.txt"></File><File path="Demos\Device\AudioInput\Descriptors.c"></File><File path="Demos\Device\AudioInput\Descriptors.h"></File><File path="Demos\Device\AudioInput\Doxygen.conf"></File><File path="Demos\Device\AudioInput\makefile"></File></Folder><Folder name="AudioOutput"><File path="Demos\Device\AudioOutput\AudioOutput.c"></File><File path="Demos\Device\AudioOutput\AudioOutput.h"></File><File path="Demos\Device\AudioOutput\AudioOutput.txt"></File><File path="Demos\Device\AudioOutput\Descriptors.c"></File><File path="Demos\Device\AudioOutput\Descriptors.h"></File><File path="Demos\Device\AudioOutput\Doxygen.conf"></File><File path="Demos\Device\AudioOutput\makefile"></File></Folder><Folder name="CDC"><File path="Demos\Device\CDC\CDC.c"></File><File path="Demos\Device\CDC\CDC.h"></File><File path="Demos\Device\CDC\CDC.txt"></File><File path="Demos\Device\CDC\Descriptors.c"></File><File path="Demos\Device\CDC\Descriptors.h"></File><File path="Demos\Device\CDC\Doxygen.conf"></File><File path="Demos\Device\CDC\LUFA CDC.inf"></File><File path="Demos\Device\CDC\makefile"></File></Folder><Folder name="DualCDC"><File path="Demos\Device\DualCDC\Descriptors.c"></File><File path="Demos\Device\DualCDC\Descriptors.h"></File><File path="Demos\Device\DualCDC\Doxygen.conf"></File><File path="Demos\Device\DualCDC\DualCDC.c"></File><File path="Demos\Device\DualCDC\DualCDC.h"></File><File path="Demos\Device\DualCDC\DualCDC.txt"></File><File path="Demos\Device\DualCDC\LUFA DualCDC.inf"></File><File path="Demos\Device\DualCDC\makefile"></File></Folder><Folder name="GenericHID"><File path="Demos\Device\GenericHID\Descriptors.c"></File><File path="Demos\Device\GenericHID\Descriptors.h"></File><File path="Demos\Device\GenericHID\GenericHID.c"></File><File path="Demos\Device\GenericHID\GenericHID.h"></File><File path="Demos\Device\GenericHID\makefile"></File><File path="Demos\Device\GenericHID\GenericHID.txt"></File><File path="Demos\Device\GenericHID\Doxygen.conf"></File></Folder><Folder name="Joystick"><File path="Demos\Device\Joystick\Descriptors.c"></File><File path="Demos\Device\Joystick\Descriptors.h"></File><File path="Demos\Device\Joystick\Doxygen.conf"></File><File path="Demos\Device\Joystick\Joystick.c"></File><File path="Demos\Device\Joystick\Joystick.h"></File><File path="Demos\Device\Joystick\Joystick.txt"></File><File path="Demos\Device\Joystick\makefile"></File></Folder><Folder name="Keyboard"><File path="Demos\Device\Keyboard\Descriptors.c"></File><File path="Demos\Device\Keyboard\Descriptors.h"></File><File path="Demos\Device\Keyboard\Doxygen.conf"></File><File path="Demos\Device\Keyboard\Keyboard.c"></File><File path="Demos\Device\Keyboard\Keyboard.h"></File><File path="Demos\Device\Keyboard\Keyboard.txt"></File><File path="Demos\Device\Keyboard\makefile"></File></Folder><Folder name="KeyboardMouse"><File path="Demos\Device\KeyboardMouse\Descriptors.c"></File><File path="Demos\Device\KeyboardMouse\Descriptors.h"></File><File path="Demos\Device\KeyboardMouse\Doxygen.conf"></File><File path="Demos\Device\KeyboardMouse\KeyboardMouse.c"></File><File path="Demos\Device\KeyboardMouse\KeyboardMouse.h"></File><File path="Demos\Device\KeyboardMouse\KeyboardMouse.txt"></File><File path="Demos\Device\KeyboardMouse\makefile"></File></Folder><Folder name="MassStorage"><Folder name="Lib"><File path="Demos\Device\MassStorage\Lib\DataflashManager.c"></File><File path="Demos\Device\MassStorage\Lib\DataflashManager.h"></File><File path="Demos\Device\MassStorage\Lib\SCSI.c"></File><File path="Demos\Device\MassStorage\Lib\SCSI.h"></File><File path="Demos\Device\MassStorage\Lib\SCSI_Codes.h"></File></Folder><File path="Demos\Device\MassStorage\Descriptors.c"></File><File path="Demos\Device\MassStorage\Descriptors.h"></File><File path="Demos\Device\MassStorage\Doxygen.conf"></File><File path="Demos\Device\MassStorage\makefile"></File><File path="Demos\Device\MassStorage\MassStorage.c"></File><File path="Demos\Device\MassStorage\MassStorage.h"></File><File path="Demos\Device\MassStorage\MassStorage.txt"></File></Folder><Folder name="MIDI"><File path="Demos\Device\MIDI\Descriptors.c"></File><File path="Demos\Device\MIDI\Descriptors.h"></File><File path="Demos\Device\MIDI\Doxygen.conf"></File><File path="Demos\Device\MIDI\makefile"></File><File path="Demos\Device\MIDI\MIDI.c"></File><File path="Demos\Device\MIDI\MIDI.h"></File><File path="Demos\Device\MIDI\MIDI.txt"></File></Folder><Folder name="Mouse"><File path="Demos\Device\Mouse\Descriptors.c"></File><File path="Demos\Device\Mouse\Descriptors.h"></File><File path="Demos\Device\Mouse\Doxygen.conf"></File><File path="Demos\Device\Mouse\makefile"></File><File path="Demos\Device\Mouse\Mouse.c"></File><File path="Demos\Device\Mouse\Mouse.h"></File><File path="Demos\Device\Mouse\Mouse.txt"></File></Folder><Folder name="RNDISEthernet"><Folder name="Lib"><File path="Demos\Device\RNDISEthernet\Lib\Webserver.h"></File><File path="Demos\Device\RNDISEthernet\Lib\ARP.c"></File><File path="Demos\Device\RNDISEthernet\Lib\ARP.h"></File><File path="Demos\Device\RNDISEthernet\Lib\DHCP.c"></File><File path="Demos\Device\RNDISEthernet\Lib\DHCP.h"></File><File path="Demos\Device\RNDISEthernet\Lib\Ethernet.c"></File><File path="Demos\Device\RNDISEthernet\Lib\Ethernet.h"></File><File path="Demos\Device\RNDISEthernet\Lib\EthernetProtocols.h"></File><File path="Demos\Device\RNDISEthernet\Lib\ICMP.c"></File><File path="Demos\Device\RNDISEthernet\Lib\ICMP.h"></File><File path="Demos\Device\RNDISEthernet\Lib\IP.c"></File><File path="Demos\Device\RNDISEthernet\Lib\IP.h"></File><File path="Demos\Device\RNDISEthernet\Lib\ProtocolDecoders.c"></File><File path="Demos\Device\RNDISEthernet\Lib\ProtocolDecoders.h"></File><File path="Demos\Device\RNDISEthernet\Lib\RNDIS.c"></File><File path="Demos\Device\RNDISEthernet\Lib\RNDIS.h"></File><File path="Demos\Device\RNDISEthernet\Lib\RNDISConstants.h"></File><File path="Demos\Device\RNDISEthernet\Lib\TCP.c"></File><File path="Demos\Device\RNDISEthernet\Lib\TCP.h"></File><File path="Demos\Device\RNDISEthernet\Lib\UDP.c"></File><File path="Demos\Device\RNDISEthernet\Lib\UDP.h"></File><File path="Demos\Device\RNDISEthernet\Lib\Webserver.c"></File></Folder><File path="Demos\Device\RNDISEthernet\Descriptors.c"></File><File path="Demos\Device\RNDISEthernet\Descriptors.h"></File><File path="Demos\Device\RNDISEthernet\Doxygen.conf"></File><File path="Demos\Device\RNDISEthernet\LUFA RNDIS.inf"></File><File path="Demos\Device\RNDISEthernet\makefile"></File><File path="Demos\Device\RNDISEthernet\RNDISEthernet.c"></File><File path="Demos\Device\RNDISEthernet\RNDISEthernet.h"></File><File path="Demos\Device\RNDISEthernet\RNDISEthernet.txt"></File></Folder><Folder name="USBtoSerial"><Folder name="Lib"><File path="Demos\Device\USBtoSerial\Lib\RingBuff.c"></File><File path="Demos\Device\USBtoSerial\Lib\RingBuff.h"></File></Folder><File path="Demos\Device\USBtoSerial\Descriptors.c"></File><File path="Demos\Device\USBtoSerial\Descriptors.h"></File><File path="Demos\Device\USBtoSerial\Doxygen.conf"></File><File path="Demos\Device\USBtoSerial\LUFA USBtoSerial.inf"></File><File path="Demos\Device\USBtoSerial\makefile"></File><File path="Demos\Device\USBtoSerial\USBtoSerial.c"></File><File path="Demos\Device\USBtoSerial\USBtoSerial.h"></File><File path="Demos\Device\USBtoSerial\USBtoSerial.txt"></File></Folder><File path="Demos\Device\makefile"></File></Folder><Folder name="Host"><Folder name="CDCHost"><File path="Demos\Host\CDCHost\CDCHost.c"></File><File path="Demos\Host\CDCHost\CDCHost.h"></File><File path="Demos\Host\CDCHost\CDCHost.txt"></File><File path="Demos\Host\CDCHost\ConfigDescriptor.c"></File><File path="Demos\Host\CDCHost\ConfigDescriptor.h"></File><File path="Demos\Host\CDCHost\Doxygen.conf"></File><File path="Demos\Host\CDCHost\makefile"></File></Folder><Folder name="GenericHIDHost"><File path="Demos\Host\GenericHIDHost\ConfigDescriptor.c"></File><File path="Demos\Host\GenericHIDHost\ConfigDescriptor.h"></File><File path="Demos\Host\GenericHIDHost\GenericHIDHost.c"></File><File path="Demos\Host\GenericHIDHost\GenericHIDHost.h"></File><File path="Demos\Host\GenericHIDHost\makefile"></File><File path="Demos\Host\GenericHIDHost\Doxygen.conf"></File><File path="Demos\Host\GenericHIDHost\GenericHIDHost.txt"></File></Folder><Folder name="KeyboardHost"><File path="Demos\Host\KeyboardHost\ConfigDescriptor.c"></File><File path="Demos\Host\KeyboardHost\ConfigDescriptor.h"></File><File path="Demos\Host\KeyboardHost\Doxygen.conf"></File><File path="Demos\Host\KeyboardHost\KeyboardHost.c"></File><File path="Demos\Host\KeyboardHost\KeyboardHost.h"></File><File path="Demos\Host\KeyboardHost\KeyboardHost.txt"></File><File path="Demos\Host\KeyboardHost\makefile"></File></Folder><Folder name="KeyboardHostWithParser"><File path="Demos\Host\KeyboardHostWithParser\ConfigDescriptor.c"></File><File path="Demos\Host\KeyboardHostWithParser\ConfigDescriptor.h"></File><File path="Demos\Host\KeyboardHostWithParser\Doxygen.conf"></File><File path="Demos\Host\KeyboardHostWithParser\HIDReport.c"></File><File path="Demos\Host\KeyboardHostWithParser\HIDReport.h"></File><File path="Demos\Host\KeyboardHostWithParser\KeyboardHostWithParser.c"></File><File path="Demos\Host\KeyboardHostWithParser\KeyboardHostWithParser.h"></File><File path="Demos\Host\KeyboardHostWithParser\KeyboardHostWithParser.txt"></File><File path="Demos\Host\KeyboardHostWithParser\makefile"></File></Folder><Folder name="MassStorageHost"><Folder name="Lib"><File path="Demos\Host\MassStorageHost\Lib\MassStoreCommands.c"></File><File path="Demos\Host\MassStorageHost\Lib\MassStoreCommands.h"></File><File path="Demos\Host\MassStorageHost\Lib\SCSI_Codes.h"></File></Folder><File path="Demos\Host\MassStorageHost\ConfigDescriptor.c"></File><File path="Demos\Host\MassStorageHost\ConfigDescriptor.h"></File><File path="Demos\Host\MassStorageHost\Doxygen.conf"></File><File path="Demos\Host\MassStorageHost\makefile"></File><File path="Demos\Host\MassStorageHost\MassStorageHost.c"></File><File path="Demos\Host\MassStorageHost\MassStorageHost.h"></File><File path="Demos\Host\MassStorageHost\MassStorageHost.txt"></File></Folder><Folder name="MouseHost"><File path="Demos\Host\MouseHost\ConfigDescriptor.c"></File><File path="Demos\Host\MouseHost\ConfigDescriptor.h"></File><File path="Demos\Host\MouseHost\Doxygen.conf"></File><File path="Demos\Host\MouseHost\makefile"></File><File path="Demos\Host\MouseHost\MouseHost.c"></File><File path="Demos\Host\MouseHost\MouseHost.h"></File><File path="Demos\Host\MouseHost\MouseHost.txt"></File></Folder><Folder name="MouseHostWithParser"><File path="Demos\Host\MouseHostWithParser\ConfigDescriptor.c"></File><File path="Demos\Host\MouseHostWithParser\ConfigDescriptor.h"></File><File path="Demos\Host\MouseHostWithParser\Doxygen.conf"></File><File path="Demos\Host\MouseHostWithParser\HIDReport.c"></File><File path="Demos\Host\MouseHostWithParser\HIDReport.h"></File><File path="Demos\Host\MouseHostWithParser\makefile"></File><File path="Demos\Host\MouseHostWithParser\MouseHostWithParser.c"></File><File path="Demos\Host\MouseHostWithParser\MouseHostWithParser.h"></File><File path="Demos\Host\MouseHostWithParser\MouseHostWithParser.txt"></File></Folder><Folder name="StillImageHost"><Folder name="Lib"><File path="Demos\Host\StillImageHost\Lib\PIMACodes.h"></File><File path="Demos\Host\StillImageHost\Lib\StillImageCommands.c"></File><File path="Demos\Host\StillImageHost\Lib\StillImageCommands.h"></File></Folder><File path="Demos\Host\StillImageHost\ConfigDescriptor.c"></File><File path="Demos\Host\StillImageHost\ConfigDescriptor.h"></File><File path="Demos\Host\StillImageHost\Doxygen.conf"></File><File path="Demos\Host\StillImageHost\makefile"></File><File path="Demos\Host\StillImageHost\StillImageHost.c"></File><File path="Demos\Host\StillImageHost\StillImageHost.h"></File><File path="Demos\Host\StillImageHost\StillImageHost.txt"></File></Folder><File path="Demos\Host\makefile"></File></Folder><Folder name="OTG"><Folder name="TestApp"><File path="Demos\OTG\TestApp\Descriptors.c"></File><File path="Demos\OTG\TestApp\Descriptors.h"></File><File path="Demos\OTG\TestApp\Doxygen.conf"></File><File path="Demos\OTG\TestApp\makefile"></File><File path="Demos\OTG\TestApp\TestApp.c"></File><File path="Demos\OTG\TestApp\TestApp.h"></File><File path="Demos\OTG\TestApp\TestApp.txt"></File><File path="Demos\OTG\TestApp\TestEvents.c"></File><File path="Demos\OTG\TestApp\TestEvents.h"></File></Folder><File path="Demos\OTG\makefile"></File></Folder><File path="Demos\makefile"></File></Folder><Folder name="LUFA"><Folder name="Common"><File path="LUFA\Common\Common.h"></File><File path="LUFA\Common\FunctionAttributes.h"></File><File path="LUFA\Common\BoardTypes.h"></File></Folder><Folder name="Drivers"><Folder name="USB"><Folder name="LowLevel"><File path="LUFA\Drivers\USB\LowLevel\HostChapter9.h"></File><File path="LUFA\Drivers\USB\LowLevel\LowLevel.c"></File><File path="LUFA\Drivers\USB\LowLevel\LowLevel.h"></File><File path="LUFA\Drivers\USB\LowLevel\Pipe.c"></File><File path="LUFA\Drivers\USB\LowLevel\Pipe.h"></File><File path="LUFA\Drivers\USB\LowLevel\DevChapter9.c"></File><File path="LUFA\Drivers\USB\LowLevel\DevChapter9.h"></File><File path="LUFA\Drivers\USB\LowLevel\Device.h"></File><File path="LUFA\Drivers\USB\LowLevel\Endpoint.c"></File><File path="LUFA\Drivers\USB\LowLevel\Endpoint.h"></File><File path="LUFA\Drivers\USB\LowLevel\Host.c"></File><File path="LUFA\Drivers\USB\LowLevel\Host.h"></File><File path="LUFA\Drivers\USB\LowLevel\HostChapter9.c"></File><File path="LUFA\Drivers\USB\LowLevel\OTG.h"></File></Folder><Folder name="HighLevel"><File path="LUFA\Drivers\USB\HighLevel\USBTask.h"></File><File path="LUFA\Drivers\USB\HighLevel\Events.c"></File><File path="LUFA\Drivers\USB\HighLevel\Events.h"></File><File path="LUFA\Drivers\USB\HighLevel\USBInterrupt.c"></File><File path="LUFA\Drivers\USB\HighLevel\USBInterrupt.h"></File><File path="LUFA\Drivers\USB\HighLevel\USBTask.c"></File><File path="LUFA\Drivers\USB\HighLevel\StdDescriptors.h"></File><File path="LUFA\Drivers\USB\HighLevel\StdRequestType.h"></File><File path="LUFA\Drivers\USB\HighLevel\StreamCallbacks.h"></File><File path="LUFA\Drivers\USB\HighLevel\USBMode.h"></File><File path="LUFA\Drivers\USB\HighLevel\ConfigDescriptor.c"></File><File path="LUFA\Drivers\USB\HighLevel\ConfigDescriptor.h"></File></Folder><Folder name="Class"><File path="LUFA\Drivers\USB\Class\HIDParser.c"></File><File path="LUFA\Drivers\USB\Class\HIDParser.h"></File><File path="LUFA\Drivers\USB\Class\HIDReportData.h"></File></Folder><File path="LUFA\Drivers\USB\USB.h"></File></Folder><Folder name="Misc"><File path="LUFA\Drivers\Misc\TerminalCodes.h"></File></Folder><Folder name="Board"><Folder name="USBKEY"><File path="LUFA\Drivers\Board\USBKEY\Dataflash.h"></File><File path="LUFA\Drivers\Board\USBKEY\Joystick.h"></File><File path="LUFA\Drivers\Board\USBKEY\AT45DB642D.h"></File><File path="LUFA\Drivers\Board\USBKEY\LEDs.h"></File><File path="LUFA\Drivers\Board\USBKEY\Buttons.h"></File></Folder><Folder name="STK526"><File path="LUFA\Drivers\Board\STK526\Dataflash.h"></File><File path="LUFA\Drivers\Board\STK526\Joystick.h"></File><File path="LUFA\Drivers\Board\STK526\AT45DB642D.h"></File><File path="LUFA\Drivers\Board\STK526\LEDs.h"></File><File path="LUFA\Drivers\Board\STK526\Buttons.h"></File></Folder><Folder name="STK525"><File path="LUFA\Drivers\Board\STK525\Dataflash.h"></File><File path="LUFA\Drivers\Board\STK525\Joystick.h"></File><File path="LUFA\Drivers\Board\STK525\AT45DB321C.h"></File><File path="LUFA\Drivers\Board\STK525\LEDs.h"></File><File path="LUFA\Drivers\Board\STK525\Buttons.h"></File></Folder><Folder name="RZUSBSTICK"><File path="LUFA\Drivers\Board\RZUSBSTICK\LEDs.h"></File></Folder><Folder name="ATAVRUSBRF01"><File path="LUFA\Drivers\Board\ATAVRUSBRF01\LEDs.h"></File><File path="LUFA\Drivers\Board\ATAVRUSBRF01\Buttons.h"></File></Folder><File path="LUFA\Drivers\Board\Temperature.h"></File><File path="LUFA\Drivers\Board\Dataflash.h"></File><File path="LUFA\Drivers\Board\Joystick.h"></File><File path="LUFA\Drivers\Board\Temperature.c"></File><File path="LUFA\Drivers\Board\LEDs.h"></File><File path="LUFA\Drivers\Board\Buttons.h"></File></Folder><Folder name="Peripheral"><Folder name="AT90USBXXX67"><File path="LUFA\Drivers\Peripheral\AT90USBXXX67\ADC.h"></File></Folder><File path="LUFA\Drivers\Peripheral\ADC.h"></File><File path="LUFA\Drivers\Peripheral\Serial.c"></File><File path="LUFA\Drivers\Peripheral\Serial.h"></File><File path="LUFA\Drivers\Peripheral\SPI.h"></File><File path="LUFA\Drivers\Peripheral\SerialStream.c"></File><File path="LUFA\Drivers\Peripheral\SerialStream.h"></File></Folder></Folder><Folder name="Scheduler"><File path="LUFA\Scheduler\Scheduler.h"></File><File path="LUFA\Scheduler\Scheduler.c"></File></Folder><Folder name="MemoryAllocator"><File path="LUFA\MemoryAllocator\DynAlloc.h"></File><File path="LUFA\MemoryAllocator\DynAlloc.c"></File></Folder><Folder name="DriverStubs"><File path="LUFA\DriverStubs\Dataflash.h"></File><File path="LUFA\DriverStubs\Joystick.h"></File><File path="LUFA\DriverStubs\LEDs.h"></File><File path="LUFA\DriverStubs\Buttons.h"></File></Folder><File path="LUFA\makefile"></File><File path="LUFA\Version.h"></File><File path="LUFA\BuildingLinkableLibraries.txt"></File><File path="LUFA\ChangeLog.txt"></File><File path="LUFA\CompileTimeTokens.txt"></File><File path="LUFA\DirectorySummaries.txt"></File><File path="LUFA\Doxygen.conf"></File><File path="LUFA\GettingStarted.txt"></File><File path="LUFA\Groups.txt"></File><File path="LUFA\LUFAPoweredProjects.txt"></File><File path="LUFA\MainPage.txt"></File><File path="LUFA\MigrationInformation.txt"></File><File path="LUFA\SchedulerOverview.txt"></File><File path="LUFA\VIDAndPIDValues.txt"></File><File path="LUFA\WritingBoardDrivers.txt"></File></Folder><Folder name="Projects"><Folder name="MagStripe"><Folder name="Lib"><File path="Projects\Magstripe\Lib\CircularBitBuffer.c"></File><File path="Projects\Magstripe\Lib\CircularBitBuffer.h"></File><File path="Projects\Magstripe\Lib\MagstripeHW.h"></File></Folder><File path="Projects\Magstripe\Descriptors.c"></File><File path="Projects\Magstripe\Descriptors.h"></File><File path="Projects\Magstripe\Magstripe.c"></File><File path="Projects\Magstripe\Magstripe.h"></File><File path="Projects\Magstripe\makefile"></File><File path="Projects\Magstripe\Magstripe.txt"></File><File path="Projects\Magstripe\Doxygen.conf"></File></Folder><File path="Projects\makefile"></File></Folder><Folder name="Bootloaders"><Folder name="DFU"><File path="Bootloaders\DFU\BootloaderDFU.c"></File><File path="Bootloaders\DFU\BootloaderDFU.h"></File><File path="Bootloaders\DFU\Descriptors.c"></File><File path="Bootloaders\DFU\Descriptors.h"></File><File path="Bootloaders\DFU\makefile"></File><File path="Bootloaders\DFU\BootloaderDFU.txt"></File><File path="Bootloaders\DFU\Doxygen.conf"></File></Folder><Folder name="CDC"><File path="Bootloaders\CDC\BootloaderCDC.c"></File><File path="Bootloaders\CDC\BootloaderCDC.h"></File><File path="Bootloaders\CDC\Descriptors.c"></File><File path="Bootloaders\CDC\Descriptors.h"></File><File path="Bootloaders\CDC\makefile"></File><File path="Bootloaders\CDC\LUFA CDC Bootloader.inf"></File><File path="Bootloaders\CDC\Doxygen.conf"></File><File path="Bootloaders\CDC\BootloaderCDC.txt"></File></Folder><Folder name="TeensyHID"><File path="Bootloaders\TeensyHID\Descriptors.c"></File><File path="Bootloaders\TeensyHID\Descriptors.h"></File><File path="Bootloaders\TeensyHID\makefile"></File><File path="Bootloaders\TeensyHID\TeensyHID.c"></File><File path="Bootloaders\TeensyHID\TeensyHID.h"></File><File path="Bootloaders\TeensyHID\TeensyHID.txt"></File></Folder><File path="Bootloaders\makefile"></File></Folder><File path="makefile"></File></Project>
\ No newline at end of file
+<Project name="LUFA"><Folder name="Demos"><Folder name="Device"><Folder name="AudioInput"><File path="Demos\Device\AudioInput\AudioInput.c"></File><File path="Demos\Device\AudioInput\AudioInput.h"></File><File path="Demos\Device\AudioInput\AudioInput.txt"></File><File path="Demos\Device\AudioInput\Descriptors.c"></File><File path="Demos\Device\AudioInput\Descriptors.h"></File><File path="Demos\Device\AudioInput\Doxygen.conf"></File><File path="Demos\Device\AudioInput\makefile"></File></Folder><Folder name="AudioOutput"><File path="Demos\Device\AudioOutput\AudioOutput.c"></File><File path="Demos\Device\AudioOutput\AudioOutput.h"></File><File path="Demos\Device\AudioOutput\AudioOutput.txt"></File><File path="Demos\Device\AudioOutput\Descriptors.c"></File><File path="Demos\Device\AudioOutput\Descriptors.h"></File><File path="Demos\Device\AudioOutput\Doxygen.conf"></File><File path="Demos\Device\AudioOutput\makefile"></File></Folder><Folder name="CDC"><File path="Demos\Device\CDC\CDC.c"></File><File path="Demos\Device\CDC\CDC.h"></File><File path="Demos\Device\CDC\CDC.txt"></File><File path="Demos\Device\CDC\Descriptors.c"></File><File path="Demos\Device\CDC\Descriptors.h"></File><File path="Demos\Device\CDC\Doxygen.conf"></File><File path="Demos\Device\CDC\LUFA CDC.inf"></File><File path="Demos\Device\CDC\makefile"></File></Folder><Folder name="DualCDC"><File path="Demos\Device\DualCDC\Descriptors.c"></File><File path="Demos\Device\DualCDC\Descriptors.h"></File><File path="Demos\Device\DualCDC\Doxygen.conf"></File><File path="Demos\Device\DualCDC\DualCDC.c"></File><File path="Demos\Device\DualCDC\DualCDC.h"></File><File path="Demos\Device\DualCDC\DualCDC.txt"></File><File path="Demos\Device\DualCDC\LUFA DualCDC.inf"></File><File path="Demos\Device\DualCDC\makefile"></File></Folder><Folder name="GenericHID"><File path="Demos\Device\GenericHID\Descriptors.c"></File><File path="Demos\Device\GenericHID\Descriptors.h"></File><File path="Demos\Device\GenericHID\GenericHID.c"></File><File path="Demos\Device\GenericHID\GenericHID.h"></File><File path="Demos\Device\GenericHID\makefile"></File><File path="Demos\Device\GenericHID\GenericHID.txt"></File><File path="Demos\Device\GenericHID\Doxygen.conf"></File></Folder><Folder name="Joystick"><File path="Demos\Device\Joystick\Descriptors.c"></File><File path="Demos\Device\Joystick\Descriptors.h"></File><File path="Demos\Device\Joystick\Doxygen.conf"></File><File path="Demos\Device\Joystick\Joystick.c"></File><File path="Demos\Device\Joystick\Joystick.h"></File><File path="Demos\Device\Joystick\Joystick.txt"></File><File path="Demos\Device\Joystick\makefile"></File></Folder><Folder name="Keyboard"><File path="Demos\Device\Keyboard\Descriptors.c"></File><File path="Demos\Device\Keyboard\Descriptors.h"></File><File path="Demos\Device\Keyboard\Doxygen.conf"></File><File path="Demos\Device\Keyboard\Keyboard.c"></File><File path="Demos\Device\Keyboard\Keyboard.h"></File><File path="Demos\Device\Keyboard\Keyboard.txt"></File><File path="Demos\Device\Keyboard\makefile"></File></Folder><Folder name="KeyboardMouse"><File path="Demos\Device\KeyboardMouse\Descriptors.c"></File><File path="Demos\Device\KeyboardMouse\Descriptors.h"></File><File path="Demos\Device\KeyboardMouse\Doxygen.conf"></File><File path="Demos\Device\KeyboardMouse\KeyboardMouse.c"></File><File path="Demos\Device\KeyboardMouse\KeyboardMouse.h"></File><File path="Demos\Device\KeyboardMouse\KeyboardMouse.txt"></File><File path="Demos\Device\KeyboardMouse\makefile"></File></Folder><Folder name="MassStorage"><Folder name="Lib"><File path="Demos\Device\MassStorage\Lib\DataflashManager.c"></File><File path="Demos\Device\MassStorage\Lib\DataflashManager.h"></File><File path="Demos\Device\MassStorage\Lib\SCSI.c"></File><File path="Demos\Device\MassStorage\Lib\SCSI.h"></File><File path="Demos\Device\MassStorage\Lib\SCSI_Codes.h"></File></Folder><File path="Demos\Device\MassStorage\Descriptors.c"></File><File path="Demos\Device\MassStorage\Descriptors.h"></File><File path="Demos\Device\MassStorage\Doxygen.conf"></File><File path="Demos\Device\MassStorage\makefile"></File><File path="Demos\Device\MassStorage\MassStorage.c"></File><File path="Demos\Device\MassStorage\MassStorage.h"></File><File path="Demos\Device\MassStorage\MassStorage.txt"></File></Folder><Folder name="MIDI"><File path="Demos\Device\MIDI\Descriptors.c"></File><File path="Demos\Device\MIDI\Descriptors.h"></File><File path="Demos\Device\MIDI\Doxygen.conf"></File><File path="Demos\Device\MIDI\makefile"></File><File path="Demos\Device\MIDI\MIDI.c"></File><File path="Demos\Device\MIDI\MIDI.h"></File><File path="Demos\Device\MIDI\MIDI.txt"></File></Folder><Folder name="Mouse"><File path="Demos\Device\Mouse\Descriptors.c"></File><File path="Demos\Device\Mouse\Descriptors.h"></File><File path="Demos\Device\Mouse\Doxygen.conf"></File><File path="Demos\Device\Mouse\makefile"></File><File path="Demos\Device\Mouse\Mouse.c"></File><File path="Demos\Device\Mouse\Mouse.h"></File><File path="Demos\Device\Mouse\Mouse.txt"></File></Folder><Folder name="RNDISEthernet"><Folder name="Lib"><File path="Demos\Device\RNDISEthernet\Lib\Webserver.h"></File><File path="Demos\Device\RNDISEthernet\Lib\ARP.c"></File><File path="Demos\Device\RNDISEthernet\Lib\ARP.h"></File><File path="Demos\Device\RNDISEthernet\Lib\DHCP.c"></File><File path="Demos\Device\RNDISEthernet\Lib\DHCP.h"></File><File path="Demos\Device\RNDISEthernet\Lib\Ethernet.c"></File><File path="Demos\Device\RNDISEthernet\Lib\Ethernet.h"></File><File path="Demos\Device\RNDISEthernet\Lib\EthernetProtocols.h"></File><File path="Demos\Device\RNDISEthernet\Lib\ICMP.c"></File><File path="Demos\Device\RNDISEthernet\Lib\ICMP.h"></File><File path="Demos\Device\RNDISEthernet\Lib\IP.c"></File><File path="Demos\Device\RNDISEthernet\Lib\IP.h"></File><File path="Demos\Device\RNDISEthernet\Lib\ProtocolDecoders.c"></File><File path="Demos\Device\RNDISEthernet\Lib\ProtocolDecoders.h"></File><File path="Demos\Device\RNDISEthernet\Lib\TCP.c"></File><File path="Demos\Device\RNDISEthernet\Lib\TCP.h"></File><File path="Demos\Device\RNDISEthernet\Lib\UDP.c"></File><File path="Demos\Device\RNDISEthernet\Lib\UDP.h"></File><File path="Demos\Device\RNDISEthernet\Lib\Webserver.c"></File></Folder><File path="Demos\Device\RNDISEthernet\Descriptors.c"></File><File path="Demos\Device\RNDISEthernet\Descriptors.h"></File><File path="Demos\Device\RNDISEthernet\Doxygen.conf"></File><File path="Demos\Device\RNDISEthernet\LUFA RNDIS.inf"></File><File path="Demos\Device\RNDISEthernet\makefile"></File><File path="Demos\Device\RNDISEthernet\RNDISEthernet.c"></File><File path="Demos\Device\RNDISEthernet\RNDISEthernet.h"></File><File path="Demos\Device\RNDISEthernet\RNDISEthernet.txt"></File></Folder><Folder name="USBtoSerial"><Folder name="Lib"><File path="Demos\Device\USBtoSerial\Lib\RingBuff.c"></File><File path="Demos\Device\USBtoSerial\Lib\RingBuff.h"></File></Folder><File path="Demos\Device\USBtoSerial\Descriptors.c"></File><File path="Demos\Device\USBtoSerial\Descriptors.h"></File><File path="Demos\Device\USBtoSerial\Doxygen.conf"></File><File path="Demos\Device\USBtoSerial\LUFA USBtoSerial.inf"></File><File path="Demos\Device\USBtoSerial\makefile"></File><File path="Demos\Device\USBtoSerial\USBtoSerial.c"></File><File path="Demos\Device\USBtoSerial\USBtoSerial.h"></File><File path="Demos\Device\USBtoSerial\USBtoSerial.txt"></File></Folder><File path="Demos\Device\makefile"></File></Folder><Folder name="Host"><Folder name="CDCHost"><File path="Demos\Host\CDCHost\CDCHost.c"></File><File path="Demos\Host\CDCHost\CDCHost.h"></File><File path="Demos\Host\CDCHost\CDCHost.txt"></File><File path="Demos\Host\CDCHost\ConfigDescriptor.c"></File><File path="Demos\Host\CDCHost\ConfigDescriptor.h"></File><File path="Demos\Host\CDCHost\Doxygen.conf"></File><File path="Demos\Host\CDCHost\makefile"></File></Folder><Folder name="GenericHIDHost"><File path="Demos\Host\GenericHIDHost\ConfigDescriptor.c"></File><File path="Demos\Host\GenericHIDHost\ConfigDescriptor.h"></File><File path="Demos\Host\GenericHIDHost\GenericHIDHost.c"></File><File path="Demos\Host\GenericHIDHost\GenericHIDHost.h"></File><File path="Demos\Host\GenericHIDHost\makefile"></File><File path="Demos\Host\GenericHIDHost\Doxygen.conf"></File><File path="Demos\Host\GenericHIDHost\GenericHIDHost.txt"></File></Folder><Folder name="KeyboardHost"><File path="Demos\Host\KeyboardHost\ConfigDescriptor.c"></File><File path="Demos\Host\KeyboardHost\ConfigDescriptor.h"></File><File path="Demos\Host\KeyboardHost\Doxygen.conf"></File><File path="Demos\Host\KeyboardHost\KeyboardHost.c"></File><File path="Demos\Host\KeyboardHost\KeyboardHost.h"></File><File path="Demos\Host\KeyboardHost\KeyboardHost.txt"></File><File path="Demos\Host\KeyboardHost\makefile"></File></Folder><Folder name="KeyboardHostWithParser"><File path="Demos\Host\KeyboardHostWithParser\ConfigDescriptor.c"></File><File path="Demos\Host\KeyboardHostWithParser\ConfigDescriptor.h"></File><File path="Demos\Host\KeyboardHostWithParser\Doxygen.conf"></File><File path="Demos\Host\KeyboardHostWithParser\HIDReport.c"></File><File path="Demos\Host\KeyboardHostWithParser\HIDReport.h"></File><File path="Demos\Host\KeyboardHostWithParser\KeyboardHostWithParser.c"></File><File path="Demos\Host\KeyboardHostWithParser\KeyboardHostWithParser.h"></File><File path="Demos\Host\KeyboardHostWithParser\KeyboardHostWithParser.txt"></File><File path="Demos\Host\KeyboardHostWithParser\makefile"></File></Folder><Folder name="MassStorageHost"><Folder name="Lib"><File path="Demos\Host\MassStorageHost\Lib\MassStoreCommands.c"></File><File path="Demos\Host\MassStorageHost\Lib\MassStoreCommands.h"></File><File path="Demos\Host\MassStorageHost\Lib\SCSI_Codes.h"></File></Folder><File path="Demos\Host\MassStorageHost\ConfigDescriptor.c"></File><File path="Demos\Host\MassStorageHost\ConfigDescriptor.h"></File><File path="Demos\Host\MassStorageHost\Doxygen.conf"></File><File path="Demos\Host\MassStorageHost\makefile"></File><File path="Demos\Host\MassStorageHost\MassStorageHost.c"></File><File path="Demos\Host\MassStorageHost\MassStorageHost.h"></File><File path="Demos\Host\MassStorageHost\MassStorageHost.txt"></File></Folder><Folder name="MouseHost"><File path="Demos\Host\MouseHost\ConfigDescriptor.c"></File><File path="Demos\Host\MouseHost\ConfigDescriptor.h"></File><File path="Demos\Host\MouseHost\Doxygen.conf"></File><File path="Demos\Host\MouseHost\makefile"></File><File path="Demos\Host\MouseHost\MouseHost.c"></File><File path="Demos\Host\MouseHost\MouseHost.h"></File><File path="Demos\Host\MouseHost\MouseHost.txt"></File></Folder><Folder name="MouseHostWithParser"><File path="Demos\Host\MouseHostWithParser\ConfigDescriptor.c"></File><File path="Demos\Host\MouseHostWithParser\ConfigDescriptor.h"></File><File path="Demos\Host\MouseHostWithParser\Doxygen.conf"></File><File path="Demos\Host\MouseHostWithParser\HIDReport.c"></File><File path="Demos\Host\MouseHostWithParser\HIDReport.h"></File><File path="Demos\Host\MouseHostWithParser\makefile"></File><File path="Demos\Host\MouseHostWithParser\MouseHostWithParser.c"></File><File path="Demos\Host\MouseHostWithParser\MouseHostWithParser.h"></File><File path="Demos\Host\MouseHostWithParser\MouseHostWithParser.txt"></File></Folder><Folder name="StillImageHost"><Folder name="Lib"><File path="Demos\Host\StillImageHost\Lib\PIMACodes.h"></File><File path="Demos\Host\StillImageHost\Lib\StillImageCommands.c"></File><File path="Demos\Host\StillImageHost\Lib\StillImageCommands.h"></File></Folder><File path="Demos\Host\StillImageHost\ConfigDescriptor.c"></File><File path="Demos\Host\StillImageHost\ConfigDescriptor.h"></File><File path="Demos\Host\StillImageHost\Doxygen.conf"></File><File path="Demos\Host\StillImageHost\makefile"></File><File path="Demos\Host\StillImageHost\StillImageHost.c"></File><File path="Demos\Host\StillImageHost\StillImageHost.h"></File><File path="Demos\Host\StillImageHost\StillImageHost.txt"></File></Folder><File path="Demos\Host\makefile"></File></Folder><Folder name="OTG"><Folder name="TestApp"><File path="Demos\OTG\TestApp\Descriptors.c"></File><File path="Demos\OTG\TestApp\Descriptors.h"></File><File path="Demos\OTG\TestApp\Doxygen.conf"></File><File path="Demos\OTG\TestApp\makefile"></File><File path="Demos\OTG\TestApp\TestApp.c"></File><File path="Demos\OTG\TestApp\TestApp.h"></File><File path="Demos\OTG\TestApp\TestApp.txt"></File><File path="Demos\OTG\TestApp\TestEvents.c"></File><File path="Demos\OTG\TestApp\TestEvents.h"></File></Folder><File path="Demos\OTG\makefile"></File></Folder><File path="Demos\makefile"></File></Folder><Folder name="LUFA"><Folder name="Common"><File path="LUFA\Common\Common.h"></File><File path="LUFA\Common\FunctionAttributes.h"></File><File path="LUFA\Common\BoardTypes.h"></File></Folder><Folder name="Drivers"><Folder name="USB"><Folder name="LowLevel"><File path="LUFA\Drivers\USB\LowLevel\HostChapter9.h"></File><File path="LUFA\Drivers\USB\LowLevel\LowLevel.c"></File><File path="LUFA\Drivers\USB\LowLevel\LowLevel.h"></File><File path="LUFA\Drivers\USB\LowLevel\Pipe.c"></File><File path="LUFA\Drivers\USB\LowLevel\Pipe.h"></File><File path="LUFA\Drivers\USB\LowLevel\DevChapter9.c"></File><File path="LUFA\Drivers\USB\LowLevel\DevChapter9.h"></File><File path="LUFA\Drivers\USB\LowLevel\Device.h"></File><File path="LUFA\Drivers\USB\LowLevel\Endpoint.c"></File><File path="LUFA\Drivers\USB\LowLevel\Endpoint.h"></File><File path="LUFA\Drivers\USB\LowLevel\Host.c"></File><File path="LUFA\Drivers\USB\LowLevel\Host.h"></File><File path="LUFA\Drivers\USB\LowLevel\HostChapter9.c"></File><File path="LUFA\Drivers\USB\LowLevel\OTG.h"></File></Folder><Folder name="HighLevel"><File path="LUFA\Drivers\USB\HighLevel\USBTask.h"></File><File path="LUFA\Drivers\USB\HighLevel\Events.c"></File><File path="LUFA\Drivers\USB\HighLevel\Events.h"></File><File path="LUFA\Drivers\USB\HighLevel\USBInterrupt.c"></File><File path="LUFA\Drivers\USB\HighLevel\USBInterrupt.h"></File><File path="LUFA\Drivers\USB\HighLevel\USBTask.c"></File><File path="LUFA\Drivers\USB\HighLevel\StdDescriptors.h"></File><File path="LUFA\Drivers\USB\HighLevel\StdRequestType.h"></File><File path="LUFA\Drivers\USB\HighLevel\StreamCallbacks.h"></File><File path="LUFA\Drivers\USB\HighLevel\USBMode.h"></File><File path="LUFA\Drivers\USB\HighLevel\ConfigDescriptor.c"></File><File path="LUFA\Drivers\USB\HighLevel\ConfigDescriptor.h"></File></Folder><Folder name="Class"><Folder name="Device"><File path="LUFA\Drivers\USB\Class\Device\HID.c"></File><File path="LUFA\Drivers\USB\Class\Device\HID.h"></File><File path="LUFA\Drivers\USB\Class\Device\CDC.c"></File><File path="LUFA\Drivers\USB\Class\Device\CDC.h"></File><File path="LUFA\Drivers\USB\Class\Device\RNDIS.c"></File><File path="LUFA\Drivers\USB\Class\Device\RNDIS.h"></File><File path="LUFA\Drivers\USB\Class\Device\RNDISConstants.h"></File><File path="LUFA\Drivers\USB\Class\Device\MassStorage.c"></File><File path="LUFA\Drivers\USB\Class\Device\MassStorage.h"></File><File path="LUFA\Drivers\USB\Class\Device\Audio.c"></File><File path="LUFA\Drivers\USB\Class\Device\Audio.h"></File></Folder><Folder name="Host"><File path="LUFA\Drivers\USB\Class\Host\HIDParser.c"></File><File path="LUFA\Drivers\USB\Class\Host\HIDParser.h"></File><File path="LUFA\Drivers\USB\Class\Host\HIDReportData.h"></File></Folder></Folder><File path="LUFA\Drivers\USB\USB.h"></File></Folder><Folder name="Misc"><File path="LUFA\Drivers\Misc\TerminalCodes.h"></File></Folder><Folder name="Board"><Folder name="USBKEY"><File path="LUFA\Drivers\Board\USBKEY\Dataflash.h"></File><File path="LUFA\Drivers\Board\USBKEY\Joystick.h"></File><File path="LUFA\Drivers\Board\USBKEY\AT45DB642D.h"></File><File path="LUFA\Drivers\Board\USBKEY\LEDs.h"></File><File path="LUFA\Drivers\Board\USBKEY\Buttons.h"></File></Folder><Folder name="STK526"><File path="LUFA\Drivers\Board\STK526\Dataflash.h"></File><File path="LUFA\Drivers\Board\STK526\Joystick.h"></File><File path="LUFA\Drivers\Board\STK526\AT45DB642D.h"></File><File path="LUFA\Drivers\Board\STK526\LEDs.h"></File><File path="LUFA\Drivers\Board\STK526\Buttons.h"></File></Folder><Folder name="STK525"><File path="LUFA\Drivers\Board\STK525\Dataflash.h"></File><File path="LUFA\Drivers\Board\STK525\Joystick.h"></File><File path="LUFA\Drivers\Board\STK525\AT45DB321C.h"></File><File path="LUFA\Drivers\Board\STK525\LEDs.h"></File><File path="LUFA\Drivers\Board\STK525\Buttons.h"></File></Folder><Folder name="RZUSBSTICK"><File path="LUFA\Drivers\Board\RZUSBSTICK\LEDs.h"></File></Folder><Folder name="ATAVRUSBRF01"><File path="LUFA\Drivers\Board\ATAVRUSBRF01\LEDs.h"></File><File path="LUFA\Drivers\Board\ATAVRUSBRF01\Buttons.h"></File></Folder><File path="LUFA\Drivers\Board\Temperature.h"></File><File path="LUFA\Drivers\Board\Dataflash.h"></File><File path="LUFA\Drivers\Board\Joystick.h"></File><File path="LUFA\Drivers\Board\Temperature.c"></File><File path="LUFA\Drivers\Board\LEDs.h"></File><File path="LUFA\Drivers\Board\Buttons.h"></File></Folder><Folder name="Peripheral"><Folder name="AT90USBXXX67"><File path="LUFA\Drivers\Peripheral\AT90USBXXX67\ADC.h"></File></Folder><File path="LUFA\Drivers\Peripheral\ADC.h"></File><File path="LUFA\Drivers\Peripheral\Serial.c"></File><File path="LUFA\Drivers\Peripheral\Serial.h"></File><File path="LUFA\Drivers\Peripheral\SPI.h"></File><File path="LUFA\Drivers\Peripheral\SerialStream.c"></File><File path="LUFA\Drivers\Peripheral\SerialStream.h"></File></Folder></Folder><Folder name="DriverStubs"><File path="LUFA\DriverStubs\Dataflash.h"></File><File path="LUFA\DriverStubs\Joystick.h"></File><File path="LUFA\DriverStubs\LEDs.h"></File><File path="LUFA\DriverStubs\Buttons.h"></File></Folder><File path="LUFA\makefile"></File><File path="LUFA\Version.h"></File><File path="LUFA\BuildingLinkableLibraries.txt"></File><File path="LUFA\ChangeLog.txt"></File><File path="LUFA\CompileTimeTokens.txt"></File><File path="LUFA\DirectorySummaries.txt"></File><File path="LUFA\Doxygen.conf"></File><File path="LUFA\GettingStarted.txt"></File><File path="LUFA\Groups.txt"></File><File path="LUFA\LUFAPoweredProjects.txt"></File><File path="LUFA\MainPage.txt"></File><File path="LUFA\MigrationInformation.txt"></File><File path="LUFA\VIDAndPIDValues.txt"></File><File path="LUFA\WritingBoardDrivers.txt"></File></Folder><Folder name="Projects"><Folder name="MagStripe"><Folder name="Lib"><File path="Projects\Magstripe\Lib\CircularBitBuffer.c"></File><File path="Projects\Magstripe\Lib\CircularBitBuffer.h"></File><File path="Projects\Magstripe\Lib\MagstripeHW.h"></File></Folder><File path="Projects\Magstripe\Descriptors.c"></File><File path="Projects\Magstripe\Descriptors.h"></File><File path="Projects\Magstripe\Magstripe.c"></File><File path="Projects\Magstripe\Magstripe.h"></File><File path="Projects\Magstripe\makefile"></File><File path="Projects\Magstripe\Magstripe.txt"></File><File path="Projects\Magstripe\Doxygen.conf"></File></Folder><File path="Projects\makefile"></File></Folder><Folder name="Bootloaders"><Folder name="DFU"><File path="Bootloaders\DFU\BootloaderDFU.c"></File><File path="Bootloaders\DFU\BootloaderDFU.h"></File><File path="Bootloaders\DFU\Descriptors.c"></File><File path="Bootloaders\DFU\Descriptors.h"></File><File path="Bootloaders\DFU\makefile"></File><File path="Bootloaders\DFU\BootloaderDFU.txt"></File><File path="Bootloaders\DFU\Doxygen.conf"></File></Folder><Folder name="CDC"><File path="Bootloaders\CDC\BootloaderCDC.c"></File><File path="Bootloaders\CDC\BootloaderCDC.h"></File><File path="Bootloaders\CDC\Descriptors.c"></File><File path="Bootloaders\CDC\Descriptors.h"></File><File path="Bootloaders\CDC\makefile"></File><File path="Bootloaders\CDC\LUFA CDC Bootloader.inf"></File><File path="Bootloaders\CDC\Doxygen.conf"></File><File path="Bootloaders\CDC\BootloaderCDC.txt"></File></Folder><Folder name="TeensyHID"><File path="Bootloaders\TeensyHID\Descriptors.c"></File><File path="Bootloaders\TeensyHID\Descriptors.h"></File><File path="Bootloaders\TeensyHID\makefile"></File><File path="Bootloaders\TeensyHID\TeensyHID.c"></File><File path="Bootloaders\TeensyHID\TeensyHID.h"></File><File path="Bootloaders\TeensyHID\TeensyHID.txt"></File></Folder><File path="Bootloaders\makefile"></File></Folder><File path="makefile"></File></Project>
\ No newline at end of file
* documentation pages. It is not a project source file.\r
*/\r
\r
+========== TODO: ===========\r
+ - Document new class drivers\r
+ - Re-document all demos now that they have changed\r
+ - Add standardized descriptor names to class driver structures, controlled by USE_NONSTANDARD_DESCRIPTOR_NAMES\r
+ - Add C++ compatibility to class drivers\r
+ - Disable JTAG in demos\r
+============================\r
+\r
/** \page Page_ChangeLog Project Changelog\r
*\r
* \section Sec_ChangeLogXXXXXX Version XXXXXX\r
* LUFA/Drivers/USB/Class/ directory to LUFA/Drivers/USB/HighLevel/ in preperation for the new USB class APIs\r
* - Moved out each demos' functionality library files (e.g. Ring Buffer library) to /Lib directories for a better directory structure\r
* - Removed Tx interrupt from the USBtoSerial demo; now sends characters via polling to ensure more time for the Rx interrupt\r
+ * - Added new EVENT_USB_StartOfFrame event in the library to indicate the start of each USB frame (when generated)\r
+ * - Removed psuedo-scheduler, dynamic memory block allocator from the library (no longer needed and not used respectively)\r
*\r
*\r
* \section Sec_ChangeLog090510 Version 090510\r
* This folder contains header files which are common to all parts of the LUFA library. They may be used freely in\r
* user applications.\r
*\r
- * \dir MemoryAllocator\r
- * \brief Auto-defragmenting dynamic memory allocation library.\r
- * \r
- * This folder contains a simple handle-based dynamic memory allocation library, capable of handing out memory in\r
- * block chunks. As new memory is allocated, the library will defragment the already allocated memory to ensure\r
- * optimal memory usage. It is not used within the LUFA library, and is provided as a convenience for user applications.\r
- *\r
- * \dir Scheduler\r
- * \brief Simple round-robbin scheduler.\r
- * \r
- * This folder contains the simple LUFA round-robbin scheduler, provided as a convenience for user applications. It\r
- * is very simple in design, and is intended to make code easier to read, rather than providing a complete RTOS kernel.\r
- *\r
* \dir Drivers\r
* \brief Library hardware and software drivers.\r
* \r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+#include "Audio.h"\r
+\r
+void USB_Audio_ProcessControlPacket(USB_ClassInfo_Audio_t* AudioInterfaceInfo)\r
+{\r
+ if (!(Endpoint_IsSETUPReceived()))\r
+ return;\r
+ \r
+// if (USB_ControlRequest.wIndex != AudioInterfaceInfo->InterfaceNumber)\r
+// return;\r
+\r
+ switch (USB_ControlRequest.bRequest)\r
+ {\r
+ case REQ_SetInterface:\r
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE))\r
+ {\r
+ Endpoint_ClearSETUP();\r
+ \r
+ AudioInterfaceInfo->InterfaceEnabled = (USB_ControlRequest.wValue != 0);\r
+ \r
+ while (!(Endpoint_IsINReady()));\r
+ Endpoint_ClearIN();\r
+ }\r
+\r
+ break;\r
+ }\r
+}\r
+\r
+bool USB_Audio_ConfigureEndpoints(USB_ClassInfo_Audio_t* AudioInterfaceInfo)\r
+{\r
+ if (AudioInterfaceInfo->DataINEndpointNumber)\r
+ {\r
+ if (!(Endpoint_ConfigureEndpoint(AudioInterfaceInfo->DataINEndpointNumber, EP_TYPE_ISOCHRONOUS,\r
+ ENDPOINT_DIR_IN, AudioInterfaceInfo->DataINEndpointSize,\r
+ ENDPOINT_BANK_DOUBLE)))\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+\r
+ if (AudioInterfaceInfo->DataOUTEndpointNumber)\r
+ {\r
+ if (!(Endpoint_ConfigureEndpoint(AudioInterfaceInfo->DataOUTEndpointNumber, EP_TYPE_ISOCHRONOUS,\r
+ ENDPOINT_DIR_OUT, AudioInterfaceInfo->DataOUTEndpointSize,\r
+ ENDPOINT_BANK_DOUBLE)))\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+int8_t USB_Audio_ReadSample8(void)\r
+{\r
+ int8_t Sample;\r
+\r
+ Sample = Endpoint_Read_Byte();\r
+\r
+ if (!(Endpoint_IsReadWriteAllowed()))\r
+ Endpoint_ClearOUT();\r
+ \r
+ return Sample;\r
+}\r
+\r
+int16_t USB_Audio_ReadSample16(void)\r
+{\r
+ int16_t Sample;\r
+\r
+ Sample = (int16_t)Endpoint_Read_Word_LE();\r
+ \r
+ if (!(Endpoint_IsReadWriteAllowed()))\r
+ Endpoint_ClearOUT();\r
+\r
+ return Sample;\r
+}\r
+\r
+int32_t USB_Audio_ReadSample24(void)\r
+{\r
+ int32_t Sample;\r
+\r
+ Sample = (((uint32_t)Endpoint_Read_Byte() << 16) | Endpoint_Read_Word_LE());\r
+ \r
+ if (!(Endpoint_IsReadWriteAllowed()))\r
+ Endpoint_ClearOUT();\r
+\r
+ return Sample;\r
+}\r
+\r
+void USB_Audio_WriteSample8(int8_t Sample)\r
+{\r
+ Endpoint_Write_Byte(Sample);\r
+\r
+ if (!(Endpoint_IsReadWriteAllowed()))\r
+ Endpoint_ClearIN();\r
+}\r
+\r
+void USB_Audio_WriteSample16(int16_t Sample)\r
+{\r
+ Endpoint_Write_Word_LE(Sample);\r
+\r
+ if (!(Endpoint_IsReadWriteAllowed()))\r
+ Endpoint_ClearIN();\r
+}\r
+\r
+void USB_Audio_WriteSample24(int32_t Sample)\r
+{\r
+ Endpoint_Write_Byte(Sample >> 16);\r
+ Endpoint_Write_Word_LE(Sample);\r
+\r
+ if (!(Endpoint_IsReadWriteAllowed()))\r
+ Endpoint_ClearIN();\r
+}\r
+\r
+bool USB_Audio_IsSampleReceived(USB_ClassInfo_Audio_t* AudioInterfaceInfo)\r
+{\r
+ Endpoint_SelectEndpoint(AudioInterfaceInfo->DataOUTEndpointNumber);\r
+ return Endpoint_IsOUTReceived();\r
+}\r
+\r
+bool USB_Audio_IsReadyForNextSample(USB_ClassInfo_Audio_t* AudioInterfaceInfo)\r
+{\r
+ Endpoint_SelectEndpoint(AudioInterfaceInfo->DataINEndpointNumber);\r
+ return Endpoint_IsINReady();\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+#ifndef _AUDIO_CLASS_H_\r
+#define _AUDIO_CLASS_H_\r
+\r
+ /* Includes: */\r
+ #include "../../USB.h"\r
+\r
+ #include <string.h>\r
+\r
+ /* Macros: */\r
+\r
+ /* Enums: */\r
+\r
+ /* Type Defines: */\r
+ typedef struct\r
+ {\r
+ uint8_t InterfaceNumber;\r
+\r
+ uint8_t DataINEndpointNumber;\r
+ uint16_t DataINEndpointSize;\r
+\r
+ uint8_t DataOUTEndpointNumber;\r
+ uint16_t DataOUTEndpointSize;\r
+\r
+ bool InterfaceEnabled;\r
+ } USB_ClassInfo_Audio_t;\r
+ \r
+ /* Function Prototypes: */\r
+ bool USB_Audio_ConfigureEndpoints(USB_ClassInfo_Audio_t* AudioInterfaceInfo);\r
+ void USB_Audio_ProcessControlPacket(USB_ClassInfo_Audio_t* AudioInterfaceInfo);\r
+ void USB_Audio_USBTask(USB_ClassInfo_Audio_t* AudioInterfaceInfo);\r
+ \r
+ int8_t USB_Audio_ReadSample8(void);\r
+ int16_t USB_Audio_ReadSample16(void);\r
+ int32_t USB_Audio_ReadSample24(void);\r
+ void USB_Audio_WriteSample8(int8_t Sample);\r
+ void USB_Audio_WriteSample16(int16_t Sample);\r
+ void USB_Audio_WriteSample24(int32_t Sample);\r
+ bool USB_Audio_IsSampleReceived(USB_ClassInfo_Audio_t* AudioInterfaceInfo);\r
+ bool USB_Audio_IsReadyForNextSample(USB_ClassInfo_Audio_t* AudioInterfaceInfo);\r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+#define INCLUDE_FROM_CDC_CLASS_C\r
+#include "CDC.h"\r
+\r
+void USB_CDC_Event_Stub(void)\r
+{\r
+\r
+}\r
+\r
+void USB_CDC_ProcessControlPacket(USB_ClassInfo_CDC_t* CDCInterfaceInfo)\r
+{\r
+ if (!(Endpoint_IsSETUPReceived()))\r
+ return;\r
+ \r
+ if (USB_ControlRequest.wIndex != CDCInterfaceInfo->ControlInterfaceNumber)\r
+ return;\r
+\r
+ switch (USB_ControlRequest.bRequest)\r
+ {\r
+ case REQ_GetLineEncoding:\r
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
+ {\r
+ Endpoint_ClearSETUP();\r
+ Endpoint_Write_Control_Stream_LE(&CDCInterfaceInfo->LineEncoding, sizeof(CDCInterfaceInfo->LineEncoding));\r
+ Endpoint_ClearOUT();\r
+ }\r
+ \r
+ break;\r
+ case REQ_SetLineEncoding:\r
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
+ {\r
+ Endpoint_ClearSETUP();\r
+ Endpoint_Read_Control_Stream_LE(&CDCInterfaceInfo->LineEncoding, sizeof(CDCInterfaceInfo->LineEncoding));\r
+ Endpoint_ClearIN();\r
+\r
+ EVENT_USB_CDC_LineEncodingChanged(CDCInterfaceInfo);\r
+ }\r
+ \r
+ break;\r
+ case REQ_SetControlLineState:\r
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
+ { \r
+ Endpoint_ClearSETUP();\r
+ \r
+ CDCInterfaceInfo->ControlLineState = USB_ControlRequest.wValue;\r
+ \r
+ EVENT_USB_CDC_ControLineStateChanged();\r
+\r
+ while (!(Endpoint_IsINReady()));\r
+ Endpoint_ClearIN();\r
+ }\r
+ \r
+ break;\r
+ }\r
+}\r
+\r
+bool USB_CDC_ConfigureEndpoints(USB_ClassInfo_CDC_t* CDCInterfaceInfo)\r
+{\r
+ if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo->DataINEndpointNumber, EP_TYPE_BULK,\r
+ ENDPOINT_DIR_IN, CDCInterfaceInfo->DataINEndpointSize,\r
+ ENDPOINT_BANK_SINGLE)))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo->DataOUTEndpointNumber, EP_TYPE_BULK,\r
+ ENDPOINT_DIR_OUT, CDCInterfaceInfo->DataOUTEndpointSize,\r
+ ENDPOINT_BANK_SINGLE)))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo->NotificationEndpointNumber, EP_TYPE_INTERRUPT,\r
+ ENDPOINT_DIR_IN, CDCInterfaceInfo->NotificationEndpointSize,\r
+ ENDPOINT_BANK_SINGLE)))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+void USB_CDC_USBTask(USB_ClassInfo_CDC_t* CDCInterfaceInfo)\r
+{\r
+ if (!(USB_IsConnected))\r
+ return;\r
+\r
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->DataINEndpointNumber);\r
+\r
+ if (!(Endpoint_BytesInEndpoint()))\r
+ return;\r
+ \r
+ if (!(Endpoint_IsReadWriteAllowed()))\r
+ {\r
+ Endpoint_ClearIN();\r
+ while (!(Endpoint_IsReadWriteAllowed()));\r
+ } \r
+ \r
+ Endpoint_ClearIN();\r
+}\r
+\r
+void USB_CDC_SendString(USB_ClassInfo_CDC_t* CDCInterfaceInfo, char* Data, uint16_t Length)\r
+{\r
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->DataINEndpointNumber);\r
+ Endpoint_Write_Stream_LE(Data, Length, NO_STREAM_CALLBACK);\r
+}\r
+\r
+void USB_CDC_SendByte(USB_ClassInfo_CDC_t* CDCInterfaceInfo, uint8_t Data)\r
+{\r
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->DataINEndpointNumber);\r
+\r
+ if (!(Endpoint_IsReadWriteAllowed()))\r
+ {\r
+ Endpoint_ClearIN();\r
+ while (!(Endpoint_IsReadWriteAllowed()));\r
+ }\r
+\r
+ Endpoint_Write_Byte(Data); \r
+}\r
+\r
+uint16_t USB_CDC_BytesReceived(USB_ClassInfo_CDC_t* CDCInterfaceInfo)\r
+{\r
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->DataOUTEndpointNumber);\r
+\r
+ return Endpoint_BytesInEndpoint();\r
+}\r
+\r
+uint8_t USB_CDC_ReceiveByte(USB_ClassInfo_CDC_t* CDCInterfaceInfo)\r
+{\r
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->DataOUTEndpointNumber);\r
+ \r
+ uint8_t DataByte = Endpoint_Read_Byte();\r
+ \r
+ if (!(Endpoint_BytesInEndpoint()))\r
+ Endpoint_ClearOUT();\r
+ \r
+ return DataByte;\r
+}\r
+\r
+void USB_CDC_SendSerialLineStateChanged(USB_ClassInfo_CDC_t* CDCInterfaceInfo, uint16_t LineStateMask)\r
+{\r
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->NotificationEndpointNumber);\r
+ \r
+ USB_Request_Header_t Notification = (USB_Request_Header_t)\r
+ {\r
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),\r
+ .bRequest = NOTIF_SerialState,\r
+ .wValue = 0,\r
+ .wIndex = 0,\r
+ .wLength = sizeof(uint16_t),\r
+ };\r
+\r
+ Endpoint_Write_Stream_LE(&Notification, sizeof(Notification), NO_STREAM_CALLBACK);\r
+ Endpoint_Write_Stream_LE(&LineStateMask, sizeof(LineStateMask), NO_STREAM_CALLBACK);\r
+ Endpoint_ClearIN();\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+#ifndef _CDC_CLASS_H_\r
+#define _CDC_CLASS_H_\r
+\r
+ /* Includes: */\r
+ #include "../../USB.h"\r
+\r
+ #include <string.h>\r
+\r
+ /* Macros: */\r
+ /** CDC Class specific request to get the current virtual serial port configuration settings. */\r
+ #define REQ_GetLineEncoding 0x21\r
+\r
+ /** CDC Class specific request to set the current virtual serial port configuration settings. */\r
+ #define REQ_SetLineEncoding 0x20\r
+\r
+ /** CDC Class specific request to set the current virtual serial port handshake line states. */\r
+ #define REQ_SetControlLineState 0x22\r
+ \r
+ /** Notification type constant for a change in the virtual serial port handshake line states, for\r
+ * use with a USB_Notification_Header_t notification structure when sent to the host via the CDC \r
+ * notification endpoint.\r
+ */\r
+ #define NOTIF_SerialState 0x20\r
+\r
+ /** Mask for the DTR handshake line for use with the REQ_SetControlLineState class specific request\r
+ * from the host, to indicate that the DTR line state should be high.\r
+ */\r
+ #define CONTROL_LINE_OUT_DTR (1 << 0)\r
+\r
+ /** Mask for the RTS handshake line for use with the REQ_SetControlLineState class specific request\r
+ * from the host, to indicate that theRTS line state should be high.\r
+ */\r
+ #define CONTROL_LINE_OUT_RTS (1 << 1)\r
+ \r
+ /** Mask for the DCD handshake line for use with the a NOTIF_SerialState class specific notification\r
+ * from the device to the host, to indicate that the DCD line state is currently high.\r
+ */\r
+ #define CONTROL_LINE_IN_DCD (1 << 0)\r
+\r
+ /** Mask for the DSR handshake line for use with the a NOTIF_SerialState class specific notification\r
+ * from the device to the host, to indicate that the DSR line state is currently high.\r
+ */\r
+ #define CONTROL_LINE_IN_DSR (1 << 1)\r
+\r
+ /** Mask for the BREAK handshake line for use with the a NOTIF_SerialState class specific notification\r
+ * from the device to the host, to indicate that the BREAK line state is currently high.\r
+ */\r
+ #define CONTROL_LINE_IN_BREAK (1 << 2)\r
+\r
+ /** Mask for the RING handshake line for use with the a NOTIF_SerialState class specific notification\r
+ * from the device to the host, to indicate that the RING line state is currently high.\r
+ */\r
+ #define CONTROL_LINE_IN_RING (1 << 3)\r
+\r
+ /** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,\r
+ * to indicate that a framing error has occurred on the virtual serial port.\r
+ */\r
+ #define CONTROL_LINE_IN_FRAMEERROR (1 << 4)\r
+\r
+ /** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,\r
+ * to indicate that a parity error has occurred on the virtual serial port.\r
+ */\r
+ #define CONTROL_LINE_IN_PARITYERROR (1 << 5)\r
+\r
+ /** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,\r
+ * to indicate that a data overrun error has occurred on the virtual serial port.\r
+ */\r
+ #define CONTROL_LINE_IN_OVERRUNERROR (1 << 6)\r
+ \r
+ /** Macro to define a CDC class-specific functional descriptor. CDC functional descriptors have a\r
+ * uniform structure but variable sized data payloads, thus cannot be represented accurately by\r
+ * a single typedef struct. A macro is used instead so that functional descriptors can be created\r
+ * easily by specifying the size of the payload. This allows sizeof() to work correctly.\r
+ *\r
+ * \param DataSize Size in bytes of the CDC functional descriptor's data payload\r
+ */\r
+ #define CDC_FUNCTIONAL_DESCRIPTOR(DataSize) \\r
+ struct \\r
+ { \\r
+ USB_Descriptor_Header_t Header; \\r
+ uint8_t SubType; \\r
+ uint8_t Data[DataSize]; \\r
+ }\r
+\r
+ /* Enums: */\r
+ /** Enum for the possible line encoding formats of a virtual serial port. */\r
+ enum CDCDevice_CDC_LineCodingFormats_t\r
+ {\r
+ OneStopBit = 0, /**< Each frame contains one stop bit */\r
+ OneAndAHalfStopBits = 1, /**< Each frame contains one and a half stop bits */\r
+ TwoStopBits = 2, /**< Each frame contains two stop bits */\r
+ };\r
+ \r
+ /** Enum for the possible line encoding parity settings of a virtual serial port. */\r
+ enum CDCDevice_LineCodingParity_t\r
+ {\r
+ Parity_None = 0, /**< No parity bit mode on each frame */\r
+ Parity_Odd = 1, /**< Odd parity bit mode on each frame */\r
+ Parity_Even = 2, /**< Even parity bit mode on each frame */\r
+ Parity_Mark = 3, /**< Mark parity bit mode on each frame */\r
+ Parity_Space = 4, /**< Space parity bit mode on each frame */\r
+ };\r
+\r
+ /* Type Defines: */\r
+ /** Type define for the virtual serial port line encoding settings, for storing the current USART configuration\r
+ * as set by the host via a class specific request.\r
+ */\r
+ typedef struct\r
+ {\r
+ uint8_t ControlInterfaceNumber; /**< Interface number of the CDC control interface within the device */\r
+\r
+ uint8_t DataINEndpointNumber; /**< Endpoint number of the CDC interface's IN data endpoint */\r
+ uint16_t DataINEndpointSize; /**< Size in bytes of the CDC interface's IN data endpoint */\r
+\r
+ uint8_t DataOUTEndpointNumber; /**< Endpoint number of the CDC interface's OUT data endpoint */\r
+ uint16_t DataOUTEndpointSize; /**< Size in bytes of the CDC interface's OUT data endpoint */\r
+\r
+ uint8_t NotificationEndpointNumber; /**< Endpoint number of the CDC interface's IN notification endpoint, if used */\r
+ uint16_t NotificationEndpointSize; /**< Size in bytes of the CDC interface's IN notification endpoint, if used */\r
+\r
+ uint8_t ControlLineState;\r
+\r
+ struct\r
+ {\r
+ uint32_t BaudRateBPS; /**< Baud rate of the virtual serial port, in bits per second */\r
+ uint8_t CharFormat; /**< Character format of the virtual serial port, a value from the\r
+ * CDCDevice_CDC_LineCodingFormats_t enum\r
+ */\r
+ uint8_t ParityType; /**< Parity setting of the virtual serial port, a value from the\r
+ * CDCDevice_LineCodingParity_t enum\r
+ */\r
+ uint8_t DataBits; /**< Bits of data per character of the virtual serial port */\r
+ } LineEncoding;\r
+ } USB_ClassInfo_CDC_t;\r
+ \r
+ /* Function Prototypes: */\r
+ #if defined(INCLUDE_FROM_CDC_CLASS_C)\r
+ void USB_CDC_Event_Stub(void);\r
+ void EVENT_USB_CDC_LineEncodingChanged(USB_ClassInfo_CDC_t* CDCInterfaceInfo)\r
+ ATTR_WEAK ATTR_ALIAS(USB_CDC_Event_Stub);\r
+ void EVENT_USB_CDC_ControLineStateChanged(void) ATTR_WEAK ATTR_ALIAS(USB_CDC_Event_Stub);; \r
+ #endif\r
+ \r
+ void USB_CDC_USBTask(USB_ClassInfo_CDC_t* CDCInterfaceInfo);\r
+ bool USB_CDC_ConfigureEndpoints(USB_ClassInfo_CDC_t* CDCInterfaceInfo);\r
+ void USB_CDC_ProcessControlPacket(USB_ClassInfo_CDC_t* CDCInterfaceInfo);\r
+ void USB_CDC_USBTask(USB_ClassInfo_CDC_t* CDCInterfaceInfo);\r
+\r
+ void EVENT_USB_CDC_LineEncodingChanged(USB_ClassInfo_CDC_t* CDCInterfaceInfo);\r
+ void EVENT_USB_CDC_ControLineStateChanged(void);\r
+\r
+ void USB_CDC_SendString(USB_ClassInfo_CDC_t* CDCInterfaceInfo, char* Data, uint16_t Length);\r
+ void USB_CDC_SendByte(USB_ClassInfo_CDC_t* CDCInterfaceInfo, uint8_t Data);\r
+ uint16_t USB_CDC_BytesReceived(USB_ClassInfo_CDC_t* CDCInterfaceInfo);\r
+ uint8_t USB_CDC_ReceiveByte(USB_ClassInfo_CDC_t* CDCInterfaceInfo);\r
+ void USB_CDC_SendSerialLineStateChanged(USB_ClassInfo_CDC_t* CDCInterfaceInfo, uint16_t LineStateMask);\r
+ \r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+#include "HID.h"\r
+\r
+void USB_HID_ProcessControlPacket(USB_ClassInfo_HID_t* HIDInterfaceInfo)\r
+{\r
+ if (!(Endpoint_IsSETUPReceived()))\r
+ return;\r
+ \r
+ if (USB_ControlRequest.wIndex != HIDInterfaceInfo->InterfaceNumber)\r
+ return;\r
+\r
+ switch (USB_ControlRequest.bRequest)\r
+ {\r
+ case REQ_GetReport:\r
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
+ {\r
+ Endpoint_ClearSETUP(); \r
+\r
+ uint8_t ReportINData[HIDInterfaceInfo->ReportBufferSize];\r
+ uint16_t ReportINSize;\r
+\r
+ memset(ReportINData, 0, sizeof(ReportINData));\r
+\r
+ ReportINSize = CALLBACK_USB_HID_CreateNextHIDReport(HIDInterfaceInfo, ReportINData);\r
+\r
+ Endpoint_Write_Control_Stream_LE(ReportINData, ReportINSize);\r
+ Endpoint_ClearOUT();\r
+ }\r
+ \r
+ break;\r
+ case REQ_SetReport:\r
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
+ {\r
+ Endpoint_ClearSETUP();\r
+ \r
+ uint16_t ReportOUTSize = USB_ControlRequest.wLength;\r
+ uint8_t ReportOUTData[ReportOUTSize];\r
+\r
+ Endpoint_Read_Control_Stream_LE(ReportOUTData, ReportOUTSize);\r
+ Endpoint_ClearIN();\r
+ \r
+ CALLBACK_USB_HID_ProcessReceivedHIDReport(HIDInterfaceInfo, ReportOUTData, ReportOUTSize);\r
+ }\r
+ \r
+ break;\r
+ case REQ_GetProtocol:\r
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
+ {\r
+ Endpoint_ClearSETUP();\r
+\r
+ Endpoint_Write_Byte(HIDInterfaceInfo->UsingReportProtocol);\r
+ Endpoint_ClearIN();\r
+\r
+ while (!(Endpoint_IsOUTReceived()));\r
+ Endpoint_ClearOUT();\r
+ }\r
+ \r
+ break;\r
+ case REQ_SetProtocol:\r
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
+ {\r
+ Endpoint_ClearSETUP();\r
+\r
+ HIDInterfaceInfo->UsingReportProtocol = (USB_ControlRequest.wValue != 0x0000);\r
+ \r
+ while (!(Endpoint_IsINReady()));\r
+ Endpoint_ClearIN();\r
+ }\r
+ \r
+ break;\r
+ case REQ_SetIdle:\r
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
+ {\r
+ Endpoint_ClearSETUP();\r
+ \r
+ HIDInterfaceInfo->IdleCount = ((USB_ControlRequest.wValue >> 8) << 2);\r
+ \r
+ while (!(Endpoint_IsINReady()));\r
+ Endpoint_ClearIN();\r
+ }\r
+ \r
+ break;\r
+ case REQ_GetIdle:\r
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
+ { \r
+ Endpoint_ClearSETUP();\r
+ \r
+ Endpoint_Write_Byte(HIDInterfaceInfo->IdleCount >> 2);\r
+ Endpoint_ClearIN();\r
+\r
+ while (!(Endpoint_IsOUTReceived()));\r
+ Endpoint_ClearOUT();\r
+ }\r
+\r
+ break;\r
+ }\r
+}\r
+\r
+bool USB_HID_ConfigureEndpoints(USB_ClassInfo_HID_t* HIDInterfaceInfo)\r
+{\r
+ HIDInterfaceInfo->UsingReportProtocol = true;\r
+\r
+ if (!(Endpoint_ConfigureEndpoint(HIDInterfaceInfo->ReportINEndpointNumber, EP_TYPE_INTERRUPT,\r
+ ENDPOINT_DIR_IN, HIDInterfaceInfo->ReportINEndpointSize, ENDPOINT_BANK_SINGLE)))\r
+ {\r
+ return false;\r
+ }\r
+ \r
+ if (HIDInterfaceInfo->ReportOUTEndpointNumber)\r
+ {\r
+ if (!(Endpoint_ConfigureEndpoint(HIDInterfaceInfo->ReportOUTEndpointNumber, EP_TYPE_INTERRUPT,\r
+ ENDPOINT_DIR_OUT, HIDInterfaceInfo->ReportOUTEndpointSize, ENDPOINT_BANK_SINGLE)))\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+ \r
+ return true;\r
+}\r
+\r
+void USB_HID_RegisterStartOfFrame(USB_ClassInfo_HID_t* HIDInterfaceInfo)\r
+{\r
+ if (HIDInterfaceInfo->IdleMSRemaining)\r
+ HIDInterfaceInfo->IdleMSRemaining--;\r
+}\r
+ \r
+void USB_HID_USBTask(USB_ClassInfo_HID_t* HIDInterfaceInfo)\r
+{\r
+ if (!(USB_IsConnected))\r
+ return;\r
+\r
+ Endpoint_SelectEndpoint(HIDInterfaceInfo->ReportINEndpointNumber);\r
+ \r
+ if (Endpoint_IsReadWriteAllowed() &&\r
+ !(HIDInterfaceInfo->IdleCount && HIDInterfaceInfo->IdleMSRemaining))\r
+ {\r
+ if (HIDInterfaceInfo->IdleCount && !(HIDInterfaceInfo->IdleMSRemaining))\r
+ HIDInterfaceInfo->IdleMSRemaining = HIDInterfaceInfo->IdleCount;\r
+\r
+ uint8_t ReportINData[HIDInterfaceInfo->ReportBufferSize];\r
+ uint16_t ReportINSize;\r
+\r
+ memset(ReportINData, 0, sizeof(ReportINData));\r
+\r
+ ReportINSize = CALLBACK_USB_HID_CreateNextHIDReport(HIDInterfaceInfo, ReportINData);\r
+\r
+ if (ReportINSize)\r
+ {\r
+ Endpoint_Write_Stream_LE(ReportINData, ReportINSize\r
+ #if !defined(NO_STREAM_CALLBACKS)\r
+ , NO_STREAM_CALLBACK\r
+ #endif\r
+ );\r
+ }\r
+ \r
+ Endpoint_ClearIN();\r
+ }\r
+ \r
+ if (HIDInterfaceInfo->ReportOUTEndpointNumber)\r
+ {\r
+ Endpoint_SelectEndpoint(HIDInterfaceInfo->ReportOUTEndpointNumber);\r
+ \r
+ if (Endpoint_IsOUTReceived())\r
+ {\r
+ uint16_t ReportOUTSize = Endpoint_BytesInEndpoint();\r
+ uint8_t ReportOUTData[ReportOUTSize];\r
+ \r
+ if (ReportOUTSize)\r
+ {\r
+ Endpoint_Read_Stream_LE(ReportOUTData, ReportOUTSize\r
+ #if !defined(NO_STREAM_CALLBACKS)\r
+ , NO_STREAM_CALLBACK\r
+ #endif\r
+ );\r
+ }\r
+ \r
+ CALLBACK_USB_HID_ProcessReceivedHIDReport(HIDInterfaceInfo, ReportOUTData, ReportOUTSize);\r
+ \r
+ Endpoint_ClearOUT();\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+#ifndef _HID_CLASS_H_\r
+#define _HID_CLASS_H_\r
+\r
+ /* Includes: */\r
+ #include "../../USB.h"\r
+\r
+ #include <string.h>\r
+\r
+ /* Macros: */\r
+ /** HID Class Specific Request to get the current HID report from the device. */\r
+ #define REQ_GetReport 0x01\r
+\r
+ /** HID Class Specific Request to get the current device idle count. */\r
+ #define REQ_GetIdle 0x02\r
+\r
+ /** HID Class Specific Request to set the current HID report to the device. */\r
+ #define REQ_SetReport 0x09\r
+\r
+ /** HID Class Specific Request to set the device's idle count. */\r
+ #define REQ_SetIdle 0x0A\r
+\r
+ /** HID Class Specific Request to get the current HID report protocol mode. */\r
+ #define REQ_GetProtocol 0x03\r
+\r
+ /** HID Class Specific Request to set the current HID report protocol mode. */\r
+ #define REQ_SetProtocol 0x0B\r
+\r
+ /** Descriptor header type value, to indicate a HID class HID descriptor. */\r
+ #define DTYPE_HID 0x21\r
+ \r
+ /** Descriptor header type value, to indicate a HID class HID report descriptor. */\r
+ #define DTYPE_Report 0x22\r
+\r
+ /* Type Defines: */\r
+ /** Type define for the HID class specific HID descriptor, to describe the HID device's specifications. Refer to the HID\r
+ * specification for details on the structure elements.\r
+ */\r
+ typedef struct\r
+ {\r
+ USB_Descriptor_Header_t Header;\r
+ \r
+ uint16_t HIDSpec;\r
+ uint8_t CountryCode;\r
+ \r
+ uint8_t TotalReportDescriptors;\r
+\r
+ uint8_t HIDReportType;\r
+ uint16_t HIDReportLength;\r
+ } USB_Descriptor_HID_t;\r
+\r
+ /** Type define for the data type used to store HID report descriptor elements. */\r
+ typedef uint8_t USB_Descriptor_HIDReport_Datatype_t;\r
+\r
+ /** Class state structure. An instance of this structure should be made for each HID interface\r
+ * within the user application, and passed to each of the HID class driver functions as the\r
+ * HIDInterfaceInfo parameter. The contents of this structure should be set to their correct\r
+ * values when used, or ommitted to force the library to use default values.\r
+ */\r
+ typedef struct\r
+ {\r
+ uint8_t InterfaceNumber; /**< Interface number of the HID interface within the device */\r
+\r
+ uint8_t ReportINEndpointNumber; /**< Endpoint number of the HID interface's IN report endpoint */\r
+ uint16_t ReportINEndpointSize; /**< Size in bytes of the HID interface's IN report endpoint */\r
+\r
+ uint8_t ReportOUTEndpointNumber; /**< Endpoint number of the HID interface's OUT report endpoint, if used */\r
+ uint16_t ReportOUTEndpointSize; /**< Size in bytes of the HID interface's OUT report endpoint, if used */\r
+ \r
+ uint8_t ReportBufferSize;\r
+\r
+ bool UsingReportProtocol; /**< Indicates if the HID interface is set to Boot or Report protocol mode */\r
+ uint16_t IdleCount; /**< Report idle period, in ms, set by the host */\r
+ uint16_t IdleMSRemaining; /**< Total number of ms remaining before the idle period elapses */\r
+ } USB_ClassInfo_HID_t;\r
+\r
+ /* Function Prototypes: */\r
+ bool USB_HID_ConfigureEndpoints(USB_ClassInfo_HID_t* HIDInterfaceInfo);\r
+ void USB_HID_ProcessControlPacket(USB_ClassInfo_HID_t* HIDInterfaceInfo);\r
+ void USB_HID_RegisterStartOfFrame(USB_ClassInfo_HID_t* HIDInterfaceInfo);\r
+ void USB_HID_USBTask(USB_ClassInfo_HID_t* HIDInterfaceInfo);\r
+ \r
+ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);\r
+ void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize);\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+#define INCLUDE_FROM_MS_CLASS_C\r
+#include "MassStorage.h"\r
+\r
+static USB_ClassInfo_MS_t* CallbackMSInterfaceInfo;\r
+\r
+void USB_MS_ProcessControlPacket(USB_ClassInfo_MS_t* MSInterfaceInfo)\r
+{\r
+ if (!(Endpoint_IsSETUPReceived()))\r
+ return;\r
+ \r
+ if (USB_ControlRequest.wIndex != MSInterfaceInfo->InterfaceNumber)\r
+ return;\r
+\r
+ switch (USB_ControlRequest.bRequest)\r
+ {\r
+ case REQ_MassStorageReset:\r
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
+ {\r
+ Endpoint_ClearSETUP();\r
+\r
+ MSInterfaceInfo->IsMassStoreReset = true; \r
+\r
+ while (!(Endpoint_IsINReady()));\r
+ Endpoint_ClearIN();\r
+ }\r
+\r
+ break;\r
+ case REQ_GetMaxLUN:\r
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
+ {\r
+ Endpoint_ClearSETUP();\r
+\r
+ Endpoint_Write_Byte(MSInterfaceInfo->TotalLUNs - 1);\r
+ \r
+ Endpoint_ClearIN();\r
+ \r
+ while (!(Endpoint_IsOUTReceived()));\r
+ Endpoint_ClearOUT();\r
+ }\r
+ \r
+ break;\r
+ }\r
+}\r
+\r
+bool USB_MS_ConfigureEndpoints(USB_ClassInfo_MS_t* MSInterfaceInfo)\r
+{\r
+ if (!(Endpoint_ConfigureEndpoint(MSInterfaceInfo->DataINEndpointNumber, EP_TYPE_BULK,\r
+ ENDPOINT_DIR_IN, MSInterfaceInfo->DataINEndpointSize,\r
+ ENDPOINT_BANK_SINGLE)))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ if (!(Endpoint_ConfigureEndpoint(MSInterfaceInfo->DataOUTEndpointNumber, EP_TYPE_BULK,\r
+ ENDPOINT_DIR_OUT, MSInterfaceInfo->DataOUTEndpointSize,\r
+ ENDPOINT_BANK_SINGLE)))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+void USB_MS_USBTask(USB_ClassInfo_MS_t* MSInterfaceInfo)\r
+{\r
+ if (!(USB_IsConnected))\r
+ return;\r
+\r
+ Endpoint_SelectEndpoint(MSInterfaceInfo->DataOUTEndpointNumber);\r
+ \r
+ if (Endpoint_IsReadWriteAllowed())\r
+ {\r
+ if (USB_MS_ReadInCommandBlock(MSInterfaceInfo))\r
+ {\r
+ if (MSInterfaceInfo->CommandBlock.Flags & COMMAND_DIRECTION_DATA_IN)\r
+ Endpoint_SelectEndpoint(MSInterfaceInfo->DataINEndpointNumber);\r
+ \r
+ MSInterfaceInfo->CommandStatus.Status = CALLBACK_USB_MS_SCSICommandReceived(MSInterfaceInfo) ?\r
+ Command_Pass : Command_Fail;\r
+ MSInterfaceInfo->CommandStatus.Signature = CSW_SIGNATURE;\r
+ MSInterfaceInfo->CommandStatus.Tag = MSInterfaceInfo->CommandBlock.Tag;\r
+ MSInterfaceInfo->CommandStatus.DataTransferResidue = MSInterfaceInfo->CommandBlock.DataTransferLength;\r
+\r
+ if ((MSInterfaceInfo->CommandStatus.Status == Command_Fail) && (MSInterfaceInfo->CommandStatus.DataTransferResidue))\r
+ Endpoint_StallTransaction();\r
+ \r
+ USB_MS_ReturnCommandStatus(MSInterfaceInfo);\r
+ \r
+ if (MSInterfaceInfo->IsMassStoreReset)\r
+ {\r
+ Endpoint_ResetFIFO(MSInterfaceInfo->DataOUTEndpointNumber);\r
+ Endpoint_ResetFIFO(MSInterfaceInfo->DataINEndpointNumber);\r
+ \r
+ Endpoint_SelectEndpoint(MSInterfaceInfo->DataOUTEndpointNumber);\r
+ Endpoint_ClearStall();\r
+ Endpoint_SelectEndpoint(MSInterfaceInfo->DataINEndpointNumber);\r
+ Endpoint_ClearStall();\r
+\r
+ MSInterfaceInfo->IsMassStoreReset = false;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+static bool USB_MS_ReadInCommandBlock(USB_ClassInfo_MS_t* MSInterfaceInfo)\r
+{\r
+ Endpoint_SelectEndpoint(MSInterfaceInfo->DataOUTEndpointNumber);\r
+\r
+ CallbackMSInterfaceInfo = MSInterfaceInfo;\r
+ Endpoint_Read_Stream_LE(&MSInterfaceInfo->CommandBlock,\r
+ (sizeof(CommandBlockWrapper_t) - MAX_SCSI_COMMAND_LENGTH),\r
+ StreamCallback_AbortOnMassStoreReset);\r
+\r
+ if ((MSInterfaceInfo->CommandBlock.Signature != CBW_SIGNATURE) ||\r
+ (MSInterfaceInfo->CommandBlock.LUN >= MSInterfaceInfo->TotalLUNs) ||\r
+ (MSInterfaceInfo->CommandBlock.SCSICommandLength > MAX_SCSI_COMMAND_LENGTH))\r
+ {\r
+ Endpoint_StallTransaction();\r
+ Endpoint_SelectEndpoint(MSInterfaceInfo->DataINEndpointNumber);\r
+ Endpoint_StallTransaction();\r
+ \r
+ return false;\r
+ }\r
+\r
+ CallbackMSInterfaceInfo = MSInterfaceInfo;\r
+ Endpoint_Read_Stream_LE(&MSInterfaceInfo->CommandBlock.SCSICommandData,\r
+ MSInterfaceInfo->CommandBlock.SCSICommandLength,\r
+ StreamCallback_AbortOnMassStoreReset);\r
+ \r
+ Endpoint_ClearOUT();\r
+ \r
+ if (MSInterfaceInfo->IsMassStoreReset)\r
+ return false;\r
+\r
+ return true;\r
+}\r
+\r
+static void USB_MS_ReturnCommandStatus(USB_ClassInfo_MS_t* MSInterfaceInfo)\r
+{\r
+ Endpoint_SelectEndpoint(MSInterfaceInfo->DataOUTEndpointNumber);\r
+\r
+ while (Endpoint_IsStalled())\r
+ {\r
+ USB_USBTask();\r
+\r
+ if (MSInterfaceInfo->IsMassStoreReset)\r
+ return;\r
+ }\r
+\r
+ Endpoint_SelectEndpoint(MSInterfaceInfo->DataINEndpointNumber);\r
+\r
+ while (Endpoint_IsStalled())\r
+ {\r
+ USB_USBTask();\r
+\r
+ if (MSInterfaceInfo->IsMassStoreReset)\r
+ return;\r
+ }\r
+ \r
+ CallbackMSInterfaceInfo = MSInterfaceInfo;\r
+ Endpoint_Write_Stream_LE(&MSInterfaceInfo->CommandStatus, sizeof(CommandStatusWrapper_t),\r
+ StreamCallback_AbortOnMassStoreReset);\r
+ \r
+ Endpoint_ClearIN();\r
+\r
+ if (MSInterfaceInfo->IsMassStoreReset)\r
+ return;\r
+}\r
+\r
+static uint8_t StreamCallback_AbortOnMassStoreReset(void)\r
+{\r
+ USB_MS_USBTask(CallbackMSInterfaceInfo);\r
+\r
+ if (CallbackMSInterfaceInfo->IsMassStoreReset)\r
+ return STREAMCALLBACK_Abort;\r
+ else\r
+ return STREAMCALLBACK_Continue;\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+#ifndef _MS_CLASS_H_\r
+#define _MS_CLASS_H_\r
+\r
+ /* Includes: */\r
+ #include "../../USB.h"\r
+\r
+ #include <string.h>\r
+\r
+ /* Macros: */\r
+ /** Mass Storage Class specific request to reset the Mass Storage interface, ready for the next command. */\r
+ #define REQ_MassStorageReset 0xFF\r
+\r
+ /** Mass Storage Class specific request to retrieve the total number of Logical Units (drives) in the SCSI device. */\r
+ #define REQ_GetMaxLUN 0xFE\r
+\r
+ /** Maximum length of a SCSI command which can be issued by the device or host in a Mass Storage bulk wrapper. */\r
+ #define MAX_SCSI_COMMAND_LENGTH 16\r
+ \r
+ /** Magic signature for a Command Block Wrapper used in the Mass Storage Bulk-Only transport protocol. */\r
+ #define CBW_SIGNATURE 0x43425355UL\r
+\r
+ /** Magic signature for a Command Status Wrapper used in the Mass Storage Bulk-Only transport protocol. */\r
+ #define CSW_SIGNATURE 0x53425355UL\r
+ \r
+ /** Mask for a Command Block Wrapper's flags attribute to specify a command with data sent from host-to-device. */\r
+ #define COMMAND_DIRECTION_DATA_OUT (0 << 7)\r
+\r
+ /** Mask for a Command Block Wrapper's flags attribute to specify a command with data sent from device-to-host. */\r
+ #define COMMAND_DIRECTION_DATA_IN (1 << 7)\r
+\r
+ /* Type defines: */\r
+ /** Type define for a Command Block Wrapper, used in the Mass Storage Bulk-Only Transport protocol. */\r
+ typedef struct\r
+ {\r
+ uint32_t Signature; /**< Command block signature, must be CBW_SIGNATURE to indicate a valid Command Block */\r
+ uint32_t Tag; /**< Unique command ID value, to associate a command block wrapper with its command status wrapper */\r
+ uint32_t DataTransferLength; /** Length of the optional data portion of the issued command, in bytes */\r
+ uint8_t Flags; /**< Command block flags, indicating command data direction */\r
+ uint8_t LUN; /**< Logical Unit number this command is issued to */\r
+ uint8_t SCSICommandLength; /**< Length of the issued SCSI command within the SCSI command data array */\r
+ uint8_t SCSICommandData[MAX_SCSI_COMMAND_LENGTH]; /**< Issued SCSI command in the Command Block */\r
+ } CommandBlockWrapper_t;\r
+ \r
+ /** Type define for a Command Status Wrapper, used in the Mass Storage Bulk-Only Transport protocol. */\r
+ typedef struct\r
+ {\r
+ uint32_t Signature; /**< Status block signature, must be CSW_SIGNATURE to indicate a valid Command Status */\r
+ uint32_t Tag; /**< Unique command ID value, to associate a command block wrapper with its command status wrapper */\r
+ uint32_t DataTransferResidue; /**< Number of bytes of data not processed in the SCSI command */\r
+ uint8_t Status; /**< Status code of the issued command - a value from the MassStorage_CommandStatusCodes_t enum */\r
+ } CommandStatusWrapper_t;\r
+ \r
+ /* Enums: */\r
+ /** Enum for the possible command status wrapper return status codes. */\r
+ enum MassStorage_CommandStatusCodes_t\r
+ {\r
+ Command_Pass = 0, /**< Command completed with no error */\r
+ Command_Fail = 1, /**< Command failed to complete - host may check the exact error via a SCSI REQUEST SENSE command */\r
+ Phase_Error = 2 /**< Command failed due to being invalid in the current phase */\r
+ };\r
+ \r
+ /* Type Defines: */\r
+ /** Type define for the virtual serial port line encoding settings, for storing the current USART configuration\r
+ * as set by the host via a class specific request.\r
+ */\r
+ typedef struct\r
+ {\r
+ uint8_t InterfaceNumber; /**< Interface number of the Mass Storage interface within the device */\r
+\r
+ uint8_t DataINEndpointNumber; /**< Endpoint number of the Mass Storage interface's IN data endpoint */\r
+ uint16_t DataINEndpointSize; /**< Size in bytes of the Mass Storage interface's IN data endpoint */\r
+\r
+ uint8_t DataOUTEndpointNumber; /**< Endpoint number of the Mass Storage interface's OUT data endpoint */\r
+ uint16_t DataOUTEndpointSize; /**< Size in bytes of the Mass Storage interface's OUT data endpoint */\r
+\r
+ uint8_t TotalLUNs;\r
+\r
+ CommandBlockWrapper_t CommandBlock;\r
+ CommandStatusWrapper_t CommandStatus;\r
+\r
+ bool IsMassStoreReset;\r
+ } USB_ClassInfo_MS_t;\r
+ \r
+ /* Function Prototypes: */\r
+ #if defined(INCLUDE_FROM_MS_CLASS_C)\r
+ static void USB_MS_ReturnCommandStatus(USB_ClassInfo_MS_t* MSInterfaceInfo);\r
+ static bool USB_MS_ReadInCommandBlock(USB_ClassInfo_MS_t* MSInterfaceInfo);\r
+ static uint8_t StreamCallback_AbortOnMassStoreReset(void);\r
+ #endif\r
+ \r
+ void USB_MS_USBTask(USB_ClassInfo_MS_t* MSInterfaceInfo);\r
+ bool USB_MS_ConfigureEndpoints(USB_ClassInfo_MS_t* MSInterfaceInfo);\r
+ void USB_MS_ProcessControlPacket(USB_ClassInfo_MS_t* MSInterfaceInfo);\r
+ \r
+ bool CALLBACK_USB_MS_SCSICommandReceived(USB_ClassInfo_MS_t* MSInterfaceInfo);\r
+ \r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+#define INCLUDE_FROM_RNDIS_CLASS_C\r
+#include "RNDIS.h"\r
+\r
+static const uint32_t PROGMEM AdapterSupportedOIDList[] =\r
+ {\r
+ OID_GEN_SUPPORTED_LIST,\r
+ OID_GEN_PHYSICAL_MEDIUM,\r
+ OID_GEN_HARDWARE_STATUS,\r
+ OID_GEN_MEDIA_SUPPORTED,\r
+ OID_GEN_MEDIA_IN_USE,\r
+ OID_GEN_MAXIMUM_FRAME_SIZE,\r
+ OID_GEN_MAXIMUM_TOTAL_SIZE,\r
+ OID_GEN_LINK_SPEED,\r
+ OID_GEN_TRANSMIT_BLOCK_SIZE,\r
+ OID_GEN_RECEIVE_BLOCK_SIZE,\r
+ OID_GEN_VENDOR_ID,\r
+ OID_GEN_VENDOR_DESCRIPTION,\r
+ OID_GEN_CURRENT_PACKET_FILTER,\r
+ OID_GEN_MAXIMUM_TOTAL_SIZE,\r
+ OID_GEN_MEDIA_CONNECT_STATUS,\r
+ OID_GEN_XMIT_OK,\r
+ OID_GEN_RCV_OK,\r
+ OID_GEN_XMIT_ERROR,\r
+ OID_GEN_RCV_ERROR,\r
+ OID_GEN_RCV_NO_BUFFER,\r
+ OID_802_3_PERMANENT_ADDRESS,\r
+ OID_802_3_CURRENT_ADDRESS,\r
+ OID_802_3_MULTICAST_LIST,\r
+ OID_802_3_MAXIMUM_LIST_SIZE,\r
+ OID_802_3_RCV_ERROR_ALIGNMENT,\r
+ OID_802_3_XMIT_ONE_COLLISION,\r
+ OID_802_3_XMIT_MORE_COLLISIONS,\r
+ };\r
+\r
+void USB_RNDIS_ProcessControlPacket(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo)\r
+{\r
+ if (!(Endpoint_IsSETUPReceived()))\r
+ return;\r
+ \r
+ if (USB_ControlRequest.wIndex != RNDISInterfaceInfo->ControlInterfaceNumber)\r
+ return;\r
+\r
+ switch (USB_ControlRequest.bRequest)\r
+ {\r
+ case REQ_SendEncapsulatedCommand:\r
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
+ {\r
+ Endpoint_ClearSETUP();\r
+\r
+ Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo->RNDISMessageBuffer, USB_ControlRequest.wLength);\r
+ Endpoint_ClearIN();\r
+\r
+ USB_RNDIS_ProcessRNDISControlMessage(RNDISInterfaceInfo);\r
+ }\r
+ \r
+ break;\r
+ case REQ_GetEncapsulatedResponse:\r
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
+ {\r
+ Endpoint_ClearSETUP();\r
+\r
+ RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;\r
+\r
+ if (!(MessageHeader->MessageLength))\r
+ {\r
+ RNDISInterfaceInfo->RNDISMessageBuffer[0] = 0;\r
+ MessageHeader->MessageLength = 1;\r
+ }\r
+\r
+ Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->RNDISMessageBuffer, MessageHeader->MessageLength); \r
+ Endpoint_ClearOUT();\r
+\r
+ MessageHeader->MessageLength = 0;\r
+ }\r
+ \r
+ break;\r
+ }\r
+}\r
+\r
+bool USB_RNDIS_ConfigureEndpoints(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo)\r
+{\r
+ if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->DataINEndpointNumber, EP_TYPE_BULK,\r
+ ENDPOINT_DIR_IN, RNDISInterfaceInfo->DataINEndpointSize,\r
+ ENDPOINT_BANK_SINGLE)))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->DataOUTEndpointNumber, EP_TYPE_BULK,\r
+ ENDPOINT_DIR_OUT, RNDISInterfaceInfo->DataOUTEndpointSize,\r
+ ENDPOINT_BANK_SINGLE)))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->NotificationEndpointNumber, EP_TYPE_INTERRUPT,\r
+ ENDPOINT_DIR_IN, RNDISInterfaceInfo->NotificationEndpointSize,\r
+ ENDPOINT_BANK_SINGLE)))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+void USB_RNDIS_USBTask(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo)\r
+{\r
+ if (!(USB_IsConnected))\r
+ return;\r
+\r
+ RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;\r
+\r
+ Endpoint_SelectEndpoint(RNDISInterfaceInfo->NotificationEndpointNumber);\r
+\r
+ if (Endpoint_IsINReady() && RNDISInterfaceInfo->ResponseReady)\r
+ {\r
+ USB_Request_Header_t Notification = (USB_Request_Header_t)\r
+ {\r
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),\r
+ .bRequest = NOTIF_ResponseAvailable,\r
+ .wValue = 0,\r
+ .wIndex = 0,\r
+ .wLength = 0,\r
+ };\r
+ \r
+ Endpoint_Write_Stream_LE(&Notification, sizeof(Notification), NO_STREAM_CALLBACK);\r
+\r
+ Endpoint_ClearIN();\r
+\r
+ RNDISInterfaceInfo->ResponseReady = false;\r
+ }\r
+ \r
+ if ((RNDISInterfaceInfo->CurrRNDISState == RNDIS_Data_Initialized) && !(MessageHeader->MessageLength))\r
+ {\r
+ RNDIS_PACKET_MSG_t RNDISPacketHeader;\r
+\r
+ Endpoint_SelectEndpoint(RNDISInterfaceInfo->DataOUTEndpointNumber);\r
+\r
+ if (Endpoint_IsOUTReceived() && !(RNDISInterfaceInfo->FrameIN.FrameInBuffer))\r
+ {\r
+ Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_PACKET_MSG_t), NO_STREAM_CALLBACK);\r
+\r
+ if (RNDISPacketHeader.DataLength > ETHERNET_FRAME_SIZE_MAX)\r
+ {\r
+ Endpoint_StallTransaction();\r
+ return;\r
+ }\r
+ \r
+ Endpoint_Read_Stream_LE(RNDISInterfaceInfo->FrameIN.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK);\r
+\r
+ Endpoint_ClearOUT();\r
+ \r
+ RNDISInterfaceInfo->FrameIN.FrameLength = RNDISPacketHeader.DataLength;\r
+\r
+ RNDISInterfaceInfo->FrameIN.FrameInBuffer = true;\r
+ }\r
+ \r
+ Endpoint_SelectEndpoint(RNDISInterfaceInfo->DataINEndpointNumber);\r
+ \r
+ if (Endpoint_IsINReady() && RNDISInterfaceInfo->FrameOUT.FrameInBuffer)\r
+ {\r
+ memset(&RNDISPacketHeader, 0, sizeof(RNDIS_PACKET_MSG_t));\r
+\r
+ RNDISPacketHeader.MessageType = REMOTE_NDIS_PACKET_MSG;\r
+ RNDISPacketHeader.MessageLength = (sizeof(RNDIS_PACKET_MSG_t) + RNDISInterfaceInfo->FrameOUT.FrameLength);\r
+ RNDISPacketHeader.DataOffset = (sizeof(RNDIS_PACKET_MSG_t) - sizeof(RNDIS_Message_Header_t));\r
+ RNDISPacketHeader.DataLength = RNDISInterfaceInfo->FrameOUT.FrameLength;\r
+\r
+ Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_PACKET_MSG_t), NO_STREAM_CALLBACK);\r
+ Endpoint_Write_Stream_LE(RNDISInterfaceInfo->FrameOUT.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK);\r
+ Endpoint_ClearIN();\r
+ \r
+ RNDISInterfaceInfo->FrameOUT.FrameInBuffer = false;\r
+ }\r
+ }\r
+} \r
+\r
+void USB_RNDIS_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo)\r
+{\r
+ /* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of\r
+ this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */\r
+\r
+ RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;\r
+\r
+ switch (MessageHeader->MessageType)\r
+ {\r
+ case REMOTE_NDIS_INITIALIZE_MSG:\r
+ RNDISInterfaceInfo->ResponseReady = true;\r
+ \r
+ RNDIS_INITIALIZE_MSG_t* INITIALIZE_Message = (RNDIS_INITIALIZE_MSG_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;\r
+ RNDIS_INITIALIZE_CMPLT_t* INITIALIZE_Response = (RNDIS_INITIALIZE_CMPLT_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;\r
+ \r
+ INITIALIZE_Response->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;\r
+ INITIALIZE_Response->MessageLength = sizeof(RNDIS_INITIALIZE_CMPLT_t);\r
+ INITIALIZE_Response->RequestId = INITIALIZE_Message->RequestId;\r
+ INITIALIZE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
+ \r
+ INITIALIZE_Response->MajorVersion = REMOTE_NDIS_VERSION_MAJOR;\r
+ INITIALIZE_Response->MinorVersion = REMOTE_NDIS_VERSION_MINOR; \r
+ INITIALIZE_Response->DeviceFlags = REMOTE_NDIS_DF_CONNECTIONLESS;\r
+ INITIALIZE_Response->Medium = REMOTE_NDIS_MEDIUM_802_3;\r
+ INITIALIZE_Response->MaxPacketsPerTransfer = 1;\r
+ INITIALIZE_Response->MaxTransferSize = (sizeof(RNDIS_PACKET_MSG_t) + ETHERNET_FRAME_SIZE_MAX);\r
+ INITIALIZE_Response->PacketAlignmentFactor = 0;\r
+ INITIALIZE_Response->AFListOffset = 0;\r
+ INITIALIZE_Response->AFListSize = 0;\r
+ \r
+ RNDISInterfaceInfo->CurrRNDISState = RNDIS_Initialized;\r
+ \r
+ break;\r
+ case REMOTE_NDIS_HALT_MSG:\r
+ RNDISInterfaceInfo->ResponseReady = false;\r
+ MessageHeader->MessageLength = 0;\r
+\r
+ RNDISInterfaceInfo->CurrRNDISState = RNDIS_Uninitialized;\r
+\r
+ break;\r
+ case REMOTE_NDIS_QUERY_MSG:\r
+ RNDISInterfaceInfo->ResponseReady = true;\r
+ \r
+ RNDIS_QUERY_MSG_t* QUERY_Message = (RNDIS_QUERY_MSG_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;\r
+ RNDIS_QUERY_CMPLT_t* QUERY_Response = (RNDIS_QUERY_CMPLT_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;\r
+ uint32_t Query_Oid = QUERY_Message->Oid;\r
+ \r
+ void* QueryData = &RNDISInterfaceInfo->RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +\r
+ QUERY_Message->InformationBufferOffset];\r
+ void* ResponseData = &RNDISInterfaceInfo->RNDISMessageBuffer[sizeof(RNDIS_QUERY_CMPLT_t)]; \r
+ uint16_t ResponseSize;\r
+\r
+ QUERY_Response->MessageType = REMOTE_NDIS_QUERY_CMPLT;\r
+ QUERY_Response->MessageLength = sizeof(RNDIS_QUERY_CMPLT_t);\r
+ \r
+ if (USB_RNDIS_ProcessNDISQuery(RNDISInterfaceInfo, Query_Oid, QueryData, QUERY_Message->InformationBufferLength,\r
+ ResponseData, &ResponseSize))\r
+ {\r
+ QUERY_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
+ QUERY_Response->MessageLength += ResponseSize;\r
+ \r
+ QUERY_Response->InformationBufferLength = ResponseSize;\r
+ QUERY_Response->InformationBufferOffset = (sizeof(RNDIS_QUERY_CMPLT_t) - sizeof(RNDIS_Message_Header_t));\r
+ }\r
+ else\r
+ { \r
+ QUERY_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;\r
+\r
+ QUERY_Response->InformationBufferLength = 0;\r
+ QUERY_Response->InformationBufferOffset = 0;\r
+ }\r
+ \r
+ break;\r
+ case REMOTE_NDIS_SET_MSG:\r
+ RNDISInterfaceInfo->ResponseReady = true;\r
+ \r
+ RNDIS_SET_MSG_t* SET_Message = (RNDIS_SET_MSG_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;\r
+ RNDIS_SET_CMPLT_t* SET_Response = (RNDIS_SET_CMPLT_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;\r
+ uint32_t SET_Oid = SET_Message->Oid;\r
+\r
+ SET_Response->MessageType = REMOTE_NDIS_SET_CMPLT;\r
+ SET_Response->MessageLength = sizeof(RNDIS_SET_CMPLT_t);\r
+ SET_Response->RequestId = SET_Message->RequestId;\r
+\r
+ void* SetData = &RNDISInterfaceInfo->RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +\r
+ SET_Message->InformationBufferOffset];\r
+ \r
+ if (USB_RNDIS_ProcessNDISSet(RNDISInterfaceInfo, SET_Oid, SetData, SET_Message->InformationBufferLength))\r
+ SET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
+ else\r
+ SET_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;\r
+\r
+ break;\r
+ case REMOTE_NDIS_RESET_MSG:\r
+ RNDISInterfaceInfo->ResponseReady = true;\r
+ \r
+ RNDIS_RESET_CMPLT_t* RESET_Response = (RNDIS_RESET_CMPLT_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;\r
+\r
+ RESET_Response->MessageType = REMOTE_NDIS_RESET_CMPLT;\r
+ RESET_Response->MessageLength = sizeof(RNDIS_RESET_CMPLT_t);\r
+ RESET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
+ RESET_Response->AddressingReset = 0;\r
+\r
+ break;\r
+ case REMOTE_NDIS_KEEPALIVE_MSG:\r
+ RNDISInterfaceInfo->ResponseReady = true;\r
+ \r
+ RNDIS_KEEPALIVE_MSG_t* KEEPALIVE_Message = (RNDIS_KEEPALIVE_MSG_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;\r
+ RNDIS_KEEPALIVE_CMPLT_t* KEEPALIVE_Response = (RNDIS_KEEPALIVE_CMPLT_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;\r
+\r
+ KEEPALIVE_Response->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;\r
+ KEEPALIVE_Response->MessageLength = sizeof(RNDIS_KEEPALIVE_CMPLT_t);\r
+ KEEPALIVE_Response->RequestId = KEEPALIVE_Message->RequestId;\r
+ KEEPALIVE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
+ \r
+ break;\r
+ }\r
+}\r
+\r
+static bool USB_RNDIS_ProcessNDISQuery(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo,\r
+ uint32_t OId, void* QueryData, uint16_t QuerySize,\r
+ void* ResponseData, uint16_t* ResponseSize)\r
+{\r
+ switch (OId)\r
+ {\r
+ case OID_GEN_SUPPORTED_LIST:\r
+ *ResponseSize = sizeof(AdapterSupportedOIDList);\r
+ \r
+ memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));\r
+ \r
+ return true;\r
+ case OID_GEN_PHYSICAL_MEDIUM:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ /* Indicate that the device is a true ethernet link */\r
+ *((uint32_t*)ResponseData) = 0;\r
+ \r
+ return true;\r
+ case OID_GEN_HARDWARE_STATUS:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ *((uint32_t*)ResponseData) = NdisHardwareStatusReady;\r
+ \r
+ return true;\r
+ case OID_GEN_MEDIA_SUPPORTED:\r
+ case OID_GEN_MEDIA_IN_USE:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIUM_802_3;\r
+ \r
+ return true;\r
+ case OID_GEN_VENDOR_ID:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */\r
+ *((uint32_t*)ResponseData) = 0x00FFFFFF;\r
+ \r
+ return true;\r
+ case OID_GEN_MAXIMUM_FRAME_SIZE:\r
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
+ case OID_GEN_RECEIVE_BLOCK_SIZE:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ *((uint32_t*)ResponseData) = ETHERNET_FRAME_SIZE_MAX;\r
+ \r
+ return true;\r
+ case OID_GEN_VENDOR_DESCRIPTION:\r
+ *ResponseSize = (strlen(RNDISInterfaceInfo->AdapterVendorDescription) + 1);\r
+ \r
+ memcpy(ResponseData, RNDISInterfaceInfo->AdapterVendorDescription, *ResponseSize);\r
+ \r
+ return true;\r
+ case OID_GEN_MEDIA_CONNECT_STATUS:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIA_STATE_CONNECTED;\r
+ \r
+ return true;\r
+ case OID_GEN_LINK_SPEED:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ /* Indicate 10Mb/s link speed */\r
+ *((uint32_t*)ResponseData) = 100000;\r
+\r
+ return true;\r
+ case OID_802_3_PERMANENT_ADDRESS:\r
+ case OID_802_3_CURRENT_ADDRESS:\r
+ *ResponseSize = sizeof(MAC_Address_t);\r
+ \r
+ memcpy(ResponseData, &RNDISInterfaceInfo->AdapterMACAddress, sizeof(MAC_Address_t));\r
+\r
+ return true;\r
+ case OID_802_3_MAXIMUM_LIST_SIZE:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ /* Indicate only one multicast address supported */\r
+ *((uint32_t*)ResponseData) = 1;\r
+ \r
+ return true;\r
+ case OID_GEN_CURRENT_PACKET_FILTER:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ *((uint32_t*)ResponseData) = RNDISInterfaceInfo->CurrPacketFilter;\r
+ \r
+ return true; \r
+ case OID_GEN_XMIT_OK:\r
+ case OID_GEN_RCV_OK:\r
+ case OID_GEN_XMIT_ERROR:\r
+ case OID_GEN_RCV_ERROR:\r
+ case OID_GEN_RCV_NO_BUFFER:\r
+ case OID_802_3_RCV_ERROR_ALIGNMENT:\r
+ case OID_802_3_XMIT_ONE_COLLISION:\r
+ case OID_802_3_XMIT_MORE_COLLISIONS:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ /* Unused statistic OIDs - always return 0 for each */\r
+ *((uint32_t*)ResponseData) = 0;\r
+ \r
+ return true;\r
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */\r
+ *((uint32_t*)ResponseData) = (RNDIS_MESSAGE_BUFFER_SIZE + ETHERNET_FRAME_SIZE_MAX);\r
+ \r
+ return true;\r
+ default:\r
+ return false;\r
+ }\r
+}\r
+\r
+static bool USB_RNDIS_ProcessNDISSet(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo, uint32_t OId, void* SetData, uint16_t SetSize)\r
+{\r
+ switch (OId)\r
+ {\r
+ case OID_GEN_CURRENT_PACKET_FILTER:\r
+ RNDISInterfaceInfo->CurrPacketFilter = *((uint32_t*)SetData);\r
+ RNDISInterfaceInfo->CurrRNDISState = ((RNDISInterfaceInfo->CurrPacketFilter) ?\r
+ RNDIS_Data_Initialized : RNDIS_Data_Initialized);\r
+ \r
+ return true;\r
+ case OID_802_3_MULTICAST_LIST:\r
+ /* Do nothing - throw away the value from the host as it is unused */\r
+ \r
+ return true;\r
+ default:\r
+ return false;\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+#ifndef _RNDIS_CLASS_H_\r
+#define _RNDIS_CLASS_H_\r
+\r
+ /* Includes: */\r
+ #include <string.h>\r
+ \r
+ #include "../../USB.h"\r
+ #include "RNDISConstants.h"\r
+ \r
+ /* Macros: */\r
+ /** Implemented RNDIS Version Major */\r
+ #define REMOTE_NDIS_VERSION_MAJOR 0x01\r
+\r
+ /** Implemented RNDIS Version Minor */\r
+ #define REMOTE_NDIS_VERSION_MINOR 0x00\r
+ \r
+ /** RNDIS request to issue a host-to-device NDIS command */\r
+ #define REQ_SendEncapsulatedCommand 0x00\r
+\r
+ /** RNDIS request to issue a device-to-host NDIS response */\r
+ #define REQ_GetEncapsulatedResponse 0x01\r
+ \r
+ #define RNDIS_MESSAGE_BUFFER_SIZE 128\r
+\r
+ #define ETHERNET_FRAME_SIZE_MAX 1500\r
+ \r
+ #define NOTIF_ResponseAvailable 1\r
+ \r
+ /* Enums: */\r
+ /** Enum for the possible NDIS adapter states. */\r
+ enum RNDIS_States_t\r
+ {\r
+ RNDIS_Uninitialized = 0, /**< Adapter currently uninitialized */\r
+ RNDIS_Initialized = 1, /**< Adapter currently initialized but not ready for data transfers */\r
+ RNDIS_Data_Initialized = 2, /**< Adapter currently initialized and ready for data transfers */\r
+ };\r
+\r
+ /** Enum for the NDIS hardware states */\r
+ enum NDIS_Hardware_Status_t\r
+ {\r
+ NdisHardwareStatusReady, /**< Hardware Ready to accept commands from the host */\r
+ NdisHardwareStatusInitializing, /**< Hardware busy initializing */\r
+ NdisHardwareStatusReset, /**< Hardware reset */\r
+ NdisHardwareStatusClosing, /**< Hardware currently closing */\r
+ NdisHardwareStatusNotReady /**< Hardware not ready to accept commands from the host */\r
+ };\r
+ \r
+ /* Type Defines: */\r
+ /** Type define for a physical MAC address of a device on a network */\r
+ typedef struct\r
+ {\r
+ uint8_t Octets[6]; /**< Individual bytes of a MAC address */\r
+ } MAC_Address_t;\r
+\r
+ /** Type define for a RNDIS message header, sent before RNDIS messages */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType; /**< RNDIS message type, a REMOTE_NDIS_*_MSG constant */\r
+ uint32_t MessageLength; /**< Total length of the RNDIS message, in bytes */\r
+ } RNDIS_Message_Header_t;\r
+\r
+ /** Type define for an Ethernet frame buffer. */\r
+ typedef struct\r
+ {\r
+ uint8_t FrameData[ETHERNET_FRAME_SIZE_MAX]; /**< Ethernet frame contents */\r
+ uint16_t FrameLength; /**< Length in bytes of the Ethernet frame stored in the buffer */\r
+ bool FrameInBuffer; /**< Indicates if a frame is currently stored in the buffer */\r
+ } Ethernet_Frame_Info_t;\r
+\r
+ /** Type define for a RNDIS packet message, used to encapsulate Ethernet packets sent to and from the adapter */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t DataOffset;\r
+ uint32_t DataLength;\r
+ uint32_t OOBDataOffset;\r
+ uint32_t OOBDataLength;\r
+ uint32_t NumOOBDataElements;\r
+ uint32_t PerPacketInfoOffset;\r
+ uint32_t PerPacketInfoLength;\r
+ uint32_t VcHandle;\r
+ uint32_t Reserved;\r
+ } RNDIS_PACKET_MSG_t;\r
+\r
+ typedef struct\r
+ {\r
+ uint8_t ControlInterfaceNumber; /**< Interface number of the CDC control interface within the device */\r
+\r
+ uint8_t DataINEndpointNumber; /**< Endpoint number of the CDC interface's IN data endpoint */\r
+ uint16_t DataINEndpointSize; /**< Size in bytes of the CDC interface's IN data endpoint */\r
+\r
+ uint8_t DataOUTEndpointNumber; /**< Endpoint number of the CDC interface's OUT data endpoint */\r
+ uint16_t DataOUTEndpointSize; /**< Size in bytes of the CDC interface's OUT data endpoint */\r
+\r
+ uint8_t NotificationEndpointNumber; /**< Endpoint number of the CDC interface's IN notification endpoint, if used */\r
+ uint16_t NotificationEndpointSize; /**< Size in bytes of the CDC interface's IN notification endpoint, if used */\r
+ \r
+ char* AdapterVendorDescription;\r
+ MAC_Address_t AdapterMACAddress;\r
+\r
+ uint8_t RNDISMessageBuffer[RNDIS_MESSAGE_BUFFER_SIZE];\r
+ bool ResponseReady;\r
+ uint8_t CurrRNDISState;\r
+ uint32_t CurrPacketFilter;\r
+ Ethernet_Frame_Info_t FrameIN;\r
+ Ethernet_Frame_Info_t FrameOUT;\r
+ } USB_ClassInfo_RNDIS_t;\r
+ \r
+ /** Type define for a RNDIS Initialize command message */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t RequestId;\r
+ \r
+ uint32_t MajorVersion;\r
+ uint32_t MinorVersion;\r
+ uint32_t MaxTransferSize;\r
+ } RNDIS_INITIALIZE_MSG_t;\r
+ \r
+ /** Type define for a RNDIS Initialize complete response message */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t RequestId;\r
+ uint32_t Status;\r
+ \r
+ uint32_t MajorVersion;\r
+ uint32_t MinorVersion;\r
+ uint32_t DeviceFlags;\r
+ uint32_t Medium;\r
+ uint32_t MaxPacketsPerTransfer;\r
+ uint32_t MaxTransferSize;\r
+ uint32_t PacketAlignmentFactor;\r
+ uint32_t AFListOffset;\r
+ uint32_t AFListSize;\r
+ } RNDIS_INITIALIZE_CMPLT_t;\r
+ \r
+ /** Type define for a RNDIS Keepalive command message */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t RequestId;\r
+ } RNDIS_KEEPALIVE_MSG_t;\r
+\r
+ /** Type define for a RNDIS Keepalive complete message */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t RequestId;\r
+ uint32_t Status;\r
+ } RNDIS_KEEPALIVE_CMPLT_t;\r
+\r
+ /** Type define for a RNDIS Reset complete message */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t Status;\r
+\r
+ uint32_t AddressingReset;\r
+ } RNDIS_RESET_CMPLT_t;\r
+ \r
+ /** Type define for a RNDIS Set command message */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t RequestId;\r
+ \r
+ uint32_t Oid;\r
+ uint32_t InformationBufferLength;\r
+ uint32_t InformationBufferOffset;\r
+ uint32_t DeviceVcHandle;\r
+ } RNDIS_SET_MSG_t;\r
+\r
+ /** Type define for a RNDIS Set complete response message */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t RequestId;\r
+ uint32_t Status;\r
+ } RNDIS_SET_CMPLT_t;\r
+ \r
+ /** Type define for a RNDIS Query command message */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t RequestId;\r
+ \r
+ uint32_t Oid;\r
+ uint32_t InformationBufferLength;\r
+ uint32_t InformationBufferOffset;\r
+ uint32_t DeviceVcHandle;\r
+ } RNDIS_QUERY_MSG_t;\r
+ \r
+ /** Type define for a RNDIS Query complete response message */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t RequestId;\r
+ uint32_t Status;\r
+ \r
+ uint32_t InformationBufferLength;\r
+ uint32_t InformationBufferOffset;\r
+ } RNDIS_QUERY_CMPLT_t;\r
+ \r
+ /* Function Prototypes: */\r
+ #if defined(INCLUDE_FROM_RNDIS_CLASS_C)\r
+ static void USB_RNDIS_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo);\r
+ static bool USB_RNDIS_ProcessNDISQuery(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo, \r
+ uint32_t OId, void* QueryData, uint16_t QuerySize,\r
+ void* ResponseData, uint16_t* ResponseSize);\r
+ static bool USB_RNDIS_ProcessNDISSet(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo, uint32_t OId,\r
+ void* SetData, uint16_t SetSize); \r
+ #endif\r
+\r
+ void USB_RNDIS_USBTask(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo);\r
+ bool USB_RNDIS_ConfigureEndpoints(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo);\r
+ void USB_RNDIS_ProcessControlPacket(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo);\r
+ void USB_RNDIS_USBTask(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo);\r
+ \r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * RNDIS specification related constants. For more information on these\r
+ * constants, please refer to the Microsoft RNDIS specification.\r
+ */\r
+ \r
+#ifndef _RNDIS_CONSTANTS_H_\r
+#define _RNDIS_CONSTANTS_H_\r
+\r
+ /* Macros: */\r
+ #define REMOTE_NDIS_PACKET_MSG 0x00000001UL\r
+ #define REMOTE_NDIS_INITIALIZE_MSG 0x00000002UL\r
+ #define REMOTE_NDIS_HALT_MSG 0x00000003UL\r
+ #define REMOTE_NDIS_QUERY_MSG 0x00000004UL\r
+ #define REMOTE_NDIS_SET_MSG 0x00000005UL\r
+ #define REMOTE_NDIS_RESET_MSG 0x00000006UL\r
+ #define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007UL\r
+ #define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008UL\r
+\r
+ #define REMOTE_NDIS_INITIALIZE_CMPLT 0x80000002UL\r
+ #define REMOTE_NDIS_QUERY_CMPLT 0x80000004UL\r
+ #define REMOTE_NDIS_SET_CMPLT 0x80000005UL\r
+ #define REMOTE_NDIS_RESET_CMPLT 0x80000006UL\r
+ #define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008UL\r
+ \r
+ #define REMOTE_NDIS_STATUS_SUCCESS 0x00000000UL\r
+ #define REMOTE_NDIS_STATUS_FAILURE 0xC0000001UL\r
+ #define REMOTE_NDIS_STATUS_INVALID_DATA 0xC0010015UL\r
+ #define REMOTE_NDIS_STATUS_NOT_SUPPORTED 0xC00000BBUL\r
+ #define REMOTE_NDIS_STATUS_MEDIA_CONNECT 0x4001000BUL\r
+ #define REMOTE_NDIS_STATUS_MEDIA_DISCONNECT 0x4001000CUL\r
+ \r
+ #define REMOTE_NDIS_MEDIA_STATE_CONNECTED 0x00000000UL\r
+ #define REMOTE_NDIS_MEDIA_STATE_DISCONNECTED 0x00000001UL\r
+ \r
+ #define REMOTE_NDIS_MEDIUM_802_3 0x00000000UL\r
+ \r
+ #define REMOTE_NDIS_DF_CONNECTIONLESS 0x00000001UL\r
+ #define REMOTE_NDIS_DF_CONNECTION_ORIENTED 0x00000002UL\r
+ \r
+ #define OID_GEN_SUPPORTED_LIST 0x00010101UL\r
+ #define OID_GEN_HARDWARE_STATUS 0x00010102UL\r
+ #define OID_GEN_MEDIA_SUPPORTED 0x00010103UL\r
+ #define OID_GEN_MEDIA_IN_USE 0x00010104UL\r
+ #define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106UL\r
+ #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL\r
+ #define OID_GEN_LINK_SPEED 0x00010107UL\r
+ #define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010AUL\r
+ #define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010BUL\r
+ #define OID_GEN_VENDOR_ID 0x0001010CUL\r
+ #define OID_GEN_VENDOR_DESCRIPTION 0x0001010DUL\r
+ #define OID_GEN_CURRENT_PACKET_FILTER 0x0001010EUL\r
+ #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL\r
+ #define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114UL\r
+ #define OID_GEN_PHYSICAL_MEDIUM 0x00010202UL\r
+ #define OID_GEN_XMIT_OK 0x00020101UL\r
+ #define OID_GEN_RCV_OK 0x00020102UL\r
+ #define OID_GEN_XMIT_ERROR 0x00020103UL\r
+ #define OID_GEN_RCV_ERROR 0x00020104UL\r
+ #define OID_GEN_RCV_NO_BUFFER 0x00020105UL\r
+ #define OID_802_3_PERMANENT_ADDRESS 0x01010101UL\r
+ #define OID_802_3_CURRENT_ADDRESS 0x01010102UL\r
+ #define OID_802_3_MULTICAST_LIST 0x01010103UL\r
+ #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104UL\r
+ #define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101UL\r
+ #define OID_802_3_XMIT_ONE_COLLISION 0x01020102UL\r
+ #define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103UL\r
+\r
+#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-#include "HIDParser.h"\r
-\r
-uint8_t USB_ProcessHIDReport(const uint8_t* ReportData, uint16_t ReportSize, HID_ReportInfo_t* const ParserData)\r
-{\r
- HID_StateTable_t StateTable[HID_STATETABLE_STACK_DEPTH];\r
- HID_StateTable_t* CurrStateTable = &StateTable[0];\r
- uint16_t UsageStack[HID_USAGE_STACK_DEPTH];\r
- uint8_t UsageStackSize = 0;\r
- uint16_t BitOffsetIn = 0;\r
- uint16_t BitOffsetOut = 0;\r
-#if defined(HID_ENABLE_FEATURE_PROCESSING)\r
- uint16_t BitOffsetFeature = 0;\r
-#endif\r
- HID_CollectionPath_t* CurrCollectionPath = NULL;\r
-\r
- memset((void*)ParserData, 0x00, sizeof(HID_ReportInfo_t));\r
- memset((void*)StateTable, 0x00, sizeof(StateTable));\r
-\r
- while (ReportSize)\r
- {\r
- uint32_t ReportItemData = 0;\r
- \r
- switch (*ReportData & DATA_SIZE_MASK)\r
- {\r
- case DATA_SIZE_4:\r
- ReportItemData = *((uint32_t*)(ReportData + 1));\r
- break;\r
- case DATA_SIZE_2:\r
- ReportItemData = *((uint16_t*)(ReportData + 1));\r
- break;\r
- case DATA_SIZE_1:\r
- ReportItemData = *((uint8_t*)(ReportData + 1));\r
- break;\r
- }\r
-\r
- switch (*ReportData & (TYPE_MASK | TAG_MASK))\r
- {\r
- case (TYPE_GLOBAL | TAG_GLOBAL_PUSH):\r
- if (CurrStateTable == &StateTable[HID_STATETABLE_STACK_DEPTH])\r
- return HID_PARSE_HIDStackOverflow;\r
- \r
- memcpy((CurrStateTable - 1),\r
- CurrStateTable,\r
- sizeof(HID_ReportItem_t));\r
-\r
- CurrStateTable++;\r
- break;\r
- case (TYPE_GLOBAL | TAG_GLOBAL_POP):\r
- if (CurrStateTable == &StateTable[0])\r
- return HID_PARSE_HIDStackUnderflow;\r
- \r
- CurrStateTable--;\r
- break;\r
- case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE):\r
- CurrStateTable->Attributes.Usage.Page = ReportItemData;\r
- break;\r
- case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN):\r
- CurrStateTable->Attributes.Logical.Minimum = ReportItemData;\r
- break;\r
- case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX):\r
- CurrStateTable->Attributes.Logical.Maximum = ReportItemData;\r
- break;\r
- case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN):\r
- CurrStateTable->Attributes.Physical.Minimum = ReportItemData;\r
- break;\r
- case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX):\r
- CurrStateTable->Attributes.Physical.Maximum = ReportItemData;\r
- break;\r
- case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP):\r
- CurrStateTable->Attributes.Unit.Exponent = ReportItemData;\r
- break;\r
- case (TYPE_GLOBAL | TAG_GLOBAL_UNIT):\r
- CurrStateTable->Attributes.Unit.Type = ReportItemData;\r
- break;\r
- case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE):\r
- CurrStateTable->Attributes.BitSize = ReportItemData;\r
- break;\r
- case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT):\r
- CurrStateTable->ReportCount = ReportItemData;\r
- break;\r
- case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID):\r
- CurrStateTable->ReportID = ReportItemData;\r
- break;\r
- case (TYPE_LOCAL | TAG_LOCAL_USAGE):\r
- if (UsageStackSize == HID_USAGE_STACK_DEPTH)\r
- return HID_PARSE_UsageStackOverflow;\r
- \r
- UsageStack[UsageStackSize++] = ReportItemData;\r
- break;\r
- case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN):\r
- CurrStateTable->Attributes.Usage.MinMax.Minimum = ReportItemData;\r
- break;\r
- case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX):\r
- CurrStateTable->Attributes.Usage.MinMax.Maximum = ReportItemData;\r
- break;\r
- case (TYPE_MAIN | TAG_MAIN_COLLECTION):\r
- if (CurrCollectionPath == NULL)\r
- {\r
- CurrCollectionPath = &ParserData->CollectionPaths[0];\r
- }\r
- else\r
- {\r
- HID_CollectionPath_t* ParentCollectionPath = CurrCollectionPath;\r
- \r
- CurrCollectionPath = &ParserData->CollectionPaths[1];\r
-\r
- while (CurrCollectionPath->Parent != NULL);\r
- {\r
- if (CurrCollectionPath == &ParserData->CollectionPaths[HID_MAX_COLLECTIONS])\r
- return HID_PARSE_InsufficientCollectionPaths;\r
- \r
- CurrCollectionPath++;\r
- }\r
-\r
- CurrCollectionPath->Parent = ParentCollectionPath;\r
- }\r
- \r
- CurrCollectionPath->Type = ReportItemData;\r
- CurrCollectionPath->Usage.Page = CurrStateTable->Attributes.Usage.Page;\r
- \r
- if (UsageStackSize)\r
- {\r
- CurrCollectionPath->Usage.Usage = UsageStack[0];\r
-\r
- for (uint8_t i = 0; i < UsageStackSize; i++)\r
- UsageStack[i] = UsageStack[i + 1];\r
- \r
- UsageStackSize--;\r
- }\r
- else\r
- {\r
- CurrCollectionPath->Usage.Usage = 0;\r
- }\r
- \r
- break;\r
- case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION):\r
- if (CurrCollectionPath == NULL)\r
- return HID_PARSE_UnexpectedEndCollection;\r
- \r
- CurrCollectionPath = CurrCollectionPath->Parent;\r
-\r
- break;\r
- case (TYPE_MAIN | TAG_MAIN_INPUT):\r
- case (TYPE_MAIN | TAG_MAIN_OUTPUT):\r
-#if defined(HID_ENABLE_FEATURE_PROCESSING)\r
- case (TYPE_MAIN | TAG_MAIN_FEATURE):\r
-#endif\r
- for (uint8_t ReportItemNum = 0; ReportItemNum < CurrStateTable->ReportCount; ReportItemNum++)\r
- {\r
- HID_ReportItem_t* CurrReportItem = &ParserData->ReportItems[ParserData->TotalReportItems];\r
- \r
- if (ParserData->TotalReportItems == HID_MAX_REPORTITEMS)\r
- return HID_PARSE_InsufficientReportItems;\r
- \r
- memcpy(&CurrReportItem->Attributes,\r
- &CurrStateTable->Attributes,\r
- sizeof(HID_ReportItem_Attributes_t));\r
-\r
- CurrReportItem->ItemFlags = ReportItemData;\r
- CurrReportItem->CollectionPath = CurrCollectionPath;\r
- CurrReportItem->ReportID = CurrStateTable->ReportID;\r
-\r
- if (UsageStackSize)\r
- {\r
- CurrReportItem->Attributes.Usage.Usage = UsageStack[0];\r
-\r
- for (uint8_t i = 0; i < UsageStackSize; i++)\r
- UsageStack[i] = UsageStack[i + 1];\r
- \r
- UsageStackSize--;\r
- }\r
- else\r
- {\r
- CurrReportItem->Attributes.Usage.Usage = 0;\r
- }\r
- \r
- switch (*ReportData & TAG_MASK)\r
- {\r
- case TAG_MAIN_INPUT:\r
- CurrReportItem->ItemType = REPORT_ITEM_TYPE_In;\r
- CurrReportItem->BitOffset = BitOffsetIn;\r
- \r
- BitOffsetIn += CurrStateTable->Attributes.BitSize;\r
- \r
- break;\r
- case TAG_MAIN_OUTPUT:\r
- CurrReportItem->ItemType = REPORT_ITEM_TYPE_Out;\r
- CurrReportItem->BitOffset = BitOffsetOut;\r
- \r
- BitOffsetOut += CurrStateTable->Attributes.BitSize;\r
- \r
- break;\r
-#if defined(HID_ENABLE_FEATURE_PROCESSING)\r
- case TAG_MAIN_FEATURE:\r
- CurrReportItem->ItemType = REPORT_ITEM_TYPE_Feature; \r
- CurrReportItem->BitOffset = BitOffsetFeature;\r
- \r
- BitOffsetFeature += CurrStateTable->Attributes.BitSize; \r
-\r
- break;\r
-#endif\r
- }\r
- \r
-#if !defined(HID_INCLUDE_CONSTANT_DATA_ITEMS)\r
- if (!(ReportItemData & IOF_CONSTANT))\r
- ParserData->TotalReportItems++;\r
-#else\r
- ParserData->TotalReportItems++;\r
-#endif\r
- }\r
- \r
- UsageStackSize = 0;\r
- \r
- break;\r
- }\r
- \r
- if ((*ReportData & TYPE_MASK) == TYPE_MAIN)\r
- {\r
- CurrStateTable->Attributes.Usage.MinMax.Minimum = 0;\r
- CurrStateTable->Attributes.Usage.MinMax.Maximum = 0;\r
- UsageStackSize = 0;\r
- }\r
- \r
- switch (*ReportData & DATA_SIZE_MASK)\r
- {\r
- case DATA_SIZE_4:\r
- ReportSize -= 5;\r
- ReportData += 5;\r
- break;\r
- case DATA_SIZE_2:\r
- ReportSize -= 3;\r
- ReportData += 3;\r
- break;\r
- case DATA_SIZE_1:\r
- ReportSize -= 2;\r
- ReportData += 2;\r
- break;\r
- case DATA_SIZE_0:\r
- ReportSize -= 1;\r
- ReportData += 1;\r
- break;\r
- }\r
- }\r
- \r
- return HID_PARSE_Successful;\r
-}\r
-\r
-bool USB_GetHIDReportItemInfo(const uint8_t* ReportData, HID_ReportItem_t* const ReportItem)\r
-{\r
- uint16_t DataBitsRem = ReportItem->Attributes.BitSize;\r
- uint16_t CurrentBit = ReportItem->BitOffset;\r
- uint32_t BitMask = (1 << 0);\r
-\r
- ReportItem->Value = 0;\r
- \r
- if (ReportItem->ReportID)\r
- {\r
- if (ReportItem->ReportID != ReportData[0])\r
- return false;\r
-\r
- ReportData++;\r
- }\r
-\r
- while (DataBitsRem--)\r
- {\r
- if (ReportData[CurrentBit / 8] & (1 << (CurrentBit % 8)))\r
- ReportItem->Value |= BitMask;\r
- \r
- CurrentBit++;\r
- BitMask <<= 1;\r
- }\r
- \r
- return true;\r
-}\r
-\r
-void USB_SetHIDReportItemInfo(uint8_t* ReportData, const HID_ReportItem_t* ReportItem)\r
-{\r
- uint16_t DataBitsRem = ReportItem->Attributes.BitSize;\r
- uint16_t CurrentBit = ReportItem->BitOffset;\r
- uint32_t BitMask = (1 << 0);\r
-\r
- if (ReportItem->ReportID)\r
- {\r
- ReportData[0] = ReportItem->ReportID;\r
- ReportData++;\r
- }\r
-\r
- while (DataBitsRem--)\r
- {\r
- if (ReportItem->Value & (1 << (CurrentBit % 8)))\r
- ReportData[CurrentBit / 8] |= BitMask;\r
-\r
- CurrentBit++;\r
- BitMask <<= 1;\r
- }\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * USB Human Interface Device (HID) Class report descriptor processing routines. This file allows for the easy\r
- * parsing of the complex HID report descriptor, which describes the data that the device transmits to the host.\r
- *\r
- */\r
- \r
-/** \ingroup Group_USB\r
- * @defgroup Group_HIDParser HID Report Parser\r
- *\r
- * Functions, macros, variables, enums and types related to the parsing of HID class device report descriptors.\r
- *\r
- * The processed HID report is presented back to the user application as a flat structure containing each report\r
- * item's IN, OUT and FEATURE (if desired) items along with each item's attributes.\r
- *\r
- * This library portion also allows for easy setting and retrieval of data from a HID report, including devices\r
- * with multiple reports on the one HID interface.\r
- *\r
- * By default, FEATURE reports and IN/OUT reports with constant data are ignored in the HID report when processed\r
- * to save on memory. This can be overridden by defining the HID_ENABLE_FEATURE_PROCESSING or\r
- * HID_INCLUDE_CONSTANT_DATA_ITEMS tokens in the user project makefile, passing them to the compiler via the -D\r
- * switch.\r
- *\r
- * @{\r
- */\r
-\r
-#ifndef __HIDPARSER_H__\r
-#define __HIDPARSER_H__\r
-\r
- /* Includes: */\r
- #include <string.h>\r
- #include <stdbool.h>\r
-\r
- #include "HIDReportData.h"\r
-\r
- #include "../../../Common/Common.h"\r
-\r
- /* Enable C linkage for C++ Compilers: */\r
- #if defined(__cplusplus)\r
- extern "C" {\r
- #endif\r
-\r
- /* Preprocessor checks and defines: */\r
- #if !defined(HID_STATETABLE_STACK_DEPTH) || defined(__DOXYGEN__)\r
- /** Constant indicating the maximum stack depth of the state table. A larger state table\r
- * allows for more PUSH/POP report items to be nested, but consumes more memory. By default\r
- * this is set to 3 levels (allowing for two PUSHes to be nested) but this can be overridden by\r
- * defining HID_STATETABLE_STACK_DEPTH to another value in the user project makefile, passing the\r
- * define to the compiler using the -D compiler switch.\r
- */\r
- #define HID_STATETABLE_STACK_DEPTH 3\r
- #endif\r
- \r
- #if !defined(HID_USAGE_STACK_DEPTH) || defined(__DOXYGEN__)\r
- /** Constant indicating the maximum stack depth of the usage table. A larger usage table\r
- * allows for more USAGE items to be indicated sequentially for REPORT COUNT entries of more than\r
- * one, but requires more stack space. By default this is set to 8 levels (allowing for a report\r
- * item with a count of 8) but this can be overridden by defining HID_USAGE_STACK_DEPTH to another\r
- * value in the user project makefile, passing the define to the compiler using the -D compiler\r
- * switch.\r
- */\r
- #define HID_USAGE_STACK_DEPTH 8\r
- #endif\r
-\r
- #if !defined(HID_MAX_COLLECTIONS) || defined(__DOXYGEN__)\r
- /** Constant indicating the maximum number of COLLECTION items (nested or unnested) that can be\r
- * processed in the report item descriptor. A large value allows for more COLLECTION items to be\r
- * processed, but consumes more memory. By default this is set to 5 collections, but this can be\r
- * overridden by defining HID_MAX_COLLECTIONS to another value in the user project makefile, passing\r
- * the define to the compiler using the -D compiler switch.\r
- */\r
- #define HID_MAX_COLLECTIONS 5\r
- #endif\r
- \r
- #if !defined(HID_MAX_REPORTITEMS) || defined(__DOXYGEN__)\r
- /** Constant indicating the maximum number of report items (IN, OUT or FEATURE if enabled) that can be\r
- * processed in the report item descriptor. A large value allows for more report items to be\r
- * processed, but consumes more memory. By default this is set to 30 items, but this can be\r
- * overridden by defining HID_MAX_REPORTITEMS to another value in the user project makefile, passing\r
- * the define to the compiler using the -D compiler switch.\r
- */\r
- #define HID_MAX_REPORTITEMS 30\r
- #endif\r
-\r
- /* Public Interface - May be used in end-application: */\r
- /* Enums: */\r
- /** Enum for indicating what type of report item an entry in a \ref HID_ReportInfo_t ReportItem array is */\r
- enum HID_ReportItemTypes_t\r
- {\r
- REPORT_ITEM_TYPE_In = 0, /**< Indicates that the item is an IN report type. */\r
- REPORT_ITEM_TYPE_Out = 1, /**< Indicates that the item is an OUT report type. */\r
- REPORT_ITEM_TYPE_Feature = 2, /**< Indicates that the item is a FEATURE report type. */\r
- };\r
- \r
- /** Enum for the possible error codes in the return value of the \ref USB_ProcessHIDReport() function */\r
- enum HID_Parse_ErrorCodes_t\r
- {\r
- HID_PARSE_Successful = 0, /**< Successful parse of the HID report descriptor, no error. */\r
- HID_PARSE_HIDStackOverflow = 1, /**< More than \ref HID_STATETABLE_STACK_DEPTH nested PUSHes in the report. */ \r
- HID_PARSE_HIDStackUnderflow = 2, /**< A POP was found when the state table stack was empty. */\r
- HID_PARSE_InsufficientReportItems = 3, /**< More than \ref HID_MAX_REPORTITEMS report items in the report. */\r
- HID_PARSE_UnexpectedEndCollection = 4, /**< END COLLECTION found without matching COLLECTION item. */\r
- HID_PARSE_InsufficientCollectionPaths = 5, /**< More than \ref HID_MAX_COLLECTIONS collections in the report. */\r
- HID_PARSE_UsageStackOverflow = 6, /**< More than \ref HID_USAGE_STACK_DEPTH usages listed in a row. */\r
- };\r
- \r
- /* Type Defines: */ \r
- /** Type define for an attribute with both minimum and maximum values (e.g. Logical Min/Max). */\r
- typedef struct\r
- {\r
- uint32_t Minimum; /**< Minimum value for the attribute. */\r
- uint32_t Maximum; /**< Maximum value for the attribute. */\r
- } HID_MinMax_t;\r
-\r
- /** Type define for the Unit attributes of a report item. */\r
- typedef struct\r
- {\r
- uint32_t Type; /**< Unit type (refer to HID specifications for details). */\r
- uint8_t Exponent; /**< Unit exponent (refer to HID specifications for details). */\r
- } HID_Unit_t;\r
- \r
- /** Type define for the Usage attributes of a report item. */\r
- typedef struct\r
- {\r
- uint16_t Page; /**< Usage page of the report item. */\r
- uint16_t Usage; /**< Usage of the report item. */\r
- HID_MinMax_t MinMax; /**< Usage minimum and maximum of the report item. */\r
- } HID_Usage_t;\r
-\r
- /** Type define for a COLLECTION object. Contains the collection attributes and a reference to the\r
- * parent collection if any.\r
- */\r
- typedef struct CollectionPath\r
- {\r
- uint8_t Type; /**< Collection type (e.g. "Generic Desktop"). */\r
- HID_Usage_t Usage; /**< Collection usage. */\r
- struct CollectionPath* Parent; /**< Reference to parent collection, or NULL if root collection. */\r
- } HID_CollectionPath_t;\r
-\r
- /** Type define for all the data attributes of a report item, except flags. */\r
- typedef struct\r
- {\r
- uint8_t BitSize; /**< Size in bits of the report item's data. */\r
- \r
- HID_Usage_t Usage; /**< Usage of the report item. */\r
- HID_Unit_t Unit; /**< Unit type and exponent of the report item. */\r
- HID_MinMax_t Logical; /**< Logical minimum and maximum of the report item. */\r
- HID_MinMax_t Physical; /**< Physical minimum and maximum of the report item. */\r
- } HID_ReportItem_Attributes_t;\r
- \r
- /** Type define for a report item (IN, OUT or FEATURE) attributes and other details. */\r
- typedef struct\r
- {\r
- uint16_t BitOffset; /**< Bit offset in the IN, OUT or FEATURE report of the item. */\r
- uint8_t ItemType; /**< Report item type, a value in HID_Types_t. */\r
- uint16_t ItemFlags; /**< Item data flags, such as constant/variable, etc. */\r
- uint8_t ReportID; /**< Report ID this item belongs to, or 0x00 if device has only one report */\r
- HID_CollectionPath_t* CollectionPath; /**< Collection path of the item. */\r
-\r
- HID_ReportItem_Attributes_t Attributes; /**< Report item attributes. */\r
- \r
- uint32_t Value; /**< Current value of the report item. */\r
- } HID_ReportItem_t;\r
-\r
- /** Type define for a complete processed HID report, including all report item data and collections. */\r
- typedef struct\r
- {\r
- uint8_t TotalReportItems; /**< Total number of report items stored in the\r
- * ReportItems array. */\r
-\r
- HID_ReportItem_t ReportItems[HID_MAX_REPORTITEMS]; /**< Report items array, including\r
- * all IN, OUT and FEATURE items. */\r
-\r
- HID_CollectionPath_t CollectionPaths[HID_MAX_COLLECTIONS]; /**< All collection items, referenced\r
- * by the report items. */\r
- } HID_ReportInfo_t;\r
- \r
- /* Function Prototypes: */\r
- /** Function to process a given HID report returned from an attached device, and store it into a given\r
- * \ref HID_ReportInfo_t structure.\r
- *\r
- * \param ReportData Buffer containing the device's HID report table\r
- * \param ReportSize Size in bytes of the HID report table\r
- * \param ParserData Pointer to a \ref HID_ReportInfo_t instance for the parser output\r
- *\r
- * \return A value in the \ref HID_Parse_ErrorCodes_t enum\r
- */\r
- uint8_t USB_ProcessHIDReport(const uint8_t* ReportData, uint16_t ReportSize, HID_ReportInfo_t* const ParserData)\r
- ATTR_NON_NULL_PTR_ARG(1, 3);\r
-\r
- /** Extracts the given report item's value out of the given HID report and places it into the Value\r
- * member of the report item's \ref HID_ReportItem_t structure.\r
- *\r
- * \param ReportData Buffer containing an IN or FEATURE report from an attached device\r
- * \param ReportItem Pointer to the report item of interest in a \ref HID_ReportInfo_t ReportItem array\r
- *\r
- * \returns Boolean true if the item to retrieve was located in the given report, false otherwise\r
- */\r
- bool USB_GetHIDReportItemInfo(const uint8_t* ReportData, HID_ReportItem_t* const ReportItem)\r
- ATTR_NON_NULL_PTR_ARG(1, 2);\r
-\r
- /** Retrieves the given report item's value out of the Value member of the report item's\r
- * \ref HID_ReportItem_t structure and places it into the correct position in the HID report\r
- * buffer. The report buffer is assumed to have the appropriate bits cleared before calling\r
- * this function (i.e., the buffer should be explicitly cleared before report values are added).\r
- *\r
- * If the device has multiple HID reports, the report ID is set to the report ID of the given item.\r
- *\r
- * \param ReportData Buffer holding the current OUT report data\r
- * \param ReportItem Pointer to the report item of interest in a \ref HID_ReportInfo_t ReportItem array\r
- */\r
- void USB_SetHIDReportItemInfo(uint8_t* ReportData, const HID_ReportItem_t* ReportItem)\r
- ATTR_NON_NULL_PTR_ARG(1, 2);\r
-\r
- /* Private Interface - For use in library only: */\r
- #if !defined(__DOXYGEN__)\r
- /* Type Defines: */\r
- typedef struct\r
- {\r
- HID_ReportItem_Attributes_t Attributes;\r
- uint8_t ReportCount;\r
- uint8_t ReportID;\r
- } HID_StateTable_t;\r
- #endif\r
- \r
- /* Disable C linkage for C++ Compilers: */\r
- #if defined(__cplusplus)\r
- }\r
- #endif\r
-\r
-#endif\r
-\r
-/** @} */\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Constants for HID report item attributes. Refer to the HID specification for details on each\r
- * flag's meaning when applied to an IN, OUT or FEATURE item.\r
- */\r
-\r
-/** \ingroup Group_HIDParser\r
- * @defgroup Group_HIDIOFConst Input/Output/Feature Masks\r
- *\r
- * Masks indicating the type of Input, Output of Feature HID report item.\r
- *\r
- * @{\r
- */\r
- \r
-#ifndef __HIDREPORTDATA_H__\r
-#define __HIDREPORTDATA_H__\r
-\r
- /* Public Interface - May be used in end-application: */\r
- /* Macros: */\r
- /** HID_ReportItem_t.ItemFlags flag for constant data. */\r
- #define IOF_CONSTANT (1 << 0)\r
-\r
- /** HID_ReportItem_t.ItemFlags flag for data. */\r
- #define IOF_DATA (0 << 0)\r
-\r
- /** HID_ReportItem_t.ItemFlags flag for variable data. */\r
- #define IOF_VARIABLE (1 << 1)\r
-\r
- /** HID_ReportItem_t.ItemFlags flag for array data. */\r
- #define IOF_ARRAY (0 << 1)\r
-\r
- /** HID_ReportItem_t.ItemFlags flag for relative data. */\r
- #define IOF_RELATIVE (1 << 2)\r
-\r
- /** HID_ReportItem_t.ItemFlags flag for absolute data. */\r
- #define IOF_ABSOLUTE (0 << 2)\r
-\r
- /** HID_ReportItem_t.ItemFlags flag for wrapped value data. */\r
- #define IOF_WRAP (1 << 3)\r
-\r
- /** HID_ReportItem_t.ItemFlags flag for non-wrapped value data. */\r
- #define IOF_NOWRAP (0 << 3)\r
-\r
- /** HID_ReportItem_t.ItemFlags flag for non linear data. */\r
- #define IOF_NONLINEAR (1 << 4)\r
-\r
- /** HID_ReportItem_t.ItemFlags flag for linear data. */\r
- #define IOF_LINEAR (0 << 4)\r
-\r
- /** HID_ReportItem_t.ItemFlags flag for no preferred state. */\r
- #define IOF_NOPREFERRED (1 << 5)\r
-\r
- /** HID_ReportItem_t.ItemFlags flag for preferred state items. */\r
- #define IOF_PREFERREDSTATE (0 << 5)\r
-\r
- /** HID_ReportItem_t.ItemFlags flag for null state items. */\r
- #define IOF_NULLSTATE (1 << 6)\r
-\r
- /** HID_ReportItem_t.ItemFlags flag for no null position data. */\r
- #define IOF_NONULLPOSITION (0 << 6)\r
-\r
- /** HID_ReportItem_t.ItemFlags flag for buffered bytes. */\r
- #define IOF_BUFFEREDBYTES (1 << 8)\r
-\r
- /** HID_ReportItem_t.ItemFlags flag for bit field data. */\r
- #define IOF_BITFIELD (0 << 8)\r
-\r
- /* Private Interface - For use in library only: */\r
- #if !defined(__DOXYGEN__)\r
- /* Macros: */\r
- #define DATA_SIZE_MASK 0x03\r
- #define TYPE_MASK 0x0C\r
- #define TAG_MASK 0xF0\r
-\r
- #define DATA_SIZE_0 0x00\r
- #define DATA_SIZE_1 0x01\r
- #define DATA_SIZE_2 0x02\r
- #define DATA_SIZE_4 0x03\r
- \r
- #define TYPE_MAIN 0x00\r
- #define TYPE_GLOBAL 0x04\r
- #define TYPE_LOCAL 0x08\r
- \r
- #define TAG_MAIN_INPUT 0x80\r
- #define TAG_MAIN_OUTPUT 0x90\r
- #define TAG_MAIN_COLLECTION 0xA0\r
- #define TAG_MAIN_FEATURE 0xB0\r
- #define TAG_MAIN_ENDCOLLECTION 0xC0\r
-\r
- #define TAG_GLOBAL_USAGEPAGE 0x00\r
- #define TAG_GLOBAL_LOGICALMIN 0x10\r
- #define TAG_GLOBAL_LOGICALMAX 0x20\r
- #define TAG_GLOBAL_PHYSMIN 0x30\r
- #define TAG_GLOBAL_PHYSMAX 0x40\r
- #define TAG_GLOBAL_UNITEXP 0x50\r
- #define TAG_GLOBAL_UNIT 0x60\r
- #define TAG_GLOBAL_REPORTSIZE 0x70\r
- #define TAG_GLOBAL_REPORTID 0x80\r
- #define TAG_GLOBAL_REPORTCOUNT 0x90\r
- #define TAG_GLOBAL_PUSH 0xA0\r
- #define TAG_GLOBAL_POP 0xB0\r
- \r
- #define TAG_LOCAL_USAGE 0x00\r
- #define TAG_LOCAL_USAGEMIN 0x10\r
- #define TAG_LOCAL_USAGEMAX 0x20\r
- #endif\r
-\r
-/** @} */\r
- \r
-#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+#include "HIDParser.h"\r
+\r
+uint8_t USB_ProcessHIDReport(const uint8_t* ReportData, uint16_t ReportSize, HID_ReportInfo_t* const ParserData)\r
+{\r
+ HID_StateTable_t StateTable[HID_STATETABLE_STACK_DEPTH];\r
+ HID_StateTable_t* CurrStateTable = &StateTable[0];\r
+ uint16_t UsageStack[HID_USAGE_STACK_DEPTH];\r
+ uint8_t UsageStackSize = 0;\r
+ uint16_t BitOffsetIn = 0;\r
+ uint16_t BitOffsetOut = 0;\r
+#if defined(HID_ENABLE_FEATURE_PROCESSING)\r
+ uint16_t BitOffsetFeature = 0;\r
+#endif\r
+ HID_CollectionPath_t* CurrCollectionPath = NULL;\r
+\r
+ memset((void*)ParserData, 0x00, sizeof(HID_ReportInfo_t));\r
+ memset((void*)StateTable, 0x00, sizeof(StateTable));\r
+\r
+ while (ReportSize)\r
+ {\r
+ uint32_t ReportItemData = 0;\r
+ \r
+ switch (*ReportData & DATA_SIZE_MASK)\r
+ {\r
+ case DATA_SIZE_4:\r
+ ReportItemData = *((uint32_t*)(ReportData + 1));\r
+ break;\r
+ case DATA_SIZE_2:\r
+ ReportItemData = *((uint16_t*)(ReportData + 1));\r
+ break;\r
+ case DATA_SIZE_1:\r
+ ReportItemData = *((uint8_t*)(ReportData + 1));\r
+ break;\r
+ }\r
+\r
+ switch (*ReportData & (TYPE_MASK | TAG_MASK))\r
+ {\r
+ case (TYPE_GLOBAL | TAG_GLOBAL_PUSH):\r
+ if (CurrStateTable == &StateTable[HID_STATETABLE_STACK_DEPTH])\r
+ return HID_PARSE_HIDStackOverflow;\r
+ \r
+ memcpy((CurrStateTable - 1),\r
+ CurrStateTable,\r
+ sizeof(HID_ReportItem_t));\r
+\r
+ CurrStateTable++;\r
+ break;\r
+ case (TYPE_GLOBAL | TAG_GLOBAL_POP):\r
+ if (CurrStateTable == &StateTable[0])\r
+ return HID_PARSE_HIDStackUnderflow;\r
+ \r
+ CurrStateTable--;\r
+ break;\r
+ case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE):\r
+ CurrStateTable->Attributes.Usage.Page = ReportItemData;\r
+ break;\r
+ case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN):\r
+ CurrStateTable->Attributes.Logical.Minimum = ReportItemData;\r
+ break;\r
+ case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX):\r
+ CurrStateTable->Attributes.Logical.Maximum = ReportItemData;\r
+ break;\r
+ case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN):\r
+ CurrStateTable->Attributes.Physical.Minimum = ReportItemData;\r
+ break;\r
+ case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX):\r
+ CurrStateTable->Attributes.Physical.Maximum = ReportItemData;\r
+ break;\r
+ case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP):\r
+ CurrStateTable->Attributes.Unit.Exponent = ReportItemData;\r
+ break;\r
+ case (TYPE_GLOBAL | TAG_GLOBAL_UNIT):\r
+ CurrStateTable->Attributes.Unit.Type = ReportItemData;\r
+ break;\r
+ case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE):\r
+ CurrStateTable->Attributes.BitSize = ReportItemData;\r
+ break;\r
+ case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT):\r
+ CurrStateTable->ReportCount = ReportItemData;\r
+ break;\r
+ case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID):\r
+ CurrStateTable->ReportID = ReportItemData;\r
+ break;\r
+ case (TYPE_LOCAL | TAG_LOCAL_USAGE):\r
+ if (UsageStackSize == HID_USAGE_STACK_DEPTH)\r
+ return HID_PARSE_UsageStackOverflow;\r
+ \r
+ UsageStack[UsageStackSize++] = ReportItemData;\r
+ break;\r
+ case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN):\r
+ CurrStateTable->Attributes.Usage.MinMax.Minimum = ReportItemData;\r
+ break;\r
+ case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX):\r
+ CurrStateTable->Attributes.Usage.MinMax.Maximum = ReportItemData;\r
+ break;\r
+ case (TYPE_MAIN | TAG_MAIN_COLLECTION):\r
+ if (CurrCollectionPath == NULL)\r
+ {\r
+ CurrCollectionPath = &ParserData->CollectionPaths[0];\r
+ }\r
+ else\r
+ {\r
+ HID_CollectionPath_t* ParentCollectionPath = CurrCollectionPath;\r
+ \r
+ CurrCollectionPath = &ParserData->CollectionPaths[1];\r
+\r
+ while (CurrCollectionPath->Parent != NULL);\r
+ {\r
+ if (CurrCollectionPath == &ParserData->CollectionPaths[HID_MAX_COLLECTIONS])\r
+ return HID_PARSE_InsufficientCollectionPaths;\r
+ \r
+ CurrCollectionPath++;\r
+ }\r
+\r
+ CurrCollectionPath->Parent = ParentCollectionPath;\r
+ }\r
+ \r
+ CurrCollectionPath->Type = ReportItemData;\r
+ CurrCollectionPath->Usage.Page = CurrStateTable->Attributes.Usage.Page;\r
+ \r
+ if (UsageStackSize)\r
+ {\r
+ CurrCollectionPath->Usage.Usage = UsageStack[0];\r
+\r
+ for (uint8_t i = 0; i < UsageStackSize; i++)\r
+ UsageStack[i] = UsageStack[i + 1];\r
+ \r
+ UsageStackSize--;\r
+ }\r
+ else\r
+ {\r
+ CurrCollectionPath->Usage.Usage = 0;\r
+ }\r
+ \r
+ break;\r
+ case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION):\r
+ if (CurrCollectionPath == NULL)\r
+ return HID_PARSE_UnexpectedEndCollection;\r
+ \r
+ CurrCollectionPath = CurrCollectionPath->Parent;\r
+\r
+ break;\r
+ case (TYPE_MAIN | TAG_MAIN_INPUT):\r
+ case (TYPE_MAIN | TAG_MAIN_OUTPUT):\r
+#if defined(HID_ENABLE_FEATURE_PROCESSING)\r
+ case (TYPE_MAIN | TAG_MAIN_FEATURE):\r
+#endif\r
+ for (uint8_t ReportItemNum = 0; ReportItemNum < CurrStateTable->ReportCount; ReportItemNum++)\r
+ {\r
+ HID_ReportItem_t* CurrReportItem = &ParserData->ReportItems[ParserData->TotalReportItems];\r
+ \r
+ if (ParserData->TotalReportItems == HID_MAX_REPORTITEMS)\r
+ return HID_PARSE_InsufficientReportItems;\r
+ \r
+ memcpy(&CurrReportItem->Attributes,\r
+ &CurrStateTable->Attributes,\r
+ sizeof(HID_ReportItem_Attributes_t));\r
+\r
+ CurrReportItem->ItemFlags = ReportItemData;\r
+ CurrReportItem->CollectionPath = CurrCollectionPath;\r
+ CurrReportItem->ReportID = CurrStateTable->ReportID;\r
+\r
+ if (UsageStackSize)\r
+ {\r
+ CurrReportItem->Attributes.Usage.Usage = UsageStack[0];\r
+\r
+ for (uint8_t i = 0; i < UsageStackSize; i++)\r
+ UsageStack[i] = UsageStack[i + 1];\r
+ \r
+ UsageStackSize--;\r
+ }\r
+ else\r
+ {\r
+ CurrReportItem->Attributes.Usage.Usage = 0;\r
+ }\r
+ \r
+ switch (*ReportData & TAG_MASK)\r
+ {\r
+ case TAG_MAIN_INPUT:\r
+ CurrReportItem->ItemType = REPORT_ITEM_TYPE_In;\r
+ CurrReportItem->BitOffset = BitOffsetIn;\r
+ \r
+ BitOffsetIn += CurrStateTable->Attributes.BitSize;\r
+ \r
+ break;\r
+ case TAG_MAIN_OUTPUT:\r
+ CurrReportItem->ItemType = REPORT_ITEM_TYPE_Out;\r
+ CurrReportItem->BitOffset = BitOffsetOut;\r
+ \r
+ BitOffsetOut += CurrStateTable->Attributes.BitSize;\r
+ \r
+ break;\r
+#if defined(HID_ENABLE_FEATURE_PROCESSING)\r
+ case TAG_MAIN_FEATURE:\r
+ CurrReportItem->ItemType = REPORT_ITEM_TYPE_Feature; \r
+ CurrReportItem->BitOffset = BitOffsetFeature;\r
+ \r
+ BitOffsetFeature += CurrStateTable->Attributes.BitSize; \r
+\r
+ break;\r
+#endif\r
+ }\r
+ \r
+#if !defined(HID_INCLUDE_CONSTANT_DATA_ITEMS)\r
+ if (!(ReportItemData & IOF_CONSTANT))\r
+ ParserData->TotalReportItems++;\r
+#else\r
+ ParserData->TotalReportItems++;\r
+#endif\r
+ }\r
+ \r
+ UsageStackSize = 0;\r
+ \r
+ break;\r
+ }\r
+ \r
+ if ((*ReportData & TYPE_MASK) == TYPE_MAIN)\r
+ {\r
+ CurrStateTable->Attributes.Usage.MinMax.Minimum = 0;\r
+ CurrStateTable->Attributes.Usage.MinMax.Maximum = 0;\r
+ UsageStackSize = 0;\r
+ }\r
+ \r
+ switch (*ReportData & DATA_SIZE_MASK)\r
+ {\r
+ case DATA_SIZE_4:\r
+ ReportSize -= 5;\r
+ ReportData += 5;\r
+ break;\r
+ case DATA_SIZE_2:\r
+ ReportSize -= 3;\r
+ ReportData += 3;\r
+ break;\r
+ case DATA_SIZE_1:\r
+ ReportSize -= 2;\r
+ ReportData += 2;\r
+ break;\r
+ case DATA_SIZE_0:\r
+ ReportSize -= 1;\r
+ ReportData += 1;\r
+ break;\r
+ }\r
+ }\r
+ \r
+ return HID_PARSE_Successful;\r
+}\r
+\r
+bool USB_GetHIDReportItemInfo(const uint8_t* ReportData, HID_ReportItem_t* const ReportItem)\r
+{\r
+ uint16_t DataBitsRem = ReportItem->Attributes.BitSize;\r
+ uint16_t CurrentBit = ReportItem->BitOffset;\r
+ uint32_t BitMask = (1 << 0);\r
+\r
+ ReportItem->Value = 0;\r
+ \r
+ if (ReportItem->ReportID)\r
+ {\r
+ if (ReportItem->ReportID != ReportData[0])\r
+ return false;\r
+\r
+ ReportData++;\r
+ }\r
+\r
+ while (DataBitsRem--)\r
+ {\r
+ if (ReportData[CurrentBit / 8] & (1 << (CurrentBit % 8)))\r
+ ReportItem->Value |= BitMask;\r
+ \r
+ CurrentBit++;\r
+ BitMask <<= 1;\r
+ }\r
+ \r
+ return true;\r
+}\r
+\r
+void USB_SetHIDReportItemInfo(uint8_t* ReportData, const HID_ReportItem_t* ReportItem)\r
+{\r
+ uint16_t DataBitsRem = ReportItem->Attributes.BitSize;\r
+ uint16_t CurrentBit = ReportItem->BitOffset;\r
+ uint32_t BitMask = (1 << 0);\r
+\r
+ if (ReportItem->ReportID)\r
+ {\r
+ ReportData[0] = ReportItem->ReportID;\r
+ ReportData++;\r
+ }\r
+\r
+ while (DataBitsRem--)\r
+ {\r
+ if (ReportItem->Value & (1 << (CurrentBit % 8)))\r
+ ReportData[CurrentBit / 8] |= BitMask;\r
+\r
+ CurrentBit++;\r
+ BitMask <<= 1;\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * USB Human Interface Device (HID) Class report descriptor processing routines. This file allows for the easy\r
+ * parsing of the complex HID report descriptor, which describes the data that the device transmits to the host.\r
+ *\r
+ */\r
+ \r
+/** \ingroup Group_USB\r
+ * @defgroup Group_HIDParser HID Report Parser\r
+ *\r
+ * Functions, macros, variables, enums and types related to the parsing of HID class device report descriptors.\r
+ *\r
+ * The processed HID report is presented back to the user application as a flat structure containing each report\r
+ * item's IN, OUT and FEATURE (if desired) items along with each item's attributes.\r
+ *\r
+ * This library portion also allows for easy setting and retrieval of data from a HID report, including devices\r
+ * with multiple reports on the one HID interface.\r
+ *\r
+ * By default, FEATURE reports and IN/OUT reports with constant data are ignored in the HID report when processed\r
+ * to save on memory. This can be overridden by defining the HID_ENABLE_FEATURE_PROCESSING or\r
+ * HID_INCLUDE_CONSTANT_DATA_ITEMS tokens in the user project makefile, passing them to the compiler via the -D\r
+ * switch.\r
+ *\r
+ * @{\r
+ */\r
+\r
+#ifndef __HIDPARSER_H__\r
+#define __HIDPARSER_H__\r
+\r
+ /* Includes: */\r
+ #include <string.h>\r
+ #include <stdbool.h>\r
+\r
+ #include "HIDReportData.h"\r
+\r
+ #include "../../../../Common/Common.h"\r
+\r
+ /* Enable C linkage for C++ Compilers: */\r
+ #if defined(__cplusplus)\r
+ extern "C" {\r
+ #endif\r
+\r
+ /* Preprocessor checks and defines: */\r
+ #if !defined(HID_STATETABLE_STACK_DEPTH) || defined(__DOXYGEN__)\r
+ /** Constant indicating the maximum stack depth of the state table. A larger state table\r
+ * allows for more PUSH/POP report items to be nested, but consumes more memory. By default\r
+ * this is set to 3 levels (allowing for two PUSHes to be nested) but this can be overridden by\r
+ * defining HID_STATETABLE_STACK_DEPTH to another value in the user project makefile, passing the\r
+ * define to the compiler using the -D compiler switch.\r
+ */\r
+ #define HID_STATETABLE_STACK_DEPTH 3\r
+ #endif\r
+ \r
+ #if !defined(HID_USAGE_STACK_DEPTH) || defined(__DOXYGEN__)\r
+ /** Constant indicating the maximum stack depth of the usage table. A larger usage table\r
+ * allows for more USAGE items to be indicated sequentially for REPORT COUNT entries of more than\r
+ * one, but requires more stack space. By default this is set to 8 levels (allowing for a report\r
+ * item with a count of 8) but this can be overridden by defining HID_USAGE_STACK_DEPTH to another\r
+ * value in the user project makefile, passing the define to the compiler using the -D compiler\r
+ * switch.\r
+ */\r
+ #define HID_USAGE_STACK_DEPTH 8\r
+ #endif\r
+\r
+ #if !defined(HID_MAX_COLLECTIONS) || defined(__DOXYGEN__)\r
+ /** Constant indicating the maximum number of COLLECTION items (nested or unnested) that can be\r
+ * processed in the report item descriptor. A large value allows for more COLLECTION items to be\r
+ * processed, but consumes more memory. By default this is set to 5 collections, but this can be\r
+ * overridden by defining HID_MAX_COLLECTIONS to another value in the user project makefile, passing\r
+ * the define to the compiler using the -D compiler switch.\r
+ */\r
+ #define HID_MAX_COLLECTIONS 5\r
+ #endif\r
+ \r
+ #if !defined(HID_MAX_REPORTITEMS) || defined(__DOXYGEN__)\r
+ /** Constant indicating the maximum number of report items (IN, OUT or FEATURE if enabled) that can be\r
+ * processed in the report item descriptor. A large value allows for more report items to be\r
+ * processed, but consumes more memory. By default this is set to 30 items, but this can be\r
+ * overridden by defining HID_MAX_REPORTITEMS to another value in the user project makefile, passing\r
+ * the define to the compiler using the -D compiler switch.\r
+ */\r
+ #define HID_MAX_REPORTITEMS 30\r
+ #endif\r
+\r
+ /* Public Interface - May be used in end-application: */\r
+ /* Enums: */\r
+ /** Enum for indicating what type of report item an entry in a \ref HID_ReportInfo_t ReportItem array is */\r
+ enum HID_ReportItemTypes_t\r
+ {\r
+ REPORT_ITEM_TYPE_In = 0, /**< Indicates that the item is an IN report type. */\r
+ REPORT_ITEM_TYPE_Out = 1, /**< Indicates that the item is an OUT report type. */\r
+ REPORT_ITEM_TYPE_Feature = 2, /**< Indicates that the item is a FEATURE report type. */\r
+ };\r
+ \r
+ /** Enum for the possible error codes in the return value of the \ref USB_ProcessHIDReport() function */\r
+ enum HID_Parse_ErrorCodes_t\r
+ {\r
+ HID_PARSE_Successful = 0, /**< Successful parse of the HID report descriptor, no error. */\r
+ HID_PARSE_HIDStackOverflow = 1, /**< More than \ref HID_STATETABLE_STACK_DEPTH nested PUSHes in the report. */ \r
+ HID_PARSE_HIDStackUnderflow = 2, /**< A POP was found when the state table stack was empty. */\r
+ HID_PARSE_InsufficientReportItems = 3, /**< More than \ref HID_MAX_REPORTITEMS report items in the report. */\r
+ HID_PARSE_UnexpectedEndCollection = 4, /**< END COLLECTION found without matching COLLECTION item. */\r
+ HID_PARSE_InsufficientCollectionPaths = 5, /**< More than \ref HID_MAX_COLLECTIONS collections in the report. */\r
+ HID_PARSE_UsageStackOverflow = 6, /**< More than \ref HID_USAGE_STACK_DEPTH usages listed in a row. */\r
+ };\r
+ \r
+ /* Type Defines: */ \r
+ /** Type define for an attribute with both minimum and maximum values (e.g. Logical Min/Max). */\r
+ typedef struct\r
+ {\r
+ uint32_t Minimum; /**< Minimum value for the attribute. */\r
+ uint32_t Maximum; /**< Maximum value for the attribute. */\r
+ } HID_MinMax_t;\r
+\r
+ /** Type define for the Unit attributes of a report item. */\r
+ typedef struct\r
+ {\r
+ uint32_t Type; /**< Unit type (refer to HID specifications for details). */\r
+ uint8_t Exponent; /**< Unit exponent (refer to HID specifications for details). */\r
+ } HID_Unit_t;\r
+ \r
+ /** Type define for the Usage attributes of a report item. */\r
+ typedef struct\r
+ {\r
+ uint16_t Page; /**< Usage page of the report item. */\r
+ uint16_t Usage; /**< Usage of the report item. */\r
+ HID_MinMax_t MinMax; /**< Usage minimum and maximum of the report item. */\r
+ } HID_Usage_t;\r
+\r
+ /** Type define for a COLLECTION object. Contains the collection attributes and a reference to the\r
+ * parent collection if any.\r
+ */\r
+ typedef struct CollectionPath\r
+ {\r
+ uint8_t Type; /**< Collection type (e.g. "Generic Desktop"). */\r
+ HID_Usage_t Usage; /**< Collection usage. */\r
+ struct CollectionPath* Parent; /**< Reference to parent collection, or NULL if root collection. */\r
+ } HID_CollectionPath_t;\r
+\r
+ /** Type define for all the data attributes of a report item, except flags. */\r
+ typedef struct\r
+ {\r
+ uint8_t BitSize; /**< Size in bits of the report item's data. */\r
+ \r
+ HID_Usage_t Usage; /**< Usage of the report item. */\r
+ HID_Unit_t Unit; /**< Unit type and exponent of the report item. */\r
+ HID_MinMax_t Logical; /**< Logical minimum and maximum of the report item. */\r
+ HID_MinMax_t Physical; /**< Physical minimum and maximum of the report item. */\r
+ } HID_ReportItem_Attributes_t;\r
+ \r
+ /** Type define for a report item (IN, OUT or FEATURE) attributes and other details. */\r
+ typedef struct\r
+ {\r
+ uint16_t BitOffset; /**< Bit offset in the IN, OUT or FEATURE report of the item. */\r
+ uint8_t ItemType; /**< Report item type, a value in HID_Types_t. */\r
+ uint16_t ItemFlags; /**< Item data flags, such as constant/variable, etc. */\r
+ uint8_t ReportID; /**< Report ID this item belongs to, or 0x00 if device has only one report */\r
+ HID_CollectionPath_t* CollectionPath; /**< Collection path of the item. */\r
+\r
+ HID_ReportItem_Attributes_t Attributes; /**< Report item attributes. */\r
+ \r
+ uint32_t Value; /**< Current value of the report item. */\r
+ } HID_ReportItem_t;\r
+\r
+ /** Type define for a complete processed HID report, including all report item data and collections. */\r
+ typedef struct\r
+ {\r
+ uint8_t TotalReportItems; /**< Total number of report items stored in the\r
+ * ReportItems array. */\r
+\r
+ HID_ReportItem_t ReportItems[HID_MAX_REPORTITEMS]; /**< Report items array, including\r
+ * all IN, OUT and FEATURE items. */\r
+\r
+ HID_CollectionPath_t CollectionPaths[HID_MAX_COLLECTIONS]; /**< All collection items, referenced\r
+ * by the report items. */\r
+ } HID_ReportInfo_t;\r
+ \r
+ /* Function Prototypes: */\r
+ /** Function to process a given HID report returned from an attached device, and store it into a given\r
+ * \ref HID_ReportInfo_t structure.\r
+ *\r
+ * \param ReportData Buffer containing the device's HID report table\r
+ * \param ReportSize Size in bytes of the HID report table\r
+ * \param ParserData Pointer to a \ref HID_ReportInfo_t instance for the parser output\r
+ *\r
+ * \return A value in the \ref HID_Parse_ErrorCodes_t enum\r
+ */\r
+ uint8_t USB_ProcessHIDReport(const uint8_t* ReportData, uint16_t ReportSize, HID_ReportInfo_t* const ParserData)\r
+ ATTR_NON_NULL_PTR_ARG(1, 3);\r
+\r
+ /** Extracts the given report item's value out of the given HID report and places it into the Value\r
+ * member of the report item's \ref HID_ReportItem_t structure.\r
+ *\r
+ * \param ReportData Buffer containing an IN or FEATURE report from an attached device\r
+ * \param ReportItem Pointer to the report item of interest in a \ref HID_ReportInfo_t ReportItem array\r
+ *\r
+ * \returns Boolean true if the item to retrieve was located in the given report, false otherwise\r
+ */\r
+ bool USB_GetHIDReportItemInfo(const uint8_t* ReportData, HID_ReportItem_t* const ReportItem)\r
+ ATTR_NON_NULL_PTR_ARG(1, 2);\r
+\r
+ /** Retrieves the given report item's value out of the Value member of the report item's\r
+ * \ref HID_ReportItem_t structure and places it into the correct position in the HID report\r
+ * buffer. The report buffer is assumed to have the appropriate bits cleared before calling\r
+ * this function (i.e., the buffer should be explicitly cleared before report values are added).\r
+ *\r
+ * If the device has multiple HID reports, the report ID is set to the report ID of the given item.\r
+ *\r
+ * \param ReportData Buffer holding the current OUT report data\r
+ * \param ReportItem Pointer to the report item of interest in a \ref HID_ReportInfo_t ReportItem array\r
+ */\r
+ void USB_SetHIDReportItemInfo(uint8_t* ReportData, const HID_ReportItem_t* ReportItem)\r
+ ATTR_NON_NULL_PTR_ARG(1, 2);\r
+\r
+ /* Private Interface - For use in library only: */\r
+ #if !defined(__DOXYGEN__)\r
+ /* Type Defines: */\r
+ typedef struct\r
+ {\r
+ HID_ReportItem_Attributes_t Attributes;\r
+ uint8_t ReportCount;\r
+ uint8_t ReportID;\r
+ } HID_StateTable_t;\r
+ #endif\r
+ \r
+ /* Disable C linkage for C++ Compilers: */\r
+ #if defined(__cplusplus)\r
+ }\r
+ #endif\r
+\r
+#endif\r
+\r
+/** @} */\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Constants for HID report item attributes. Refer to the HID specification for details on each\r
+ * flag's meaning when applied to an IN, OUT or FEATURE item.\r
+ */\r
+\r
+/** \ingroup Group_HIDParser\r
+ * @defgroup Group_HIDIOFConst Input/Output/Feature Masks\r
+ *\r
+ * Masks indicating the type of Input, Output of Feature HID report item.\r
+ *\r
+ * @{\r
+ */\r
+ \r
+#ifndef __HIDREPORTDATA_H__\r
+#define __HIDREPORTDATA_H__\r
+\r
+ /* Public Interface - May be used in end-application: */\r
+ /* Macros: */\r
+ /** HID_ReportItem_t.ItemFlags flag for constant data. */\r
+ #define IOF_CONSTANT (1 << 0)\r
+\r
+ /** HID_ReportItem_t.ItemFlags flag for data. */\r
+ #define IOF_DATA (0 << 0)\r
+\r
+ /** HID_ReportItem_t.ItemFlags flag for variable data. */\r
+ #define IOF_VARIABLE (1 << 1)\r
+\r
+ /** HID_ReportItem_t.ItemFlags flag for array data. */\r
+ #define IOF_ARRAY (0 << 1)\r
+\r
+ /** HID_ReportItem_t.ItemFlags flag for relative data. */\r
+ #define IOF_RELATIVE (1 << 2)\r
+\r
+ /** HID_ReportItem_t.ItemFlags flag for absolute data. */\r
+ #define IOF_ABSOLUTE (0 << 2)\r
+\r
+ /** HID_ReportItem_t.ItemFlags flag for wrapped value data. */\r
+ #define IOF_WRAP (1 << 3)\r
+\r
+ /** HID_ReportItem_t.ItemFlags flag for non-wrapped value data. */\r
+ #define IOF_NOWRAP (0 << 3)\r
+\r
+ /** HID_ReportItem_t.ItemFlags flag for non linear data. */\r
+ #define IOF_NONLINEAR (1 << 4)\r
+\r
+ /** HID_ReportItem_t.ItemFlags flag for linear data. */\r
+ #define IOF_LINEAR (0 << 4)\r
+\r
+ /** HID_ReportItem_t.ItemFlags flag for no preferred state. */\r
+ #define IOF_NOPREFERRED (1 << 5)\r
+\r
+ /** HID_ReportItem_t.ItemFlags flag for preferred state items. */\r
+ #define IOF_PREFERREDSTATE (0 << 5)\r
+\r
+ /** HID_ReportItem_t.ItemFlags flag for null state items. */\r
+ #define IOF_NULLSTATE (1 << 6)\r
+\r
+ /** HID_ReportItem_t.ItemFlags flag for no null position data. */\r
+ #define IOF_NONULLPOSITION (0 << 6)\r
+\r
+ /** HID_ReportItem_t.ItemFlags flag for buffered bytes. */\r
+ #define IOF_BUFFEREDBYTES (1 << 8)\r
+\r
+ /** HID_ReportItem_t.ItemFlags flag for bit field data. */\r
+ #define IOF_BITFIELD (0 << 8)\r
+\r
+ /* Private Interface - For use in library only: */\r
+ #if !defined(__DOXYGEN__)\r
+ /* Macros: */\r
+ #define DATA_SIZE_MASK 0x03\r
+ #define TYPE_MASK 0x0C\r
+ #define TAG_MASK 0xF0\r
+\r
+ #define DATA_SIZE_0 0x00\r
+ #define DATA_SIZE_1 0x01\r
+ #define DATA_SIZE_2 0x02\r
+ #define DATA_SIZE_4 0x03\r
+ \r
+ #define TYPE_MAIN 0x00\r
+ #define TYPE_GLOBAL 0x04\r
+ #define TYPE_LOCAL 0x08\r
+ \r
+ #define TAG_MAIN_INPUT 0x80\r
+ #define TAG_MAIN_OUTPUT 0x90\r
+ #define TAG_MAIN_COLLECTION 0xA0\r
+ #define TAG_MAIN_FEATURE 0xB0\r
+ #define TAG_MAIN_ENDCOLLECTION 0xC0\r
+\r
+ #define TAG_GLOBAL_USAGEPAGE 0x00\r
+ #define TAG_GLOBAL_LOGICALMIN 0x10\r
+ #define TAG_GLOBAL_LOGICALMAX 0x20\r
+ #define TAG_GLOBAL_PHYSMIN 0x30\r
+ #define TAG_GLOBAL_PHYSMAX 0x40\r
+ #define TAG_GLOBAL_UNITEXP 0x50\r
+ #define TAG_GLOBAL_UNIT 0x60\r
+ #define TAG_GLOBAL_REPORTSIZE 0x70\r
+ #define TAG_GLOBAL_REPORTID 0x80\r
+ #define TAG_GLOBAL_REPORTCOUNT 0x90\r
+ #define TAG_GLOBAL_PUSH 0xA0\r
+ #define TAG_GLOBAL_POP 0xB0\r
+ \r
+ #define TAG_LOCAL_USAGE 0x00\r
+ #define TAG_LOCAL_USAGEMIN 0x10\r
+ #define TAG_LOCAL_USAGEMAX 0x20\r
+ #endif\r
+\r
+/** @} */\r
+ \r
+#endif\r
* \ref Group_USBManagement documentation).\r
*/\r
void EVENT_USB_Reset(void);\r
+ \r
+ /** Event for the USB start of frame interrupt, firing once each millisecond in either device or host\r
+ * mode, while USB frames are being generated or recieved.\r
+ */\r
+ void EVENT_USB_StartOfFrame(void);\r
#endif\r
\r
/* Private Interface - For use in library only: */\r
void EVENT_USB_Suspend(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);\r
void EVENT_USB_WakeUp(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);\r
void EVENT_USB_Reset(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);\r
+ void EVENT_USB_StartOfFrame(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);\r
#endif\r
#endif\r
\r
\r
EVENT_USB_Reset();\r
}\r
+ \r
+ if (USB_INT_HasOccurred(USB_INT_SOFI) && USB_INT_IsEnabled(USB_INT_SOFI))\r
+ {\r
+ USB_INT_Clear(USB_INT_SOFI);\r
+\r
+ FrameElapsed = true;\r
+ \r
+ EVENT_USB_StartOfFrame();\r
+ }\r
#endif\r
\r
#if defined(USB_CAN_BE_HOST)\r
\r
USB_ResetInterface();\r
}\r
+\r
+ if (USB_INT_HasOccurred(USB_INT_HSOFI) && USB_INT_IsEnabled(USB_INT_HSOFI))\r
+ {\r
+ USB_INT_Clear(USB_INT_HSOFI);\r
+\r
+ FrameElapsed = true;\r
+ \r
+ EVENT_USB_StartOfFrame();\r
+ }\r
#endif\r
\r
#if defined(USB_CAN_BE_BOTH)\r
volatile uint8_t USB_HostState;\r
#endif\r
\r
-TASK(USB_USBTask)\r
+void USB_USBTask(void)\r
{\r
#if defined(USB_HOST_ONLY)\r
USB_HostTask();\r
#include <stdbool.h>\r
#include <stddef.h>\r
\r
- #include "../../../Scheduler/Scheduler.h"\r
#include "../LowLevel/LowLevel.h"\r
#include "StdRequestType.h"\r
#include "USBMode.h"\r
extern volatile uint8_t USB_HostState;\r
#endif\r
\r
- /* Tasks: */\r
+ /* Function Prototypes: */\r
/** This is the main USB management task. The USB driver requires that this task be executed\r
* continuously when the USB system is active (device attached in host mode, or attached to a host\r
* in device mode) in order to manage USB communications. This task may be executed inside an RTOS,\r
- * scheduler (e.g. the simple LUFA Scheduler), fast timer ISR or the main user application loop.\r
+ * fast timer ISR or the main user application loop.\r
*\r
* The USB task must be serviced within 30ms while in device mode, or within 1ms while in host mode.\r
* The task may be serviced at all times, or (for minimum CPU consumption):\r
*\r
* \ingroup Group_USBManagement\r
*/\r
- TASK(USB_USBTask);\r
+ void USB_USBTask(void);\r
\r
/* Private Interface - For use in library only: */\r
#if !defined(__DOXYGEN__)\r
uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;\r
#endif\r
\r
- USB_INT_Clear(USB_INT_SOFI);\r
-\r
for (;;)\r
{\r
if (Endpoint_GetEndpointDirection() == ENDPOINT_DIR_IN)\r
else if (Endpoint_IsStalled())\r
return ENDPOINT_READYWAIT_EndpointStalled;\r
\r
- if (USB_INT_HasOccurred(USB_INT_SOFI))\r
+ if (FrameElapsed)\r
{\r
- USB_INT_Clear(USB_INT_SOFI);\r
+ FrameElapsed = false;\r
\r
if (!(TimeoutMSRem--))\r
return ENDPOINT_READYWAIT_Timeout;\r
bool BusSuspended = USB_Host_IsBusSuspended();\r
uint8_t ErrorCode = HOST_WAITERROR_Successful;\r
\r
- USB_INT_Clear(USB_INT_HSOFI);\r
USB_Host_ResumeBus();\r
\r
while (MS)\r
{\r
- if (USB_INT_HasOccurred(USB_INT_HSOFI))\r
+ if (FrameElapsed)\r
{\r
- USB_INT_Clear(USB_INT_HSOFI);\r
+ FrameElapsed = false;\r
MS--;\r
}\r
\r
USB_Host_ResetBus();\r
while (!(USB_Host_IsBusResetComplete()));\r
\r
- USB_INT_Clear(USB_INT_HSOFI);\r
USB_Host_ResumeBus(); \r
\r
+ FrameElapsed = false;\r
+\r
for (uint8_t MSRem = 10; MSRem != 0; MSRem--)\r
{\r
/* Workaround for powerless-pull-up devices. After a USB bus reset,\r
looked for - if it is found within 10ms, the device is still\r
present. */\r
\r
- if (USB_INT_HasOccurred(USB_INT_HSOFI))\r
+ if (FrameElapsed)\r
{\r
+ FrameElapsed = false;\r
+ \r
USB_INT_Clear(USB_INT_DDISCI);\r
break;\r
}\r
volatile uint8_t USB_Options;\r
#endif\r
\r
+volatile bool FrameElapsed;\r
+\r
void USB_Init(\r
#if defined(USB_CAN_BE_BOTH)\r
const uint8_t Mode\r
USB_INT_DisableAllInterrupts();\r
USB_INT_ClearAllInterrupts();\r
\r
+ FrameElapsed = false;\r
+\r
USB_IsConnected = false;\r
\r
#if defined(USB_CAN_BE_HOST)\r
#if defined(USB_DEVICE_ONLY) \r
USB_INT_Enable(USB_INT_SUSPEND);\r
USB_INT_Enable(USB_INT_EORSTI);\r
+ USB_INT_Enable(USB_INT_SOFI);\r
\r
#if defined(CONTROL_ONLY_DEVICE)\r
UENUM = ENDPOINT_CONTROLEP;\r
\r
USB_INT_Enable(USB_INT_SRPI);\r
USB_INT_Enable(USB_INT_BCERRI);\r
+ USB_INT_Enable(USB_INT_HSOFI);\r
#else\r
if (USB_CurrentMode == USB_MODE_DEVICE)\r
{\r
USB_INT_Enable(USB_INT_SUSPEND);\r
USB_INT_Enable(USB_INT_EORSTI);\r
+ USB_INT_Enable(USB_INT_SOFI);\r
\r
#if defined(CONTROL_ONLY_DEVICE)\r
UENUM = ENDPOINT_CONTROLEP;\r
\r
USB_INT_Enable(USB_INT_SRPI);\r
USB_INT_Enable(USB_INT_BCERRI);\r
+ USB_INT_Enable(USB_INT_HSOFI);\r
}\r
#endif\r
}\r
return USB_MODE_HOST;\r
}\r
#endif\r
+ \r
+ /* External Variables: */\r
+ extern volatile bool FrameElapsed;\r
\r
#endif\r
\r
uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;\r
#endif\r
\r
- USB_INT_Clear(USB_INT_HSOFI);\r
-\r
for (;;)\r
{\r
if (Pipe_GetPipeToken() == PIPE_TOKEN_IN)\r
else if (!(USB_IsConnected))\r
return PIPE_READYWAIT_DeviceDisconnected;\r
\r
- if (USB_INT_HasOccurred(USB_INT_HSOFI))\r
+ if (FrameElapsed)\r
{\r
- USB_INT_Clear(USB_INT_HSOFI);\r
+ FrameElapsed = false;\r
\r
if (!(TimeoutMSRem--))\r
return PIPE_READYWAIT_Timeout;\r
* - LUFA/Drivers/USB/HighLevel/USBInterrupt.c\r
* - LUFA/Drivers/USB/HighLevel/USBTask.c\r
* - LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c\r
- * - LUFA/Drivers/USB/Class/HIDParser.c\r
*\r
* \section Module Description\r
* Functions, macros, variables, enums and types related to the management of USB communications.\r
#endif\r
\r
#include "HighLevel/ConfigDescriptor.h"\r
- #include "Class/HIDParser.h"\r
\r
#endif\r
\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-#define INCLUDE_FROM_DYNALLOC_C\r
-#include "DynAlloc.h"\r
-\r
-struct\r
-{\r
- char Mem_Heap[NUM_BLOCKS * BLOCK_SIZE];\r
- void* Mem_Handles[NUM_HANDLES];\r
- uint8_t Mem_Block_Flags[(NUM_BLOCKS / 4) + ((NUM_BLOCKS % 4) ? 1 : 0)];\r
- uint8_t FlagMaskLookupMask[4];\r
- uint8_t FlagMaskLookupNum[4];\r
-} Mem_MemData = {.FlagMaskLookupMask = {(3 << 0), (3 << 2), (3 << 4), (3 << 6)},\r
- .FlagMaskLookupNum = { 0, 2, 4, 6}};\r
-\r
-static uint8_t Mem_GetBlockFlags(const Block_Number_t BlockNum)\r
-{\r
- const Block_Number_t BlockIndex = (BlockNum >> 2);\r
- const uint8_t FlagMask = Mem_MemData.FlagMaskLookupMask[BlockNum & 0x03];\r
- const uint8_t FlagMaskShift = Mem_MemData.FlagMaskLookupNum[BlockNum & 0x03];\r
-\r
- return ((Mem_MemData.Mem_Block_Flags[BlockIndex] & FlagMask) >> FlagMaskShift);\r
-}\r
-\r
-static void Mem_SetBlockFlags(const Block_Number_t BlockNum, const uint8_t Flags)\r
-{\r
- const Block_Number_t BlockIndex = (BlockNum >> 2);\r
- const uint8_t FlagMask = Mem_MemData.FlagMaskLookupMask[BlockNum & 0x03];\r
- const uint8_t FlagMaskShift = Mem_MemData.FlagMaskLookupNum[BlockNum & 0x03];\r
-\r
- Mem_MemData.Mem_Block_Flags[BlockIndex] &= ~FlagMask;\r
- Mem_MemData.Mem_Block_Flags[BlockIndex] |= (Flags << FlagMaskShift);\r
-}\r
-\r
-static inline void Mem_Defrag(void)\r
-{\r
- Block_Number_t FreeStartBlock = 0;\r
- char* FreeStartPtr = NULL;\r
- char* UsedStartPtr = NULL;\r
- Block_Number_t CurrBlock;\r
- \r
- for (CurrBlock = 0; CurrBlock < NUM_BLOCKS; CurrBlock++)\r
- {\r
- if (!(Mem_GetBlockFlags(CurrBlock) & BLOCK_USED_MASK))\r
- {\r
- FreeStartPtr = &Mem_MemData.Mem_Heap[CurrBlock * BLOCK_SIZE];\r
- FreeStartBlock = CurrBlock;\r
- break;\r
- }\r
- }\r
- \r
- if (FreeStartPtr == NULL)\r
- return;\r
-\r
- while (++CurrBlock < NUM_BLOCKS)\r
- {\r
- uint8_t CurrBlockFlags = Mem_GetBlockFlags(CurrBlock);\r
- \r
- if (CurrBlockFlags & BLOCK_USED_MASK)\r
- {\r
- UsedStartPtr = &Mem_MemData.Mem_Heap[CurrBlock * BLOCK_SIZE];\r
- \r
- for (Handle_Number_t HandleNum = 0; HandleNum < NUM_HANDLES; HandleNum++)\r
- {\r
- if (Mem_MemData.Mem_Handles[HandleNum] == UsedStartPtr)\r
- {\r
- Mem_MemData.Mem_Handles[HandleNum] = FreeStartPtr;\r
- break;\r
- }\r
- }\r
-\r
- memcpy(FreeStartPtr, UsedStartPtr, BLOCK_SIZE);\r
- FreeStartPtr += BLOCK_SIZE;\r
- \r
- Mem_SetBlockFlags(FreeStartBlock++, CurrBlockFlags);\r
- Mem_SetBlockFlags(CurrBlock, 0);\r
- }\r
- }\r
-}\r
-\r
-static inline bool Mem_FindFreeBlocks(Block_Number_t* const RetStartPtr, const Block_Number_t Blocks)\r
-{\r
- Block_Number_t FreeInCurrSec = 0;\r
-\r
- for (Block_Number_t CurrBlock = 0; CurrBlock < NUM_BLOCKS; CurrBlock++)\r
- {\r
- if (Mem_GetBlockFlags(CurrBlock) & BLOCK_USED_MASK)\r
- FreeInCurrSec = 0;\r
- else\r
- FreeInCurrSec++;\r
-\r
- if (FreeInCurrSec >= Blocks)\r
- {\r
- *RetStartPtr = CurrBlock;\r
- return true;\r
- }\r
- }\r
-\r
- return false;\r
-}\r
-\r
-Mem_Handle_t Mem_Alloc(const Alloc_Size_t Bytes)\r
-{\r
- Block_Number_t ReqBlocks = (Bytes / BLOCK_SIZE);\r
- Block_Number_t StartBlock;\r
- \r
- if (Bytes % BLOCK_SIZE)\r
- ReqBlocks++;\r
- \r
- if (!(Mem_FindFreeBlocks(&StartBlock, ReqBlocks)))\r
- {\r
- Mem_Defrag();\r
- \r
- if (!(Mem_FindFreeBlocks(&StartBlock, ReqBlocks)))\r
- return NULL; \r
- }\r
-\r
- for (Block_Number_t UsedBlock = 0; UsedBlock < (ReqBlocks - 1); UsedBlock++)\r
- Mem_SetBlockFlags((StartBlock + UsedBlock), (BLOCK_USED_MASK | BLOCK_LINKED_MASK));\r
-\r
- Mem_SetBlockFlags((StartBlock + (ReqBlocks - 1)), BLOCK_USED_MASK);\r
- \r
- for (Handle_Number_t AllocEntry = 0; AllocEntry < NUM_HANDLES; AllocEntry++)\r
- {\r
- Mem_Handle_t CurrHdl = (Mem_Handle_t)&Mem_MemData.Mem_Handles[AllocEntry];\r
- \r
- if (DEREF(CurrHdl, void*) == NULL)\r
- {\r
- DEREF(CurrHdl, void*) = &Mem_MemData.Mem_Heap[StartBlock * BLOCK_SIZE];\r
- return CurrHdl;\r
- }\r
- }\r
-\r
- return NULL;\r
-}\r
-\r
-Mem_Handle_t Mem_Realloc(Mem_Handle_t CurrAllocHdl, const Alloc_Size_t Bytes)\r
-{\r
- Mem_Free(CurrAllocHdl);\r
- return Mem_Alloc(Bytes);\r
-}\r
-\r
-Mem_Handle_t Mem_Calloc(const Alloc_Size_t Bytes)\r
-{\r
- Mem_Handle_t AllocHdl = Mem_Alloc(Bytes);\r
- \r
- if (AllocHdl != NULL)\r
- memset(DEREF(AllocHdl, void*), 0x00, Bytes);\r
-\r
- return AllocHdl;\r
-}\r
-\r
-void Mem_Free(Mem_Handle_t CurrAllocHdl)\r
-{\r
- char* MemBlockPtr = DEREF(CurrAllocHdl, char*);\r
- Block_Number_t CurrBlock = ((uint16_t)(MemBlockPtr - Mem_MemData.Mem_Heap) / BLOCK_SIZE);\r
- uint8_t CurrBlockFlags;\r
-\r
- if ((CurrAllocHdl == NULL) || (MemBlockPtr == NULL))\r
- return;\r
-\r
- do\r
- {\r
- CurrBlockFlags = Mem_GetBlockFlags(CurrBlock);\r
- Mem_SetBlockFlags(CurrBlock, 0);\r
-\r
- CurrBlock++;\r
- }\r
- while (CurrBlockFlags & BLOCK_LINKED_MASK);\r
- \r
- DEREF(CurrAllocHdl, void*) = NULL;\r
-}\r
-\r
-Block_Number_t Mem_TotalFreeBlocks(void)\r
-{\r
- Block_Number_t FreeBlocks = 0;\r
- \r
- for (Block_Number_t CurrBlock = 0; CurrBlock < NUM_BLOCKS; CurrBlock++)\r
- {\r
- if (!(Mem_GetBlockFlags(CurrBlock) & BLOCK_USED_MASK))\r
- FreeBlocks++;\r
- }\r
- \r
- return FreeBlocks;\r
-}\r
-\r
-Handle_Number_t Mem_TotalFreeHandles(void)\r
-{\r
- Handle_Number_t FreeHandles = 0;\r
- \r
- for (Handle_Number_t CurrHandle = 0; CurrHandle < NUM_HANDLES; CurrHandle++)\r
- {\r
- if (Mem_MemData.Mem_Handles[CurrHandle] == NULL)\r
- FreeHandles++;\r
- }\r
- \r
- return FreeHandles;\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Dynamic, auto-defragmenting block memory allocator library. This library provides a convenient replacement for\r
- * the standard avr-libc dynamic memory allocation routines. Memory is handed out in block chunks, to reduce the\r
- * management memory overhead.\r
- */\r
-\r
-/** @defgroup Group_MemoryAllocator Dynamic Block Memory Allocator - LUFA/MemoryAllocator/DynAlloc.h\r
- *\r
- * \section Sec_Dependencies Module Source Dependencies\r
- * The following files must be built with any user project that uses this module:\r
- * - LUFA/MemoryAllocator/DynAlloc.c\r
- *\r
- * \section Module Description\r
- * Dynamic, auto-defragmenting block memory allocator library. This library provides a convenient replacement for\r
- * the standard avr-libc dynamic memory allocation routines. Memory is handed out in block chunks, to reduce the\r
- * management memory overhead.\r
- *\r
- * Unlike the normal memory allocation routines, this library gives out handles to memory which must be dereferenced\r
- * at the exact time of use, rather than handing back direct memory pointers. By using library managed handles\r
- * instead of pointers, allocated memory blocks can be shifted around as needed transparently to defragment the\r
- * memory as more blocks are requested.\r
- *\r
- * The memory heap is static, thus the total memory usage of the compiled application (as reported by the avr-size\r
- * tool of the AVR-GCC toolchain) includes the dynamic memory heap.\r
- *\r
- * The constants NUM_BLOCKS, BLOCK_SIZE and NUM_HANDLES must be defined in the project makefile (and passed to the\r
- * preprocessor via the -D GCC switch) for this library to compile.\r
- *\r
- * NUM_BLOCKS indicates the number of memory blocks in the memory psudoheap which can be chained together and handed\r
- * to the application via a memory handle. NUM_HANDLES is the maximum number of memory handles (pointing to one or\r
- * more chained memory blocks) which can be handed out simultaneously before requiring a handle (and its associated\r
- * memory) to be freed. BLOCK_SIZE gives the number of bytes in each memory block. \r
- *\r
- * @{\r
- */\r
-\r
-#ifndef __DYN_ALLOC__\r
-#define __DYN_ALLOC__\r
-\r
- /* Includes : */\r
- #include <avr/io.h>\r
- #include <stdbool.h>\r
- #include <string.h>\r
- \r
- /* Preprocessor Checks: */\r
- #if (!defined(NUM_BLOCKS) || !defined(BLOCK_SIZE) || !defined(NUM_HANDLES))\r
- #error NUM_BLOCKS, BLOCK_SIZE and NUM_HANDLES must be defined before use via makefile.\r
- #endif\r
-\r
- /* Public Interface - May be used in end-application: */\r
- /* Macros: */\r
- /** Macro to dereference a given memory handle into the given type. The given type should be a pointer\r
- * if the memory is to contain an array of items, or should be a standard type (such as a primitive or\r
- * structure) if the memory is to hold a single item of a single type. */\r
- #define DEREF(handle, type) (*(type*)handle)\r
- \r
- /** Constant, giving the total heap size in bytes. */\r
- #define ALLOCABLE_BYTES (1UL * NUM_BLOCKS * BLOCK_SIZE)\r
- \r
- /* Type Defines: */\r
- /** Memory handle type, used to store handles given by the library functions. */\r
- typedef const void** Mem_Handle_t;\r
- \r
- #if (ALLOCABLE_BYTES > 0xFFFF) || defined(__DOXYGEN__)\r
- /** Type define for the size (in bytes) for an allocation for passing to the library functions.\r
- * The exact type width varies depending on the value of ALLOCABLE_BYTES to ensure that a single\r
- * allocation can request the entire heap if needed.\r
- */\r
- typedef uint32_t Alloc_Size_t;\r
- #elif (ALLOCABLE_BYTES > 0xFF)\r
- typedef uint16_t Alloc_Size_t;\r
- #else \r
- typedef uint8_t Alloc_Size_t;\r
- #endif\r
-\r
- #if (NUM_BLOCKS > 0xFFFF) || defined(__DOXYGEN__)\r
- /** Type define for a block number in the heap. The exact type width varies depending on the\r
- * value of NUM_BLOCKS to ensure that the type can store an index to any block in the block pool.\r
- */\r
- typedef uint32_t Block_Number_t;\r
- #elif (NUM_BLOCKS > 0xFF)\r
- typedef uint16_t Block_Number_t;\r
- #else\r
- typedef uint8_t Block_Number_t;\r
- #endif\r
-\r
- #if (NUM_HANDLES > 0xFFFF) || defined(__DOXYGEN__)\r
- /** Type define for a handle number. The exact type width varies depending on the value of NUM_HANDLES\r
- * to ensure that the type can store the index of any handle in the handle pool.\r
- */\r
- typedef uint32_t Handle_Number_t;\r
- #elif (NUM_HANDLES > 0xFF)\r
- typedef uint16_t Handle_Number_t;\r
- #else \r
- typedef uint8_t Handle_Number_t;\r
- #endif\r
- \r
- /* Function Prototypes: */\r
- /** Allocates a given number of blocks from the heap (calculated from the requested number of bytes) and\r
- * returns a handle to the newly allocated memory.\r
- *\r
- * \param Bytes The number of bytes requested to be allocated from the heap\r
- *\r
- * \return NULL handle if the allocation fails, or handle to the allocated memory if the allocation succeeds\r
- */\r
- Mem_Handle_t Mem_Alloc(const Alloc_Size_t Bytes);\r
- \r
- /** Allocates a given number of blocks from the heap (calculated from the requested number of bytes) and\r
- * returns a handle to the newly allocated memory. Calloced memory is automatically cleared to all 0x00\r
- * values at the time of allocation.\r
- *\r
- * \param Bytes The number of pre-cleared bytes requested to be allocated from the heap\r
- *\r
- * \return NULL handle if the allocation fails, or handle to the allocated memory if the allocation succeeds\r
- */\r
- Mem_Handle_t Mem_Calloc(const Alloc_Size_t Bytes);\r
-\r
- /** Deallocates a given memory handle, and attempts to allocates the given number of blocks from the heap\r
- * (calculated from the requested number of bytes) immediately following the deallocation. The new memory\r
- * may be located in the same area as the previous memory, but this is not guaranteed.\r
- *\r
- * \param CurrAllocHdl Handle to an already allocated section of memory in the heap to deallocate\r
- * \param Bytes The number of bytes requested to be allocated from the heap following the\r
- * deallocation\r
- *\r
- * \return NULL handle if the allocation fails, or handle to the allocated memory if the allocation succeeds\r
- *\r
- * \warning Even if the allocation fails, the deallocation will still occur. Care should be taken to ensure\r
- * that the previously allocated memory is not used following an unsuccessful realloc().\r
- */\r
- Mem_Handle_t Mem_Realloc(Mem_Handle_t CurrAllocHdl, const Alloc_Size_t Bytes);\r
- \r
- /** Deallocates a given previously allocated section of memory from the heap.\r
- *\r
- * \param CurrAllocHdl Handle to a previously allocated section of memory in the heap\r
- */\r
- void Mem_Free(Mem_Handle_t CurrAllocHdl);\r
- \r
- /** Returns the total number of unallocated blocks in the heap.\r
- *\r
- * \return Number of free blocks in the heap, as a Block_Number_t integer\r
- */\r
- Block_Number_t Mem_TotalFreeBlocks(void);\r
-\r
- /** Returns the total number of unallocated handles in the handle pool.\r
- *\r
- * \return Number of free handles in the handle pool, as a Handle_Number_t integer\r
- */\r
- Handle_Number_t Mem_TotalFreeHandles(void);\r
- \r
- /* Private Interface - For use in library only: */\r
- #if !defined(__DOXYGEN__)\r
- /* Macros: */\r
- #define BLOCK_USED_MASK (1 << 0)\r
- #define BLOCK_LINKED_MASK (1 << 1)\r
- \r
- /* Function Prototypes: */\r
- #if defined(INCLUDE_FROM_DYNALLOC_C)\r
- static uint8_t Mem_GetBlockFlags(const Block_Number_t BlockNum);\r
- static void Mem_SetBlockFlags(const Block_Number_t BlockNum, const uint8_t Flags);\r
- static void Mem_Defrag(void);\r
- #endif\r
- #endif\r
- \r
-#endif\r
-\r
-/** @} */\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-#include "Scheduler.h"\r
-\r
-volatile SchedulerDelayCounter_t Scheduler_TickCounter;\r
-volatile uint8_t Scheduler_TotalTasks;\r
-\r
-bool Scheduler_HasDelayElapsed(const uint16_t Delay, SchedulerDelayCounter_t* const DelayCounter)\r
-{\r
- SchedulerDelayCounter_t CurrentTickValue_LCL;\r
- SchedulerDelayCounter_t DelayCounter_LCL;\r
- \r
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\r
- {\r
- CurrentTickValue_LCL = Scheduler_TickCounter;\r
- }\r
- \r
- DelayCounter_LCL = *DelayCounter;\r
- \r
- if (CurrentTickValue_LCL >= DelayCounter_LCL)\r
- {\r
- if ((CurrentTickValue_LCL - DelayCounter_LCL) >= Delay)\r
- {\r
- *DelayCounter = CurrentTickValue_LCL;\r
- return true;\r
- }\r
- }\r
- else\r
- {\r
- if (((MAX_DELAYCTR_COUNT - DelayCounter_LCL) + CurrentTickValue_LCL) >= Delay)\r
- {\r
- *DelayCounter = CurrentTickValue_LCL;\r
- return true;\r
- } \r
- }\r
- \r
- return false;\r
-}\r
-\r
-void Scheduler_SetTaskMode(const TaskPtr_t Task, const bool TaskStatus)\r
-{\r
- TaskEntry_t* CurrTask = &Scheduler_TaskList[0];\r
- \r
- while (CurrTask != &Scheduler_TaskList[Scheduler_TotalTasks])\r
- {\r
- if (CurrTask->Task == Task)\r
- {\r
- CurrTask->TaskStatus = TaskStatus;\r
- break;\r
- }\r
- \r
- CurrTask++;\r
- }\r
-}\r
-\r
-void Scheduler_SetGroupTaskMode(const uint8_t GroupID, const bool TaskStatus)\r
-{\r
- TaskEntry_t* CurrTask = &Scheduler_TaskList[0];\r
- \r
- while (CurrTask != &Scheduler_TaskList[Scheduler_TotalTasks])\r
- {\r
- if (CurrTask->GroupID == GroupID)\r
- CurrTask->TaskStatus = TaskStatus;\r
- \r
- CurrTask++;\r
- }\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Simple round-robbin cooperative scheduler for use in basic projects where non real-time tasks need\r
- * to be executed. Each task is executed in sequence, and can be enabled or disabled individually or as a group.\r
- */\r
- \r
-/** @defgroup Group_Scheduler Simple Task Scheduler - LUFA/Scheduler/Scheduler.h\r
- *\r
- * \section Sec_Dependencies Module Source Dependencies\r
- * The following files must be built with any user project that uses this module:\r
- * - LUFA/Scheduler/Scheduler.c\r
- *\r
- * \section Module Description\r
- * Simple round-robbin cooperative scheduler for use in basic projects where non real-time tasks need\r
- * to be executed. Each task is executed in sequence, and can be enabled or disabled individually or as a group.\r
- *\r
- * For a task to yield it must return, thus each task should have persistent data marked with the static attribute.\r
- *\r
- * Usage Example:\r
- * \code\r
- * #include <LUFA/Scheduler/Scheduler.h>\r
- * \r
- * TASK(MyTask1);\r
- * TASK(MyTask2);\r
- * \r
- * TASK_LIST\r
- * {\r
- * { .Task = MyTask1, .TaskStatus = TASK_RUN, .GroupID = 1 },\r
- * { .Task = MyTask2, .TaskStatus = TASK_RUN, .GroupID = 1 },\r
- * }\r
- *\r
- * int main(void)\r
- * {\r
- * Scheduler_Start();\r
- * }\r
- *\r
- * TASK(MyTask1)\r
- * {\r
- * // Implementation Here\r
- * }\r
- *\r
- * TASK(MyTask2)\r
- * {\r
- * // Implementation Here\r
- * }\r
- * \endcode\r
- *\r
- * @{\r
- */\r
- \r
-#ifndef __SCHEDULER_H__\r
-#define __SCHEDULER_H__\r
-\r
- /* Includes: */\r
- #include <avr/io.h>\r
- #include <stdbool.h>\r
- \r
- #include <util/atomic.h>\r
-\r
- #include "../Common/Common.h"\r
-\r
- /* Enable C linkage for C++ Compilers: */\r
- #if defined(__cplusplus)\r
- extern "C" {\r
- #endif\r
-\r
- /* Public Interface - May be used in end-application: */\r
- /* Macros: */\r
- /** Creates a new scheduler task body or prototype. Should be used in the form:\r
- * \code\r
- * TASK(TaskName); // Prototype\r
- *\r
- * TASK(TaskName)\r
- * {\r
- * // Task body\r
- * }\r
- * \endcode\r
- */\r
- #define TASK(name) void name (void)\r
- \r
- /** Defines a task list array, containing one or more task entries of the type TaskEntry_t. Each task list\r
- * should be encased in curly braces and ended with a comma.\r
- *\r
- * Usage Example:\r
- * \code\r
- * TASK_LIST\r
- * {\r
- * { .Task = MyTask1, .TaskStatus = TASK_RUN, .GroupID = 1 },\r
- * // More task entries here\r
- * }\r
- * \endcode\r
- */\r
- #define TASK_LIST TaskEntry_t Scheduler_TaskList[] = \r
- \r
- /** Constant, giving the maximum delay in scheduler ticks which can be stored in a variable of type\r
- * SchedulerDelayCounter_t.\r
- */\r
- #define TASK_MAX_DELAY (MAX_DELAYCTR_COUNT - 1)\r
-\r
- /** Task status mode constant, for passing to Scheduler_SetTaskMode() or Scheduler_SetGroupTaskMode(). */\r
- #define TASK_RUN true\r
-\r
- /** Task status mode constant, for passing to Scheduler_SetTaskMode() or Scheduler_SetGroupTaskMode(). */\r
- #define TASK_STOP false\r
- \r
- /* Pseudo-Function Macros: */\r
- #if defined(__DOXYGEN__)\r
- /** Starts the scheduler in its infinite loop, executing running tasks. This should be placed at the end\r
- * of the user application's main() function, as it can never return to the calling function.\r
- */\r
- void Scheduler_Start(void);\r
- \r
- /** Initializes the scheduler so that the scheduler functions can be called before the scheduler itself\r
- * is started. This must be executed before any scheduler function calls other than Scheduler_Start(),\r
- * and can be omitted if no such functions could be called before the scheduler is started.\r
- */\r
- void Scheduler_Init(void);\r
- #else\r
- #define Scheduler_Start() Scheduler_GoSchedule(TOTAL_TASKS);\r
- \r
- #define Scheduler_Init() Scheduler_InitScheduler(TOTAL_TASKS);\r
- #endif\r
-\r
- /* Type Defines: */\r
- /** Type define for a pointer to a scheduler task. */\r
- typedef void (*TaskPtr_t)(void);\r
- \r
- /** Type define for a variable which can hold a tick delay value for the scheduler up to the maximum delay\r
- * possible.\r
- */\r
- typedef uint16_t SchedulerDelayCounter_t;\r
- \r
- /** Structure for holding a single task's information in the scheduler task list. */\r
- typedef struct\r
- {\r
- TaskPtr_t Task; /**< Pointer to the task to execute. */\r
- bool TaskStatus; /**< Status of the task (either TASK_RUN or TASK_STOP). */\r
- uint8_t GroupID; /**< Group ID of the task so that its status can be changed as a group. */\r
- } TaskEntry_t; \r
-\r
- /* Global Variables: */\r
- /** Task entry list, containing the scheduler tasks, task statuses and group IDs. Each entry is of type\r
- * TaskEntry_t and can be manipulated as desired, although it is preferential that the proper Scheduler\r
- * functions should be used instead of direct manipulation.\r
- */\r
- extern TaskEntry_t Scheduler_TaskList[];\r
- \r
- /** Contains the total number of tasks in the task list, irrespective of if the task's status is set to\r
- * TASK_RUN or TASK_STOP.\r
- *\r
- * \note This value should be treated as read-only, and never altered in user-code.\r
- */\r
- extern volatile uint8_t Scheduler_TotalTasks;\r
-\r
- /** Contains the current scheduler tick count, for use with the delay functions. If the delay functions\r
- * are used in the user code, this should be incremented each tick period so that the delays can be\r
- * calculated.\r
- */\r
- extern volatile SchedulerDelayCounter_t Scheduler_TickCounter;\r
-\r
- /* Inline Functions: */\r
- /** Resets the delay counter value to the current tick count. This should be called to reset the period\r
- * for a delay in a task which is dependant on the current tick value.\r
- *\r
- * \param DelayCounter Counter which is storing the starting tick count for a given delay.\r
- */\r
- static inline void Scheduler_ResetDelay(SchedulerDelayCounter_t* const DelayCounter)\r
- ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;\r
- static inline void Scheduler_ResetDelay(SchedulerDelayCounter_t* const DelayCounter)\r
- {\r
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\r
- {\r
- *DelayCounter = Scheduler_TickCounter;\r
- }\r
- }\r
- \r
- /* Function Prototypes: */\r
- /** Determines if the given tick delay has elapsed, based on the given .\r
- *\r
- * \param Delay The delay to test for, measured in ticks\r
- * \param DelayCounter The counter which is storing the starting tick value for the delay\r
- *\r
- * \return Boolean true if the delay has elapsed, false otherwise\r
- *\r
- * Usage Example:\r
- * \code\r
- * static SchedulerDelayCounter_t DelayCounter = 10000; // Force immediate run on start-up\r
- * \r
- * // Task runs every 10000 ticks, 10 seconds for this demo\r
- * if (Scheduler_HasDelayElapsed(10000, &DelayCounter))\r
- * {\r
- * // Code to execute after delay interval elapsed here\r
- * }\r
- * \endcode\r
- */\r
- bool Scheduler_HasDelayElapsed(const uint16_t Delay,\r
- SchedulerDelayCounter_t* const DelayCounter)\r
- ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(2);\r
- \r
- /** Sets the task mode for a given task.\r
- *\r
- * \param Task Name of the task whose status is to be changed\r
- * \param TaskStatus New task status for the task (TASK_RUN or TASK_STOP)\r
- */\r
- void Scheduler_SetTaskMode(const TaskPtr_t Task, const bool TaskStatus);\r
- \r
- /** Sets the task mode for a given task group ID, allowing for an entire group of tasks to have their\r
- * statuses changed at once.\r
- *\r
- * \param GroupID Value of the task group ID whose status is to be changed\r
- * \param TaskStatus New task status for tasks in the specified group (TASK_RUN or TASK_STOP)\r
- */\r
- void Scheduler_SetGroupTaskMode(const uint8_t GroupID, const bool TaskStatus);\r
-\r
- /* Private Interface - For use in library only: */ \r
- #if !defined(__DOXYGEN__)\r
- /* Macros: */\r
- #define TOTAL_TASKS (sizeof(Scheduler_TaskList) / sizeof(TaskEntry_t))\r
- #define MAX_DELAYCTR_COUNT 0xFFFF\r
-\r
- /* Inline Functions: */\r
- static inline void Scheduler_InitScheduler(const uint8_t TotalTasks) ATTR_ALWAYS_INLINE;\r
- static inline void Scheduler_InitScheduler(const uint8_t TotalTasks)\r
- {\r
- Scheduler_TotalTasks = TotalTasks;\r
- }\r
- \r
- static inline void Scheduler_GoSchedule(const uint8_t TotalTasks) ATTR_NO_RETURN ATTR_ALWAYS_INLINE;\r
- static inline void Scheduler_GoSchedule(const uint8_t TotalTasks)\r
- {\r
- Scheduler_InitScheduler(TotalTasks);\r
-\r
- for (;;)\r
- {\r
- TaskEntry_t* CurrTask = &Scheduler_TaskList[0];\r
- \r
- while (CurrTask != &Scheduler_TaskList[TotalTasks])\r
- {\r
- if (CurrTask->TaskStatus == TASK_RUN)\r
- CurrTask->Task();\r
-\r
- CurrTask++;\r
- }\r
- }\r
- }\r
- #endif\r
- \r
- /* Disable C linkage for C++ Compilers: */\r
- #if defined(__cplusplus)\r
- }\r
- #endif\r
- \r
-#endif\r
-\r
-/** @} */\r
+++ /dev/null
-/** \file\r
- *\r
- * This file contains special DoxyGen information for the generation of the main page and other special\r
- * documentation pages. It is not a project source file.\r
- */\r
-\r
-/** \page Page_SchedulerOverview LUFA Scheduler Overview\r
- *\r
- * The LUFA library comes with a small, basic round-robbin scheduler which allows for small "tasks" to be executed\r
- * continuously in sequence, and enabled/disabled at runtime. Unlike a conventional, complex RTOS scheduler, the\r
- * LUFA scheduler is very simple in design and operation and is essentially a loop conditionally executing a series\r
- * of functions.\r
- *\r
- * Each LUFA scheduler task should be written similar to an ISR; it should execute quickly (so that no one task\r
- * hogs the processor, preventing another from running before some sort of timeout is exceeded). Unlike normal RTOS\r
- * tasks, each LUFA scheduler task is a regular function, and thus must be designed to be called, and designed to\r
- * return to the calling scheduler function repeatedly. Data which must be preserved between task calls should be\r
- * declared as global or (preferably) as a static local variable inside the task.\r
- *\r
- * The scheduler consists of a task list, listing all the tasks which can be executed by the scheduler. Once started,\r
- * each task is then called one after another, unless the task is stopped by another running task or interrupt.\r
- *\r
- *\r
- * If desired, the LUFA scheduler <b>does not need to be used</b> in a LUFA powered application. A more conventional\r
- * approach to application design can be used, or a proper scheduling RTOS inserted in the place of the LUFA scheduler.\r
- * In the case of the former the USB task must be run manually repeatedly to maintain USB communications, and in the\r
- * case of the latter a proper RTOS task must be set up to do the same.\r
- *\r
- *\r
- * For more information on the LUFA scheduler, see the Scheduler.h file documentation.\r
- */\r
./Drivers/USB/LowLevel/LowLevel.c \\r
./Drivers/USB/LowLevel/Pipe.c \\r
./Drivers/USB/HighLevel/Events.c \\r
- ./Drivers/USB/HighLevel/StdDescriptors.c \\r
./Drivers/USB/HighLevel/USBInterrupt.c \\r
./Drivers/USB/HighLevel/USBTask.c \\r
- ./Drivers/USB/Class/ConfigDescriptor.c \\r
- ./Drivers/USB/Class/HIDParser.c \\r
- ./Scheduler/Scheduler.c \\r
- ./MemoryAllocator/DynAlloc.c \\r
+ ./Drivers/USB/HighLevel/ConfigDescriptor.c \\r
./Drivers/Board/Temperature.c \\r
./Drivers/Peripheral/Serial.c \\r
./Drivers/Peripheral/SerialStream.c \\r
\r
.HIDSpec = VERSION_BCD(01.11),\r
.CountryCode = 0x00,\r
- .TotalHIDDescriptors = 1,\r
+ .TotalReportDescriptors = 1,\r
.HIDReportType = DTYPE_Report,\r
.HIDReportLength = sizeof(KeyboardReport)\r
},\r
#define _DESCRIPTORS_H_\r
\r
/* Includes: */\r
- #include <LUFA/Drivers/USB/USB.h>\r
-\r
#include <avr/pgmspace.h>\r
\r
- /* Type Defines: */\r
- /** Type define for the HID class specific HID descriptor. A HID descriptor is used in HID class devices\r
- * to give information about the HID device, including the HID specification used, and the report descriptors\r
- * the device contains to describe how the HID device should be controlled.\r
- */\r
- typedef struct\r
- {\r
- USB_Descriptor_Header_t Header; /**< Standard USB descriptor header */\r
- \r
- uint16_t HIDSpec; /**< HID specification implemented by the device, in BCD form */\r
- uint8_t CountryCode; /**< Country code for the country the HID device is localised for */\r
- \r
- uint8_t TotalHIDDescriptors; /**< Total number of HID reports linked to this HID interface */\r
-\r
- uint8_t HIDReportType; /**< Type of the first HID report descriptor */\r
- uint16_t HIDReportLength; /**< Length of the first HID report descriptor */\r
- } USB_Descriptor_HID_t;\r
-\r
- /** Type define for the data type used for the HID Report descriptor data elements. A HID report\r
- * descriptor contains an array of this data type, indicating how the reports from and to the\r
- * device are formatted and how the report data is to be used by the host.\r
- */\r
- typedef uint8_t USB_Descriptor_HIDReport_Datatype_t;\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>\r
\r
+ /* Type Defines: */\r
/** Type define for the device configuration descriptor structure. This must be defined in the\r
* application code, as the configuration descriptor contains several sub-descriptors which\r
* vary between devices, and which describe the device's usage to the host.\r
/** Size of the keyboard report endpoints, in bytes. */\r
#define KEYBOARD_EPSIZE 8\r
\r
- /** Descriptor type value for a HID descriptor. */\r
- #define DTYPE_HID 0x21\r
-\r
- /** Descriptor type value for a HID report. */\r
- #define DTYPE_Report 0x22\r
-\r
/* Function Prototypes: */\r
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)\r
- ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);\r
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);\r
\r
#endif\r
arising out of or in connection with the use or performance of\r
this software.\r
*/\r
-\r
-/** \file\r
- *\r
- * Main source file for the MagStripe application. This file contains the code which drives\r
- * the USB keyboard interface from the magnetic card stripe reader device.\r
- */\r
\r
#include "Magstripe.h"\r
\r
-/* Scheduler Task List */\r
-TASK_LIST\r
-{\r
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },\r
- { .Task = USB_Keyboard_Report , .TaskStatus = TASK_STOP },\r
- { .Task = Magstripe_Read , .TaskStatus = TASK_STOP },\r
-};\r
-\r
-/* Global Variables */\r
-/** Indicates if the device is using Report Protocol mode, instead of Boot Protocol mode. Boot Protocol mode\r
- * is a special reporting mode used by compatible PC BIOS to support USB keyboards before a full OS and USB\r
- * driver has been loaded, by using predefined report structures indicated in the USB HID standard.\r
- */\r
-bool UsingReportProtocol = true;\r
+BitBuffer_t TrackDataBuffers[3];\r
\r
-/** Total idle period in milliseconds set by the host via a SetIdle request, used to silence the report endpoint\r
- * until the report data changes or the idle period elapsed. Generally used to implement hardware key repeats, or\r
- * by some BIOS to reduce the number of reports when in Boot Protocol mode.\r
- */\r
-uint8_t IdleCount = 0;\r
-\r
-/** Milliseconds remaining counter for the HID class SetIdle and GetIdle requests, used to silence the report\r
- * endpoint for an amount of time indicated by the host or until the report changes.\r
- */\r
-uint16_t IdleMSRemaining = 0;\r
-\r
-/** Circular buffer to hold the read bits from track 1 of the inserted magnetic card. */\r
-BitBuffer_t Track1Data;\r
+USB_ClassInfo_HID_t Keyboard_HID_Interface =\r
+ {\r
+ .InterfaceNumber = 0,\r
\r
-/** Circular buffer to hold the read bits from track 2 of the inserted magnetic card. */\r
-BitBuffer_t Track2Data;\r
+ .ReportINEndpointNumber = KEYBOARD_EPNUM,\r
+ .ReportINEndpointSize = KEYBOARD_EPSIZE,\r
+ };\r
\r
-/** Circular buffer to hold the read bits from track 3 of the inserted magnetic card. */\r
-BitBuffer_t Track3Data;\r
+int main(void)\r
+{\r
+ SetupHardware();\r
+ \r
+ for (uint8_t Buffer = 0; Buffer < 3; Buffer++)\r
+ BitBuffer_Init(&TrackDataBuffers[Buffer]);\r
\r
-/** Delay counter between successive key strokes. This is to prevent the OS from ignoring multiple keys in a short\r
- * period of time due to key repeats. Two milliseconds works for most OSes.\r
- */\r
-uint8_t KeyDelayRemaining;\r
+ for (;;)\r
+ {\r
+ if (Magstripe_GetStatus() & MAG_CARDPRESENT)\r
+ ReadMagstripeData();\r
\r
+ USB_HID_USBTask(&Keyboard_HID_Interface);\r
+ USB_USBTask();\r
+ }\r
+}\r
\r
-/** Main program entry point. This routine configures the hardware required by the application, then\r
- * starts the scheduler to run the application tasks.\r
- */\r
-int main(void)\r
+void SetupHardware(void)\r
{\r
/* Disable watchdog if enabled by bootloader/fuses */\r
MCUSR &= ~(1 << WDRF);\r
\r
/* Hardware Initialization */\r
Magstripe_Init();\r
- \r
- /* Buffer Initialization */\r
- BitBuffer_Init(&Track1Data);\r
- BitBuffer_Init(&Track2Data);\r
- BitBuffer_Init(&Track3Data);\r
- \r
- /* Millisecond timer initialization, with output compare interrupt enabled for the idle timing */\r
- OCR0A = 0xFA;\r
- TCCR0A = (1 << WGM01);\r
- TCCR0B = ((1 << CS01) | (1 << CS00));\r
- TIMSK0 = (1 << OCIE0A);\r
- \r
- /* Initialize Scheduler so that it can be used */\r
- Scheduler_Init();\r
-\r
- /* Initialize USB Subsystem */\r
USB_Init();\r
- \r
- /* Scheduling - routine never returns, so put this last in the main function */\r
- Scheduler_Start();\r
}\r
\r
-/** Event handler for the USB_Connect event. This starts the USB task. */\r
-void EVENT_USB_Connect(void)\r
+void ReadMagstripeData(void)\r
{\r
- /* Start USB management task */\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);\r
-}\r
+ /* Arrays to hold the buffer pointers, clock and data bit masks for the separate card tracks */\r
+ const struct\r
+ {\r
+ uint8_t ClockMask;\r
+ uint8_t DataMask; \r
+ } TrackInfo[] = {{MAG_T1_CLOCK, MAG_T1_DATA},\r
+ {MAG_T2_CLOCK, MAG_T2_DATA},\r
+ {MAG_T3_CLOCK, MAG_T3_DATA}};\r
\r
-/** Event handler for the USB_Disconnect event. This stops the USB and keyboard report tasks. */\r
-void EVENT_USB_Disconnect(void)\r
-{\r
- /* Stop running keyboard reporting, card reading and USB management tasks */\r
- Scheduler_SetTaskMode(USB_Keyboard_Report, TASK_STOP);\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);\r
- Scheduler_SetTaskMode(Magstripe_Read, TASK_STOP);\r
+ uint8_t Magstripe_Prev = 0;\r
+ uint8_t Magstripe_LCL = Magstripe_GetStatus();\r
+\r
+ while (Magstripe_LCL & MAG_CARDPRESENT)\r
+ {\r
+ for (uint8_t Track = 0; Track < 3; Track++)\r
+ {\r
+ bool DataPinLevel = ((Magstripe_LCL & TrackInfo[Track].DataMask) != 0);\r
+ bool ClockPinLevel = ((Magstripe_LCL & TrackInfo[Track].ClockMask) != 0);\r
+ bool ClockLevelChanged = (((Magstripe_LCL ^ Magstripe_Prev) & TrackInfo[Track].ClockMask) != 0);\r
+ \r
+ if (ClockPinLevel && ClockLevelChanged)\r
+ BitBuffer_StoreNextBit(&TrackDataBuffers[Track], DataPinLevel);\r
+ }\r
+\r
+ Magstripe_Prev = Magstripe_LCL;\r
+ Magstripe_LCL = Magstripe_GetStatus();\r
+ }\r
}\r
\r
-/** Event handler for the USB_ConfigurationChanged event. This configures the device's endpoints ready\r
- * to relay reports to the host, and starts the keyboard report task.\r
- */\r
void EVENT_USB_ConfigurationChanged(void)\r
{\r
- /* Setup Keyboard Keycode Report Endpoint */\r
- Endpoint_ConfigureEndpoint(KEYBOARD_EPNUM, EP_TYPE_INTERRUPT,\r
- ENDPOINT_DIR_IN, KEYBOARD_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
- \r
- /* Default to report protocol on connect */\r
- UsingReportProtocol = true;\r
-\r
- /* Start Keyboard reporting and card reading tasks */\r
- Scheduler_SetTaskMode(USB_Keyboard_Report, TASK_RUN);\r
- Scheduler_SetTaskMode(Magstripe_Read, TASK_RUN);\r
+ USB_HID_ConfigureEndpoints(&Keyboard_HID_Interface);\r
}\r
\r
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific\r
- * control requests that are not handled internally by the USB library, so that they can be handled appropriately\r
- * for the application.\r
- */\r
void EVENT_USB_UnhandledControlPacket(void)\r
{\r
- /* Handle HID Class specific requests */\r
- switch (USB_ControlRequest.bRequest)\r
- {\r
- case REQ_GetReport:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- USB_KeyboardReport_Data_t KeyboardReportData;\r
-\r
- /* Create the next keyboard report for transmission to the host */\r
- GetNextReport(&KeyboardReportData);\r
-\r
- Endpoint_ClearSETUP();\r
- \r
- /* Write the report data to the control endpoint */\r
- Endpoint_Write_Control_Stream_LE(&KeyboardReportData, sizeof(KeyboardReportData));\r
- \r
- /* Finalize the stream transfer to send the last packet or clear the host abort */\r
- Endpoint_ClearOUT();\r
- }\r
- \r
- break;\r
- case REQ_GetProtocol:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- Endpoint_ClearSETUP();\r
- \r
- /* Write the current protocol flag to the host */\r
- Endpoint_Write_Byte(UsingReportProtocol);\r
- \r
- /* Send the flag to the host */\r
- Endpoint_ClearIN();\r
-\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
- }\r
- \r
- break;\r
- case REQ_SetProtocol:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- Endpoint_ClearSETUP();\r
-\r
- /* Set or clear the flag depending on what the host indicates that the current Protocol should be */\r
- UsingReportProtocol = (USB_ControlRequest.wValue != 0x0000);\r
- \r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
- }\r
- \r
- break;\r
- case REQ_SetIdle:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- Endpoint_ClearSETUP();\r
- \r
- /* Get idle period in MSB */\r
- IdleCount = (USB_ControlRequest.wValue >> 8);\r
- \r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
- }\r
- \r
- break;\r
- case REQ_GetIdle:\r
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
- { \r
- Endpoint_ClearSETUP();\r
- \r
- /* Write the current idle duration to the host */\r
- Endpoint_Write_Byte(IdleCount);\r
- \r
- /* Send the flag to the host */\r
- Endpoint_ClearIN();\r
-\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
- }\r
-\r
- break;\r
- }\r
+ USB_HID_ProcessControlPacket(&Keyboard_HID_Interface);\r
}\r
\r
-/** ISR for the timer 0 compare vector. This ISR fires once each millisecond, and decrements the counter indicating\r
- * the number of milliseconds left to idle (not send the host reports) if the device has been instructed to idle\r
- * by the host via a SetIdle class specific request.\r
- */\r
-ISR(TIMER0_COMPA_vect, ISR_BLOCK)\r
+void EVENT_USB_StartOfFrame(void)\r
{\r
- /* One millisecond has elapsed, decrement the idle time remaining counter if it has not already elapsed */\r
- if (IdleMSRemaining)\r
- IdleMSRemaining--;\r
- \r
- if (KeyDelayRemaining)\r
- KeyDelayRemaining--;\r
+ USB_HID_RegisterStartOfFrame(&Keyboard_HID_Interface);\r
}\r
\r
-/** Constructs a keyboard report indicating the currently pressed keyboard keys to the host.\r
- *\r
- * \param ReportData Pointer to a USB_KeyboardReport_Data_t report structure where the resulting report should\r
- * be stored\r
- *\r
- * \return Boolean true if the current report is different to the previous report, false otherwise\r
- */\r
-bool GetNextReport(USB_KeyboardReport_Data_t* ReportData)\r
+uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData)\r
{\r
- static bool OddReport = false;\r
- static bool MustRelease = false;\r
- \r
- BitBuffer_t* Buffer = NULL;\r
-\r
- /* Clear the report contents */\r
- memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));\r
+ static bool IsKeyReleaseReport;\r
+ static bool IsNewlineReport;\r
\r
- /* Get the next non-empty track data buffer */\r
- if (Track1Data.Elements)\r
- Buffer = &Track1Data;\r
- else if (Track2Data.Elements)\r
- Buffer = &Track2Data; \r
- else if (Track3Data.Elements)\r
- Buffer = &Track3Data;\r
-\r
- if (Buffer != NULL)\r
- {\r
- /* Toggle the odd report number indicator */\r
- OddReport = !OddReport;\r
+ BitBuffer_t* Buffer = NULL;\r
+ USB_KeyboardReport_Data_t* KeyboardReport = (USB_KeyboardReport_Data_t*)ReportData;\r
\r
- /* Set the flag indicating that a null report must eventually be sent to release all pressed keys */\r
- MustRelease = true;\r
-\r
- /* Only send the next key on odd reports, so that they are interspersed with null reports to release keys */\r
- if (OddReport)\r
- {\r
- /* Set the report key code to the key code for the next data bit */\r
- ReportData->KeyCode = BitBuffer_GetNextBit(Buffer) ? KEY_1 : KEY_0;\r
- \r
- /* If buffer is now empty, a new line must be sent instead of the terminating bit */\r
- if (!(Buffer->Elements))\r
- {\r
- /* Set the keycode to the code for an enter key press */\r
- ReportData->KeyCode = KEY_ENTER; \r
- }\r
- }\r
+ /* Key reports must be interleaved with 0 Key Code reports to release the keys, or repeated keys will be ignored */\r
+ IsKeyReleaseReport = !IsKeyReleaseReport; \r
\r
- return true;\r
- }\r
- else if (MustRelease)\r
+ if (IsKeyReleaseReport)\r
{\r
- /* Leave key code to null (0), to release all pressed keys */\r
- return true;\r
+ KeyboardReport->KeyCode = 0;\r
}\r
- \r
- return false;\r
-}\r
-\r
-/** Task to read out data from inserted magnetic cards and place the separate track data into their respective\r
- * data buffers for later sending to the host as keyboard key presses.\r
- */\r
-TASK(Magstripe_Read)\r
-{\r
- /* Arrays to hold the buffer pointers, clock and data bit masks for the separate card tracks */\r
- const struct\r
+ else if (IsNewlineReport)\r
{\r
- BitBuffer_t* Buffer;\r
- uint8_t ClockMask;\r
- uint8_t DataMask; \r
- } TrackInfo[] = {{&Track1Data, MAG_T1_CLOCK, MAG_T1_DATA},\r
- {&Track2Data, MAG_T2_CLOCK, MAG_T2_DATA},\r
- {&Track3Data, MAG_T3_CLOCK, MAG_T3_DATA}};\r
-\r
- /* Previous magnetic card control line' status, for later comparison */\r
- uint8_t Magstripe_Prev = 0;\r
- \r
- /* Buffered current card reader control line' status */\r
- uint8_t Magstripe_LCL = Magstripe_GetStatus();\r
-\r
- /* Exit the task early if no card is present in the reader */\r
- if (!(Magstripe_LCL & MAG_CARDPRESENT))\r
- return;\r
-\r
- /* Read out card data while a card is present */\r
- while (Magstripe_LCL & MAG_CARDPRESENT)\r
+ IsNewlineReport = false;\r
+ KeyboardReport->KeyCode = KEY_ENTER;\r
+ }\r
+ else\r
{\r
- /* Read out the next bit for each track of the card */\r
- for (uint8_t Track = 0; Track < 3; Track++)\r
- {\r
- /* Current data line status for the current card track */\r
- bool DataLevel = ((Magstripe_LCL & TrackInfo[Track].DataMask) != 0);\r
-\r
- /* Current clock line status for the current card track */\r
- bool ClockLevel = ((Magstripe_LCL & TrackInfo[Track].ClockMask) != 0);\r
-\r
- /* Current track clock transition check */\r
- bool ClockChanged = (((Magstripe_LCL ^ Magstripe_Prev) & TrackInfo[Track].ClockMask) != 0);\r
- \r
- /* Sample the next bit on the falling edge of the track's clock line, store key code into the track's buffer */\r
- if (ClockLevel && ClockChanged)\r
- BitBuffer_StoreNextBit(TrackInfo[Track].Buffer, DataLevel);\r
- }\r
-\r
- /* Retain the current card reader control line states for later edge detection */\r
- Magstripe_Prev = Magstripe_LCL;\r
+ if (TrackDataBuffers[0].Elements)\r
+ Buffer = &TrackDataBuffers[0];\r
+ else if (TrackDataBuffers[1].Elements)\r
+ Buffer = &TrackDataBuffers[1]; \r
+ else if (TrackDataBuffers[2].Elements)\r
+ Buffer = &TrackDataBuffers[2];\r
+ else\r
+ return 0;\r
+\r
+ KeyboardReport->KeyCode = BitBuffer_GetNextBit(Buffer) ? KEY_1 : KEY_0;\r
\r
- /* Retrieve the new card reader control line states */\r
- Magstripe_LCL = Magstripe_GetStatus();\r
+ /* If buffer now empty, next report must be a newline to seperate track data */\r
+ if (!(Buffer->Elements))\r
+ IsNewlineReport = true;\r
}\r
\r
- /* Add terminators to the end of each track buffer */\r
- BitBuffer_StoreNextBit(&Track1Data, 0);\r
- BitBuffer_StoreNextBit(&Track2Data, 0);\r
- BitBuffer_StoreNextBit(&Track3Data, 0);\r
+ return sizeof(USB_KeyboardReport_Data_t);\r
}\r
\r
-/** Task for the magnetic card reading and keyboard report generation. This task waits until a card is inserted,\r
- * then reads off the card data and sends it to the host as a series of keyboard key presses via keyboard reports.\r
- */\r
-TASK(USB_Keyboard_Report)\r
+void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize)\r
{\r
- USB_KeyboardReport_Data_t KeyboardReportData;\r
- bool SendReport = false;\r
- \r
- /* Check if the USB system is connected to a host */\r
- if (USB_IsConnected)\r
- {\r
- /* Select the Keyboard Report Endpoint */\r
- Endpoint_SelectEndpoint(KEYBOARD_EPNUM);\r
-\r
- /* Check if Keyboard Endpoint Ready for Read/Write */\r
- if (Endpoint_IsReadWriteAllowed())\r
- {\r
- /* Only fetch the next key to send once the period between key presses has elapsed */\r
- if (!(KeyDelayRemaining))\r
- {\r
- /* Create the next keyboard report for transmission to the host */\r
- SendReport = GetNextReport(&KeyboardReportData);\r
- }\r
- \r
- /* Check if the idle period is set and has elapsed */\r
- if (IdleCount && !(IdleMSRemaining))\r
- {\r
- /* Idle period elapsed, indicate that a report must be sent */\r
- SendReport = true;\r
- \r
- /* Reset the idle time remaining counter, must multiply by 4 to get the duration in milliseconds */\r
- IdleMSRemaining = (IdleCount << 2);\r
- }\r
-\r
- /* Write the keyboard report if a report is to be sent to the host */\r
- if (SendReport)\r
- {\r
- /* Write Keyboard Report Data */\r
- Endpoint_Write_Stream_LE(&KeyboardReportData, sizeof(USB_KeyboardReport_Data_t));\r
-\r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearIN();\r
-\r
- /* Reset the key delay period counter */\r
- KeyDelayRemaining = 2;\r
- }\r
- }\r
- }\r
+ // Unused (but mandatory for the HID class driver) in this demo, since there are no Host->Device reports\r
}\r
/* Includes: */\r
#include <avr/io.h>\r
#include <avr/wdt.h>\r
- #include <avr/interrupt.h>\r
#include <avr/power.h>\r
- #include <stdbool.h>\r
- #include <string.h>\r
\r
#include "Descriptors.h"\r
-\r
#include "Lib/MagstripeHW.h"\r
#include "Lib/CircularBitBuffer.h"\r
\r
- #include <LUFA/Version.h> // Library Version Information\r
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management\r
-\r
- \r
- /* Task Definitions: */\r
- /** Task definition for the keyboard and magnetic card reading task. */\r
- TASK(USB_Keyboard_Report);\r
- \r
- TASK(Magstripe_Read);\r
+ #include <LUFA/Version.h>\r
+ #include <LUFA/Drivers/USB/USB.h>\r
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>\r
\r
/* Macros: */\r
- /** HID Class Specific Request to get the current HID report from the device. */\r
- #define REQ_GetReport 0x01\r
-\r
- /** HID Class Specific Request to get the current device idle count. */\r
- #define REQ_GetIdle 0x02\r
-\r
- /** HID Class Specific Request to set the current HID report to the device. */\r
- #define REQ_SetReport 0x09\r
-\r
- /** HID Class Specific Request to set the device's idle count. */\r
- #define REQ_SetIdle 0x0A\r
-\r
- /** HID Class Specific Request to get the current HID report protocol mode. */\r
- #define REQ_GetProtocol 0x03\r
-\r
- /** HID Class Specific Request to set the current HID report protocol mode. */\r
- #define REQ_SetProtocol 0x0B\r
- \r
/** HID keyboard keycode to indicate that the "1" key is currently pressed. */\r
#define KEY_1 30\r
\r
} USB_KeyboardReport_Data_t;\r
\r
/* Function Prototypes: */\r
- void EVENT_USB_Connect(void);\r
- void EVENT_USB_Disconnect(void);\r
+ void SetupHardware(void);\r
+ void ReadMagstripeData(void);\r
+ \r
void EVENT_USB_ConfigurationChanged(void);\r
void EVENT_USB_UnhandledControlPacket(void);\r
- \r
- bool GetNextReport(USB_KeyboardReport_Data_t* ReportData);\r
+ void EVENT_USB_StartOfFrame(void);\r
+\r
+ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);\r
+ void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo,\r
+ void* ReportData, uint16_t ReportSize);\r
\r
#endif\r
SRC = $(TARGET).c \
Descriptors.c \
Lib/CircularBitBuffer.c \
- $(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Endpoint.c \
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Host.c \
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \
- $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \
+ $(LUFA_PATH)/LUFA/Drivers/USB/Class/Device/HID.c \
# List C++ source files here. (C dependencies are automatically generated.)