aboutsummaryrefslogtreecommitdiffstats
path: root/Demos/Device
diff options
context:
space:
mode:
authorDean Camera <dean@fourwalledcubicle.com>2009-06-01 11:03:39 +0000
committerDean Camera <dean@fourwalledcubicle.com>2009-06-01 11:03:39 +0000
commitd1e52660368d34d693131f6aff3c8fd8584162e5 (patch)
tree333916f85f9fd38a80b0785478aa596f11f166b6 /Demos/Device
parent2440ca268ac444c1aed2441cefe9e25a767d961a (diff)
downloadlufa-d1e52660368d34d693131f6aff3c8fd8584162e5.tar.gz
lufa-d1e52660368d34d693131f6aff3c8fd8584162e5.tar.bz2
lufa-d1e52660368d34d693131f6aff3c8fd8584162e5.zip
Commit of new class abstraction APIs for all device demos other than the MIDI demo - not documented yet.
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.
Diffstat (limited to 'Demos/Device')
-rw-r--r--Demos/Device/AudioInput/AudioInput.c188
-rw-r--r--Demos/Device/AudioInput/AudioInput.h36
-rw-r--r--Demos/Device/AudioInput/makefile3
-rw-r--r--Demos/Device/AudioOutput/AudioOutput.c277
-rw-r--r--Demos/Device/AudioOutput/AudioOutput.h33
-rw-r--r--Demos/Device/AudioOutput/makefile5
-rw-r--r--Demos/Device/CDC/CDC.c317
-rw-r--r--Demos/Device/CDC/CDC.h139
-rw-r--r--Demos/Device/CDC/Descriptors.h22
-rw-r--r--Demos/Device/CDC/makefile5
-rw-r--r--Demos/Device/DualCDC/Descriptors.h20
-rw-r--r--Demos/Device/DualCDC/DualCDC.c370
-rw-r--r--Demos/Device/DualCDC/DualCDC.h75
-rw-r--r--Demos/Device/DualCDC/makefile5
-rw-r--r--Demos/Device/GenericHID/Descriptors.h32
-rw-r--r--Demos/Device/GenericHID/GenericHID.c243
-rw-r--r--Demos/Device/GenericHID/GenericHID.h40
-rw-r--r--Demos/Device/GenericHID/makefile5
-rw-r--r--Demos/Device/Joystick/Descriptors.h30
-rw-r--r--Demos/Device/Joystick/Joystick.c211
-rw-r--r--Demos/Device/Joystick/Joystick.h40
-rw-r--r--Demos/Device/Joystick/makefile5
-rw-r--r--Demos/Device/Keyboard/Descriptors.h30
-rw-r--r--Demos/Device/Keyboard/Keyboard.c437
-rw-r--r--Demos/Device/Keyboard/Keyboard.h60
-rw-r--r--Demos/Device/Keyboard/makefile5
-rw-r--r--Demos/Device/KeyboardMouse/Descriptors.h30
-rw-r--r--Demos/Device/KeyboardMouse/KeyboardMouse.c353
-rw-r--r--Demos/Device/KeyboardMouse/KeyboardMouse.h47
-rw-r--r--Demos/Device/KeyboardMouse/makefile5
-rw-r--r--Demos/Device/MIDI/makefile2
-rw-r--r--Demos/Device/MassStorage/Lib/DataflashManager.c18
-rw-r--r--Demos/Device/MassStorage/Lib/DataflashManager.h4
-rw-r--r--Demos/Device/MassStorage/Lib/SCSI.c116
-rw-r--r--Demos/Device/MassStorage/Lib/SCSI.h25
-rw-r--r--Demos/Device/MassStorage/MassStorage.c331
-rw-r--r--Demos/Device/MassStorage/MassStorage.h103
-rw-r--r--Demos/Device/MassStorage/makefile4
-rw-r--r--Demos/Device/Mouse/Descriptors.h30
-rw-r--r--Demos/Device/Mouse/Mouse.c309
-rw-r--r--Demos/Device/Mouse/Mouse.h58
-rw-r--r--Demos/Device/Mouse/makefile5
-rw-r--r--Demos/Device/RNDISEthernet/Lib/ARP.h4
-rw-r--r--Demos/Device/RNDISEthernet/Lib/Ethernet.c32
-rw-r--r--Demos/Device/RNDISEthernet/Lib/Ethernet.h24
-rw-r--r--Demos/Device/RNDISEthernet/Lib/EthernetProtocols.h8
-rw-r--r--Demos/Device/RNDISEthernet/Lib/ICMP.c4
-rw-r--r--Demos/Device/RNDISEthernet/Lib/ICMP.h2
-rw-r--r--Demos/Device/RNDISEthernet/Lib/IP.c5
-rw-r--r--Demos/Device/RNDISEthernet/Lib/IP.h2
-rw-r--r--Demos/Device/RNDISEthernet/Lib/RNDIS.c394
-rw-r--r--Demos/Device/RNDISEthernet/Lib/RNDIS.h226
-rw-r--r--Demos/Device/RNDISEthernet/Lib/RNDISConstants.h99
-rw-r--r--Demos/Device/RNDISEthernet/Lib/TCP.c22
-rw-r--r--Demos/Device/RNDISEthernet/Lib/TCP.h8
-rw-r--r--Demos/Device/RNDISEthernet/RNDISEthernet.c322
-rw-r--r--Demos/Device/RNDISEthernet/RNDISEthernet.h56
-rw-r--r--Demos/Device/RNDISEthernet/makefile6
-rw-r--r--Demos/Device/USBtoSerial/Descriptors.h20
-rw-r--r--Demos/Device/USBtoSerial/USBtoSerial.c346
-rw-r--r--Demos/Device/USBtoSerial/USBtoSerial.h142
-rw-r--r--Demos/Device/USBtoSerial/makefile5
62 files changed, 1084 insertions, 4716 deletions
diff --git a/Demos/Device/AudioInput/AudioInput.c b/Demos/Device/AudioInput/AudioInput.c
index ecd8cdda8..bcfb04be1 100644
--- a/Demos/Device/AudioInput/AudioInput.c
+++ b/Demos/Device/AudioInput/AudioInput.c
@@ -28,26 +28,32 @@
this software.
*/
-/** \file
- *
- * Main source file for the Audio Input demo. This file contains the main tasks of the demo and
- * is responsible for the initial application hardware configuration.
- */
-
#include "AudioInput.h"
-/* Scheduler Task List */
-TASK_LIST
+USB_ClassInfo_Audio_t Microphone_Audio_Interface =
+ {
+ .InterfaceNumber = 0,
+
+ .DataINEndpointNumber = AUDIO_STREAM_EPNUM,
+ .DataINEndpointSize = AUDIO_STREAM_EPSIZE,
+ };
+
+int main(void)
{
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },
- { .Task = USB_Audio_Task , .TaskStatus = TASK_STOP },
-};
+ SetupHardware();
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+
+ for (;;)
+ {
+ if (Microphone_Audio_Interface.InterfaceEnabled)
+ ProcessNextSample();
-/** Main program entry point. This routine configures the hardware required by the application, then
- * starts the scheduler to run the application tasks.
- */
-int main(void)
+ USB_USBTask();
+ }
+}
+
+void SetupHardware(void)
{
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
@@ -58,35 +64,35 @@ int main(void)
/* Hardware Initialization */
LEDs_Init();
+ USB_Init();
ADC_Init(ADC_FREE_RUNNING | ADC_PRESCALE_32);
ADC_SetupChannel(MIC_IN_ADC_CHANNEL);
/* Start the ADC conversion in free running mode */
ADC_StartReading(ADC_REFERENCE_AVCC | ADC_RIGHT_ADJUSTED | MIC_IN_ADC_CHANNEL);
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
-
- /* Initialize Scheduler so that it can be used */
- Scheduler_Init();
+}
- /* Initialize USB Subsystem */
- USB_Init();
+void ProcessNextSample(void)
+{
+ if ((TIFR0 & (1 << OCF0A)) && USB_Audio_IsReadyForNextSample(&Microphone_Audio_Interface))
+ {
+ TIFR0 |= (1 << OCF0A);
+
+ /* Audio sample is ADC value scaled to fit the entire range */
+ int16_t AudioSample = ((SAMPLE_MAX_RANGE / ADC_MAX_RANGE) * ADC_GetResult());
+
+#if defined(MICROPHONE_BIASED_TO_HALF_RAIL)
+ /* Microphone is biased to half rail voltage, subtract the bias from the sample value */
+ AudioSample -= (SAMPLE_MAX_RANGE / 2));
+#endif
- /* Scheduling - routine never returns, so put this last in the main function */
- Scheduler_Start();
+ USB_Audio_WriteSample16(AudioSample);
+ }
}
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs, and
- * configures the sample update and PWM timers.
- */
void EVENT_USB_Connect(void)
{
- /* Start USB management task */
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);
-
- /* Indicate USB enumerating */
- UpdateStatus(Status_USBEnumerating);
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
/* Sample reload timer initialization */
OCR0A = (F_CPU / AUDIO_SAMPLE_FREQUENCY) - 1;
@@ -94,127 +100,23 @@ void EVENT_USB_Connect(void)
TCCR0B = (1 << CS00); // Fcpu speed
}
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
- * the status LEDs, disables the sample update and PWM output timers and stops the USB and Audio management tasks.
- */
void EVENT_USB_Disconnect(void)
{
/* Stop the sample reload timer */
TCCR0B = 0;
- /* Stop running audio and USB management tasks */
- Scheduler_SetTaskMode(USB_Audio_Task, TASK_STOP);
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
}
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
- * of the USB device after enumeration - the device endpoints are configured.
- */
void EVENT_USB_ConfigurationChanged(void)
{
- /* Setup audio stream endpoint */
- Endpoint_ConfigureEndpoint(AUDIO_STREAM_EPNUM, EP_TYPE_ISOCHRONOUS,
- ENDPOINT_DIR_IN, AUDIO_STREAM_EPSIZE,
- ENDPOINT_BANK_DOUBLE);
-
- /* Indicate USB connected and ready */
- UpdateStatus(Status_USBReady);
-}
-
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
- * control requests that are not handled internally by the USB library (including the Audio class-specific
- * requests) so that they can be handled appropriately for the application.
- */
-void EVENT_USB_UnhandledControlPacket(void)
-{
- /* Process General and Audio specific control requests */
- switch (USB_ControlRequest.bRequest)
- {
- case REQ_SetInterface:
- /* Set Interface is not handled by the library, as its function is application-specific */
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Check if the host is enabling the audio interface (setting AlternateSetting to 1) */
- if (USB_ControlRequest.wValue)
- {
- /* Start audio task */
- Scheduler_SetTaskMode(USB_Audio_Task, TASK_RUN);
- }
- else
- {
- /* Stop audio task */
- Scheduler_SetTaskMode(USB_Audio_Task, TASK_STOP);
- }
-
- /* Acknowledge status stage */
- while (!(Endpoint_IsINReady()));
- Endpoint_ClearIN();
- }
-
- break;
- }
-}
-
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to
- * log to a serial port, or anything else that is suitable for status updates.
- *
- * \param CurrentStatus Current status of the system, from the AudioInput_StatusCodes_t enum
- */
-void UpdateStatus(uint8_t CurrentStatus)
-{
- uint8_t LEDMask = LEDS_NO_LEDS;
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);
- /* Set the LED mask to the appropriate LED mask based on the given status code */
- switch (CurrentStatus)
- {
- case Status_USBNotReady:
- LEDMask = (LEDS_LED1);
- break;
- case Status_USBEnumerating:
- LEDMask = (LEDS_LED1 | LEDS_LED2);
- break;
- case Status_USBReady:
- LEDMask = (LEDS_LED2 | LEDS_LED4);
- break;
- }
-
- /* Set the board LEDs to the new LED mask */
- LEDs_SetAllLEDs(LEDMask);
+ if (!(USB_Audio_ConfigureEndpoints(&Microphone_Audio_Interface)))
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}
-/** Task to manage the Audio interface, reading in ADC samples from the microphone, and them to the host. */
-TASK(USB_Audio_Task)
+void EVENT_USB_UnhandledControlPacket(void)
{
- /* Select the audio stream endpoint */
- Endpoint_SelectEndpoint(AUDIO_STREAM_EPNUM);
-
- /* Check if the current endpoint can be written to and that the next sample should be stored */
- if (Endpoint_IsINReady() && (TIFR0 & (1 << OCF0A)))
- {
- /* Clear the sample reload timer */
- TIFR0 |= (1 << OCF0A);
-
- /* Audio sample is ADC value scaled to fit the entire range */
- int16_t AudioSample = ((SAMPLE_MAX_RANGE / ADC_MAX_RANGE) * ADC_GetResult());
-
-#if defined(MICROPHONE_BIASED_TO_HALF_RAIL)
- /* Microphone is biased to half rail voltage, subtract the bias from the sample value */
- AudioSample -= (SAMPLE_MAX_RANGE / 2));
-#endif
-
- /* Write the sample to the buffer */
- Endpoint_Write_Word_LE(AudioSample);
-
- /* Check to see if the bank is now full */
- if (!(Endpoint_IsReadWriteAllowed()))
- {
- /* Send the full packet to the host */
- Endpoint_ClearIN();
- }
- }
+ USB_Audio_ProcessControlPacket(&Microphone_Audio_Interface);
}
diff --git a/Demos/Device/AudioInput/AudioInput.h b/Demos/Device/AudioInput/AudioInput.h
index a394492f0..e9f56b30a 100644
--- a/Demos/Device/AudioInput/AudioInput.h
+++ b/Demos/Device/AudioInput/AudioInput.h
@@ -43,12 +43,13 @@
#include "Descriptors.h"
- #include <LUFA/Version.h> // Library Version Information
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver
- #include <LUFA/Drivers/Peripheral/ADC.h> // ADC driver
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management
-
+ #include <LUFA/Version.h>
+ #include <LUFA/Drivers/Board/LEDs.h>
+ #include <LUFA/Drivers/Board/Joystick.h>
+ #include <LUFA/Drivers/Peripheral/ADC.h>
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/Audio.h>
+
/* Macros: */
/** ADC channel number for the microphone input. */
#define MIC_IN_ADC_CHANNEL 2
@@ -59,24 +60,19 @@
/** Maximum ADC range for the microphone input. */
#define ADC_MAX_RANGE 0x3FF
- /* Enums: */
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */
- enum AudioInput_StatusCodes_t
- {
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */
- Status_USBEnumerating = 1, /**< USB interface is enumerating */
- Status_USBReady = 2, /**< USB interface is connected and ready */
- };
-
- /* Task Definitions: */
- TASK(USB_Audio_Task);
-
+ /* Macros: */
+ #define LEDMASK_USB_NOTREADY LEDS_LED1
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
+
/* Function Prototypes: */
+ void SetupHardware(void);
+ void ProcessNextSample(void);
+
void EVENT_USB_Connect(void);
void EVENT_USB_Disconnect(void);
void EVENT_USB_ConfigurationChanged(void);
void EVENT_USB_UnhandledControlPacket(void);
- void UpdateStatus(uint8_t CurrentStatus);
-
#endif
diff --git a/Demos/Device/AudioInput/makefile b/Demos/Device/AudioInput/makefile
index c70e98e04..9d3adff69 100644
--- a/Demos/Device/AudioInput/makefile
+++ b/Demos/Device/AudioInput/makefile
@@ -125,7 +125,6 @@ LUFA_PATH = ../../..
# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c \
Descriptors.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 \
@@ -136,7 +135,7 @@ SRC = $(TARGET).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/Audio.c \
# List C++ source files here. (C dependencies are automatically generated.)
diff --git a/Demos/Device/AudioOutput/AudioOutput.c b/Demos/Device/AudioOutput/AudioOutput.c
index 40e376b52..0f193567a 100644
--- a/Demos/Device/AudioOutput/AudioOutput.c
+++ b/Demos/Device/AudioOutput/AudioOutput.c
@@ -28,27 +28,33 @@
this software.
*/
-/** \file
- *
- * Main source file for the Audio Output demo. This file contains the main tasks of the demo and
- * is responsible for the initial application hardware configuration.
- */
-
#include "AudioOutput.h"
-/* Scheduler Task List */
-TASK_LIST
-{
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },
- { .Task = USB_Audio_Task , .TaskStatus = TASK_STOP },
-};
+USB_ClassInfo_Audio_t Speaker_Audio_Interface =
+ {
+ .InterfaceNumber = 0,
+ .DataOUTEndpointNumber = AUDIO_STREAM_EPNUM,
+ .DataOUTEndpointSize = AUDIO_STREAM_EPSIZE,
+ };
-/** Main program entry point. This routine configures the hardware required by the application, then
- * starts the scheduler to run the application tasks.
- */
int main(void)
{
+ SetupHardware();
+
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+
+ for (;;)
+ {
+ if (Speaker_Audio_Interface.InterfaceEnabled)
+ ProcessNextSample();
+
+ USB_USBTask();
+ }
+}
+
+void SetupHardware(void)
+{
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
@@ -58,186 +64,19 @@ int main(void)
/* Hardware Initialization */
LEDs_Init();
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
-
- /* Initialize Scheduler so that it can be used */
- Scheduler_Init();
-
- /* Initialize USB Subsystem */
USB_Init();
-
- /* Scheduling - routine never returns, so put this last in the main function */
- Scheduler_Start();
-}
-
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs, and
- * configures the sample update and PWM timers.
- */
-void EVENT_USB_Connect(void)
-{
- /* Start USB management task */
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);
-
- /* Indicate USB enumerating */
- UpdateStatus(Status_USBEnumerating);
-
- /* Sample reload timer initialization */
- OCR0A = (F_CPU / AUDIO_SAMPLE_FREQUENCY) - 1;
- TCCR0A = (1 << WGM01); // CTC mode
- TCCR0B = (1 << CS00); // Fcpu speed
-
-#if defined(AUDIO_OUT_MONO)
- /* Set speaker as output */
- DDRC |= (1 << 6);
-#elif defined(AUDIO_OUT_STEREO)
- /* Set speakers as outputs */
- DDRC |= ((1 << 6) | (1 << 5));
-#elif defined(AUDIO_OUT_PORTC)
- /* Set PORTC as outputs */
- DDRC |= 0xFF;
-#endif
-
-#if (defined(AUDIO_OUT_MONO) || defined(AUDIO_OUT_STEREO))
- /* PWM speaker timer initialization */
- TCCRxA = ((1 << WGMx0) | (1 << COMxA1) | (1 << COMxA0)
- | (1 << COMxB1) | (1 << COMxB0)); // Set on match, clear on TOP
- TCCRxB = ((1 << WGMx2) | (1 << CSx0)); // Fast 8-Bit PWM, Fcpu speed
-#endif
}
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
- * the status LEDs, disables the sample update and PWM output timers and stops the USB and Audio management tasks.
- */
-void EVENT_USB_Disconnect(void)
-{
- /* Stop the timers */
- TCCR0B = 0;
-#if (defined(AUDIO_OUT_MONO) || defined(AUDIO_OUT_STEREO))
- TCCRxB = 0;
-#endif
-
-#if defined(AUDIO_OUT_MONO)
- /* Set speaker as input to reduce current draw */
- DDRC &= ~(1 << 6);
-#elif defined(AUDIO_OUT_STEREO)
- /* Set speakers as inputs to reduce current draw */
- DDRC &= ~((1 << 6) | (1 << 5));
-#elif defined(AUDIO_OUT_PORTC)
- /* Set PORTC low */
- PORTC = 0x00;
-#endif
-
- /* Stop running audio and USB management tasks */
- Scheduler_SetTaskMode(USB_Audio_Task, TASK_STOP);
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
-}
-
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
- * of the USB device after enumeration - the device endpoints are configured.
- */
-void EVENT_USB_ConfigurationChanged(void)
-{
- /* Setup audio stream endpoint */
- Endpoint_ConfigureEndpoint(AUDIO_STREAM_EPNUM, EP_TYPE_ISOCHRONOUS,
- ENDPOINT_DIR_OUT, AUDIO_STREAM_EPSIZE,
- ENDPOINT_BANK_DOUBLE);
-
- /* Indicate USB connected and ready */
- UpdateStatus(Status_USBReady);
-}
-
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
- * control requests that are not handled internally by the USB library (including the Audio class-specific
- * requests) so that they can be handled appropriately for the application.
- */
-void EVENT_USB_UnhandledControlPacket(void)
+void ProcessNextSample(void)
{
- /* Process General and Audio specific control requests */
- switch (USB_ControlRequest.bRequest)
- {
- case REQ_SetInterface:
- /* Set Interface is not handled by the library, as its function is application-specific */
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Check if the host is enabling the audio interface (setting AlternateSetting to 1) */
- if (USB_ControlRequest.wValue)
- {
- /* Start audio task */
- Scheduler_SetTaskMode(USB_Audio_Task, TASK_RUN);
- }
- else
- {
- /* Stop audio task */
- Scheduler_SetTaskMode(USB_Audio_Task, TASK_STOP);
- }
-
- /* Acknowledge status stage */
- while (!(Endpoint_IsINReady()));
- Endpoint_ClearIN();
- }
-
- break;
- }
-}
-
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to
- * log to a serial port, or anything else that is suitable for status updates.
- *
- * \param CurrentStatus Current status of the system, from the AudioOutput_StatusCodes_t enum
- */
-void UpdateStatus(uint8_t CurrentStatus)
-{
- uint8_t LEDMask = LEDS_NO_LEDS;
-
- /* Set the LED mask to the appropriate LED mask based on the given status code */
- switch (CurrentStatus)
- {
- case Status_USBNotReady:
- LEDMask = (LEDS_LED1);
- break;
- case Status_USBEnumerating:
- LEDMask = (LEDS_LED1 | LEDS_LED2);
- break;
- case Status_USBReady:
- LEDMask = (LEDS_LED2 | LEDS_LED4);
- break;
- }
-
- /* Set the board LEDs to the new LED mask */
- LEDs_SetAllLEDs(LEDMask);
-}
-
-/** Task to manage the Audio interface, reading in audio samples from the host, and outputting them to the speakers/LEDs as
- * desired.
- */
-TASK(USB_Audio_Task)
-{
- /* Select the audio stream endpoint */
- Endpoint_SelectEndpoint(AUDIO_STREAM_EPNUM);
-
- /* Check if the current endpoint can be read from (contains a packet) and that the next sample should be read */
- if (Endpoint_IsOUTReceived() && (TIFR0 & (1 << OCF0A)))
+ if ((TIFR0 & (1 << OCF0A)) && USB_Audio_IsSampleReceived(&Speaker_Audio_Interface))
{
/* Clear the sample reload timer */
TIFR0 |= (1 << OCF0A);
/* Retrieve the signed 16-bit left and right audio samples */
- int16_t LeftSample_16Bit = (int16_t)Endpoint_Read_Word_LE();
- int16_t RightSample_16Bit = (int16_t)Endpoint_Read_Word_LE();
-
- /* Check to see if the bank is now empty */
- if (!(Endpoint_IsReadWriteAllowed()))
- {
- /* Acknowledge the packet, clear the bank ready for the next packet */
- Endpoint_ClearOUT();
- }
+ int16_t LeftSample_16Bit = (int16_t)USB_Audio_ReadSample16();
+ int16_t RightSample_16Bit = (int16_t)USB_Audio_ReadSample16();
/* Massage signed 16-bit left and right audio samples into signed 8-bit */
int8_t LeftSample_8Bit = (LeftSample_16Bit >> 8);
@@ -289,3 +128,69 @@ TASK(USB_Audio_Task)
#endif
}
}
+
+void EVENT_USB_Connect(void)
+{
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
+
+ /* Sample reload timer initialization */
+ OCR0A = (F_CPU / AUDIO_SAMPLE_FREQUENCY) - 1;
+ TCCR0A = (1 << WGM01); // CTC mode
+ TCCR0B = (1 << CS00); // Fcpu speed
+
+#if defined(AUDIO_OUT_MONO)
+ /* Set speaker as output */
+ DDRC |= (1 << 6);
+#elif defined(AUDIO_OUT_STEREO)
+ /* Set speakers as outputs */
+ DDRC |= ((1 << 6) | (1 << 5));
+#elif defined(AUDIO_OUT_PORTC)
+ /* Set PORTC as outputs */
+ DDRC |= 0xFF;
+#endif
+
+#if (defined(AUDIO_OUT_MONO) || defined(AUDIO_OUT_STEREO))
+ /* PWM speaker timer initialization */
+ TCCRxA = ((1 << WGMx0) | (1 << COMxA1) | (1 << COMxA0)
+ | (1 << COMxB1) | (1 << COMxB0)); // Set on match, clear on TOP
+ TCCRxB = ((1 << WGMx2) | (1 << CSx0)); // Fast 8-Bit PWM, Fcpu speed
+#endif
+}
+
+/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
+ * the status LEDs, disables the sample update and PWM output timers and stops the USB and Audio management tasks.
+ */
+void EVENT_USB_Disconnect(void)
+{
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+
+ /* Stop the timers */
+ TCCR0B = 0;
+#if (defined(AUDIO_OUT_MONO) || defined(AUDIO_OUT_STEREO))
+ TCCRxB = 0;
+#endif
+
+#if defined(AUDIO_OUT_MONO)
+ /* Set speaker as input to reduce current draw */
+ DDRC &= ~(1 << 6);
+#elif defined(AUDIO_OUT_STEREO)
+ /* Set speakers as inputs to reduce current draw */
+ DDRC &= ~((1 << 6) | (1 << 5));
+#elif defined(AUDIO_OUT_PORTC)
+ /* Set PORTC low */
+ PORTC = 0x00;
+#endif
+}
+
+void EVENT_USB_ConfigurationChanged(void)
+{
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);
+
+ if (!(USB_Audio_ConfigureEndpoints(&Speaker_Audio_Interface)))
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
+}
+
+void EVENT_USB_UnhandledControlPacket(void)
+{
+ USB_Audio_ProcessControlPacket(&Speaker_Audio_Interface);
+}
diff --git a/Demos/Device/AudioOutput/AudioOutput.h b/Demos/Device/AudioOutput/AudioOutput.h
index d8725a07b..7d112db88 100644
--- a/Demos/Device/AudioOutput/AudioOutput.h
+++ b/Demos/Device/AudioOutput/AudioOutput.h
@@ -43,10 +43,12 @@
#include "Descriptors.h"
- #include <LUFA/Version.h> // Library Version Information
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management
+ #include <LUFA/Version.h>
+ #include <LUFA/Drivers/Board/LEDs.h>
+ #include <LUFA/Drivers/Board/Joystick.h>
+ #include <LUFA/Drivers/Peripheral/ADC.h>
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/Audio.h>
/* Macros: */
#if defined(USB_FULL_CONTROLLER) || defined(USB_MODIFIED_FULL_CONTROLLER)
@@ -96,24 +98,19 @@
#define CSx0 CS10
#endif
- /* Enums: */
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */
- enum AudioOutput_StatusCodes_t
- {
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */
- Status_USBEnumerating = 1, /**< USB interface is enumerating */
- Status_USBReady = 2, /**< USB interface is connected and ready */
- };
-
- /* Task Definitions: */
- TASK(USB_Audio_Task);
-
+ /* Macros: */
+ #define LEDMASK_USB_NOTREADY LEDS_LED1
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
+
/* Function Prototypes: */
+ void SetupHardware(void);
+ void ProcessNextSample(void);
+
void EVENT_USB_Connect(void);
void EVENT_USB_Disconnect(void);
void EVENT_USB_ConfigurationChanged(void);
void EVENT_USB_UnhandledControlPacket(void);
-
- void UpdateStatus(uint8_t CurrentStatus);
#endif
diff --git a/Demos/Device/AudioOutput/makefile b/Demos/Device/AudioOutput/makefile
index 28f038f49..8ad1def4d 100644
--- a/Demos/Device/AudioOutput/makefile
+++ b/Demos/Device/AudioOutput/makefile
@@ -125,7 +125,6 @@ LUFA_PATH = ../../..
# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c \
Descriptors.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 \
@@ -136,7 +135,7 @@ SRC = $(TARGET).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/Audio.c \
# List C++ source files here. (C dependencies are automatically generated.)
@@ -186,7 +185,7 @@ CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)
CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
-CDEFS += -DAUDIO_OUT_STEREO
+CDEFS += -DAUDIO_OUT_MONO
# Place -D or -U options here for ASM sources
ADEFS = -DF_CPU=$(F_CPU)
diff --git a/Demos/Device/CDC/CDC.c b/Demos/Device/CDC/CDC.c
index d7ebb9e6b..e6bc1a455 100644
--- a/Demos/Device/CDC/CDC.c
+++ b/Demos/Device/CDC/CDC.c
@@ -28,54 +28,42 @@
this software.
*/
-/** \file
- *
- * Main source file for the CDC demo. This file contains the main tasks of the demo and
- * is responsible for the initial application hardware configuration.
- */
-
#include "CDC.h"
-/* Scheduler Task List */
-TASK_LIST
-{
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },
- { .Task = CDC_Task , .TaskStatus = TASK_STOP },
-};
+USB_ClassInfo_CDC_t VirtualSerial_CDC_Interface =
+ {
+ .ControlInterfaceNumber = 0,
-/* Globals: */
-/** Contains the current baud rate and other settings of the virtual serial port. While this demo does not use
- * the physical USART and thus does not use these settings, they must still be retained and returned to the host
- * upon request or the host will assume the device is non-functional.
- *
- * These values are set by the host via a class-specific request, however they are not required to be used accurately.
- * It is possible to completely ignore these value or use other settings as the host is completely unaware of the physical
- * serial link characteristics and instead sends and receives data in endpoint streams.
- */
-CDC_Line_Coding_t LineCoding = { .BaudRateBPS = 9600,
- .CharFormat = OneStopBit,
- .ParityType = Parity_None,
- .DataBits = 8 };
+ .DataINEndpointNumber = CDC_TX_EPNUM,
+ .DataINEndpointSize = CDC_TXRX_EPSIZE,
-/** String to print through the virtual serial port when the joystick is pressed upwards. */
-char JoystickUpString[] = "Joystick Up\r\n";
+ .DataOUTEndpointNumber = CDC_RX_EPNUM,
+ .DataOUTEndpointSize = CDC_TXRX_EPSIZE,
-/** String to print through the virtual serial port when the joystick is pressed downward. */
-char JoystickDownString[] = "Joystick Down\r\n";
+ .NotificationEndpointNumber = CDC_NOTIFICATION_EPNUM,
+ .NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE,
+ };
-/** String to print through the virtual serial port when the joystick is pressed left. */
-char JoystickLeftString[] = "Joystick Left\r\n";
+int main(void)
+{
+ SetupHardware();
+
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
-/** String to print through the virtual serial port when the joystick is pressed right. */
-char JoystickRightString[] = "Joystick Right\r\n";
+ for (;;)
+ {
+ CheckJoystickMovement();
+
+ uint16_t BytesToDiscard = USB_CDC_BytesReceived(&VirtualSerial_CDC_Interface);
+ while (BytesToDiscard--)
+ USB_CDC_ReceiveByte(&VirtualSerial_CDC_Interface);
-/** String to print through the virtual serial port when the joystick is pressed inwards. */
-char JoystickPressedString[] = "Joystick Pressed\r\n";
+ USB_CDC_USBTask(&VirtualSerial_CDC_Interface);
+ USB_USBTask();
+ }
+}
-/** Main program entry point. This routine configures the hardware required by the application, then
- * starts the scheduler to run the application tasks.
- */
-int main(void)
+void SetupHardware(void)
{
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
@@ -87,235 +75,64 @@ int main(void)
/* Hardware Initialization */
Joystick_Init();
LEDs_Init();
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
-
- /* Initialize Scheduler so that it can be used */
- Scheduler_Init();
-
- /* Initialize USB Subsystem */
USB_Init();
-
- /* Scheduling - routine never returns, so put this last in the main function */
- Scheduler_Start();
-}
-
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and
- * starts the library USB task to begin the enumeration and USB management process.
- */
-void EVENT_USB_Connect(void)
-{
- /* Start USB management task */
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);
-
- /* Indicate USB enumerating */
- UpdateStatus(Status_USBEnumerating);
-}
-
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
- * the status LEDs and stops the USB management and CDC management tasks.
- */
-void EVENT_USB_Disconnect(void)
-{
- /* Stop running CDC and USB management tasks */
- Scheduler_SetTaskMode(CDC_Task, TASK_STOP);
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
-}
-
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
- * of the USB device after enumeration - the device endpoints are configured and the CDC management task started.
- */
-void EVENT_USB_ConfigurationChanged(void)
-{
- /* Setup CDC Notification, Rx and Tx Endpoints */
- Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,
- ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- /* Indicate USB connected and ready */
- UpdateStatus(Status_USBReady);
-
- /* Start CDC task */
- Scheduler_SetTaskMode(CDC_Task, TASK_RUN);
-}
-
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
- * control requests that are not handled internally by the USB library (including the CDC control commands,
- * which are all issued via the control endpoint), so that they can be handled appropriately for the application.
- */
-void EVENT_USB_UnhandledControlPacket(void)
-{
- uint8_t* LineCodingData = (uint8_t*)&LineCoding;
-
- /* Process CDC specific control requests */
- switch (USB_ControlRequest.bRequest)
- {
- case REQ_GetLineEncoding:
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- /* Acknowledge the SETUP packet, ready for data transfer */
- Endpoint_ClearSETUP();
-
- /* Write the line coding data to the control endpoint */
- Endpoint_Write_Control_Stream_LE(LineCodingData, sizeof(CDC_Line_Coding_t));
-
- /* Finalize the stream transfer to send the last packet or clear the host abort */
- Endpoint_ClearOUT();
- }
-
- break;
- case REQ_SetLineEncoding:
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- /* Acknowledge the SETUP packet, ready for data transfer */
- Endpoint_ClearSETUP();
-
- /* Read the line coding data in from the host into the global struct */
- Endpoint_Read_Control_Stream_LE(LineCodingData, sizeof(CDC_Line_Coding_t));
-
- /* Finalize the stream transfer to clear the last packet from the host */
- Endpoint_ClearIN();
- }
-
- break;
- case REQ_SetControlLineState:
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- /* Acknowledge the SETUP packet, ready for data transfer */
- Endpoint_ClearSETUP();
-
- /* NOTE: Here you can read in the line state mask from the host, to get the current state of the output handshake
- lines. The mask is read in from the wValue parameter in USB_ControlRequest, and can be masked against the
- CONTROL_LINE_OUT_* masks to determine the RTS and DTR line states using the following code:
- */
-
- /* Acknowledge status stage */
- while (!(Endpoint_IsINReady()));
- Endpoint_ClearIN();
- }
-
- break;
- }
}
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to
- * log to a serial port, or anything else that is suitable for status updates.
- *
- * \param CurrentStatus Current status of the system, from the CDC_StatusCodes_t enum
- */
-void UpdateStatus(uint8_t CurrentStatus)
+void CheckJoystickMovement(void)
{
- uint8_t LEDMask = LEDS_NO_LEDS;
-
- /* Set the LED mask to the appropriate LED mask based on the given status code */
- switch (CurrentStatus)
- {
- case Status_USBNotReady:
- LEDMask = (LEDS_LED1);
- break;
- case Status_USBEnumerating:
- LEDMask = (LEDS_LED1 | LEDS_LED2);
- break;
- case Status_USBReady:
- LEDMask = (LEDS_LED2 | LEDS_LED4);
- break;
- }
+ uint8_t JoyStatus_LCL = Joystick_GetStatus();
+ char* ReportString = NULL;
+ static bool ActionSent = false;
- /* Set the board LEDs to the new LED mask */
- LEDs_SetAllLEDs(LEDMask);
-}
-
-/** Function to manage CDC data transmission and reception to and from the host. */
-TASK(CDC_Task)
-{
- char* ReportString = NULL;
- uint8_t JoyStatus_LCL = Joystick_GetStatus();
- static bool ActionSent = false;
-
-#if 0
- /* NOTE: Here you can use the notification endpoint to send back line state changes to the host, for the special RS-232
- handshake signal lines (and some error states), via the CONTROL_LINE_IN_* masks and the following code:
- */
- USB_Notification_Header_t Notification = (USB_Notification_Header_t)
+ char* JoystickStrings[] =
{
- .NotificationType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
- .Notification = NOTIF_SerialState,
- .wValue = 0,
- .wIndex = 0,
- .wLength = sizeof(uint16_t),
+ "Joystick Up\r\n",
+ "Joystick Down\r\n",
+ "Joystick Left\r\n",
+ "Joystick Right\r\n",
+ "Joystick Pressed\r\n",
};
-
- uint16_t LineStateMask;
-
- // Set LineStateMask here to a mask of CONTROL_LINE_IN_* masks to set the input handshake line states to send to the host
-
- Endpoint_SelectEndpoint(CDC_NOTIFICATION_EPNUM);
- Endpoint_Write_Stream_LE(&Notification, sizeof(Notification));
- Endpoint_Write_Stream_LE(&LineStateMask, sizeof(LineStateMask));
- Endpoint_ClearIN();
-#endif
- /* Determine if a joystick action has occurred */
if (JoyStatus_LCL & JOY_UP)
- ReportString = JoystickUpString;
+ ReportString = JoystickStrings[0];
else if (JoyStatus_LCL & JOY_DOWN)
- ReportString = JoystickDownString;
+ ReportString = JoystickStrings[1];
else if (JoyStatus_LCL & JOY_LEFT)
- ReportString = JoystickLeftString;
+ ReportString = JoystickStrings[2];
else if (JoyStatus_LCL & JOY_RIGHT)
- ReportString = JoystickRightString;
+ ReportString = JoystickStrings[3];
else if (JoyStatus_LCL & JOY_PRESS)
- ReportString = JoystickPressedString;
-
- /* Flag management - Only allow one string to be sent per action */
- if (ReportString == NULL)
- {
- ActionSent = false;
- }
- else if (ActionSent == false)
+ ReportString = JoystickStrings[4];
+ else
+ ActionSent = false;
+
+ if ((ReportString != NULL) && (ActionSent == false))
{
ActionSent = true;
+
+ USB_CDC_SendString(&VirtualSerial_CDC_Interface, ReportString, strlen(ReportString));
+ }
+}
- /* Select the Serial Tx Endpoint */
- Endpoint_SelectEndpoint(CDC_TX_EPNUM);
+void EVENT_USB_Connect(void)
+{
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
+}
- /* Write the String to the Endpoint */
- Endpoint_Write_Stream_LE(ReportString, strlen(ReportString));
-
- /* Remember if the packet to send completely fills the endpoint */
- bool IsFull = (Endpoint_BytesInEndpoint() == CDC_TXRX_EPSIZE);
+void EVENT_USB_Disconnect(void)
+{
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+}
- /* Finalize the stream transfer to send the last packet */
- Endpoint_ClearIN();
+void EVENT_USB_ConfigurationChanged(void)
+{
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);
- /* If the last packet filled the endpoint, send an empty packet to release the buffer on
- * the receiver (otherwise all data will be cached until a non-full packet is received) */
- if (IsFull)
- {
- /* Wait until the endpoint is ready for another packet */
- while (!(Endpoint_IsINReady()));
-
- /* Send an empty packet to ensure that the host does not buffer data sent to it */
- Endpoint_ClearIN();
- }
- }
+ if (!(USB_CDC_ConfigureEndpoints(&VirtualSerial_CDC_Interface)))
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
+}
- /* Select the Serial Rx Endpoint */
- Endpoint_SelectEndpoint(CDC_RX_EPNUM);
-
- /* Throw away any received data from the host */
- if (Endpoint_IsOUTReceived())
- Endpoint_ClearOUT();
+void EVENT_USB_UnhandledControlPacket(void)
+{
+ USB_CDC_ProcessControlPacket(&VirtualSerial_CDC_Interface);
}
diff --git a/Demos/Device/CDC/CDC.h b/Demos/Device/CDC/CDC.h
index 4c4ca74d5..b487813b0 100644
--- a/Demos/Device/CDC/CDC.h
+++ b/Demos/Device/CDC/CDC.h
@@ -44,139 +44,26 @@
#include "Descriptors.h"
- #include <LUFA/Version.h> // Library Version Information
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality
- #include <LUFA/Drivers/Board/Joystick.h> // Joystick driver
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management
+ #include <LUFA/Version.h>
+ #include <LUFA/Drivers/Board/LEDs.h>
+ #include <LUFA/Drivers/Board/Joystick.h>
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/CDC.h>
/* Macros: */
- /** CDC Class specific request to get the current virtual serial port configuration settings. */
- #define REQ_GetLineEncoding 0x21
-
- /** CDC Class specific request to set the current virtual serial port configuration settings. */
- #define REQ_SetLineEncoding 0x20
-
- /** CDC Class specific request to set the current virtual serial port handshake line states. */
- #define REQ_SetControlLineState 0x22
-
- /** Notification type constant for a change in the virtual serial port handshake line states, for
- * use with a USB_Notification_Header_t notification structure when sent to the host via the CDC
- * notification endpoint.
- */
- #define NOTIF_SerialState 0x20
-
- /** Mask for the DTR handshake line for use with the REQ_SetControlLineState class specific request
- * from the host, to indicate that the DTR line state should be high.
- */
- #define CONTROL_LINE_OUT_DTR (1 << 0)
-
- /** Mask for the RTS handshake line for use with the REQ_SetControlLineState class specific request
- * from the host, to indicate that theRTS line state should be high.
- */
- #define CONTROL_LINE_OUT_RTS (1 << 1)
-
- /** Mask for the DCD handshake line for use with the a NOTIF_SerialState class specific notification
- * from the device to the host, to indicate that the DCD line state is currently high.
- */
- #define CONTROL_LINE_IN_DCD (1 << 0)
-
- /** Mask for the DSR handshake line for use with the a NOTIF_SerialState class specific notification
- * from the device to the host, to indicate that the DSR line state is currently high.
- */
- #define CONTROL_LINE_IN_DSR (1 << 1)
-
- /** Mask for the BREAK handshake line for use with the a NOTIF_SerialState class specific notification
- * from the device to the host, to indicate that the BREAK line state is currently high.
- */
- #define CONTROL_LINE_IN_BREAK (1 << 2)
-
- /** Mask for the RING handshake line for use with the a NOTIF_SerialState class specific notification
- * from the device to the host, to indicate that the RING line state is currently high.
- */
- #define CONTROL_LINE_IN_RING (1 << 3)
-
- /** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,
- * to indicate that a framing error has occurred on the virtual serial port.
- */
- #define CONTROL_LINE_IN_FRAMEERROR (1 << 4)
-
- /** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,
- * to indicate that a parity error has occurred on the virtual serial port.
- */
- #define CONTROL_LINE_IN_PARITYERROR (1 << 5)
-
- /** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,
- * to indicate that a data overrun error has occurred on the virtual serial port.
- */
- #define CONTROL_LINE_IN_OVERRUNERROR (1 << 6)
-
- /* Type Defines: */
- /** Type define for the virtual serial port line encoding settings, for storing the current USART configuration
- * as set by the host via a class specific request.
- */
- typedef struct
- {
- uint32_t BaudRateBPS; /**< Baud rate of the virtual serial port, in bits per second */
- uint8_t CharFormat; /**< Character format of the virtual serial port, a value from the
- * CDCDevice_CDC_LineCodingFormats_t enum
- */
- uint8_t ParityType; /**< Parity setting of the virtual serial port, a value from the
- * CDCDevice_LineCodingParity_t enum
- */
- uint8_t DataBits; /**< Bits of data per character of the virtual serial port */
- } CDC_Line_Coding_t;
-
- /** Type define for a CDC notification, sent to the host via the CDC notification endpoint to indicate a
- * change in the device state asynchronously.
- */
- typedef struct
- {
- uint8_t NotificationType; /**< Notification type, a mask of REQDIR_*, REQTYPE_* and REQREC_* constants
- * from the library StdRequestType.h header
- */
- uint8_t Notification; /**< Notification value, a NOTIF_* constant */
- uint16_t wValue; /**< Notification wValue, notification-specific */
- uint16_t wIndex; /**< Notification wIndex, notification-specific */
- uint16_t wLength; /**< Notification wLength, notification-specific */
- } USB_Notification_Header_t;
-
- /* Enums: */
- /** Enum for the possible line encoding formats of a virtual serial port. */
- enum CDCDevice_CDC_LineCodingFormats_t
- {
- OneStopBit = 0, /**< Each frame contains one stop bit */
- OneAndAHalfStopBits = 1, /**< Each frame contains one and a half stop bits */
- TwoStopBits = 2, /**< Each frame contains two stop bits */
- };
+ #define LEDMASK_USB_NOTREADY LEDS_LED1
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
- /** Enum for the possible line encoding parity settings of a virtual serial port. */
- enum CDCDevice_LineCodingParity_t
- {
- Parity_None = 0, /**< No parity bit mode on each frame */
- Parity_Odd = 1, /**< Odd parity bit mode on each frame */
- Parity_Even = 2, /**< Even parity bit mode on each frame */
- Parity_Mark = 3, /**< Mark parity bit mode on each frame */
- Parity_Space = 4, /**< Space parity bit mode on each frame */
- };
-
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */
- enum CDC_StatusCodes_t
- {
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */
- Status_USBEnumerating = 1, /**< USB interface is enumerating */
- Status_USBReady = 2, /**< USB interface is connected and ready */
- };
-
- /* Tasks: */
- TASK(CDC_Task);
-
/* Function Prototypes: */
+ void SetupHardware(void);
+ void CheckJoystickMovement(void);
+
void EVENT_USB_Connect(void);
void EVENT_USB_Disconnect(void);
void EVENT_USB_ConfigurationChanged(void);
void EVENT_USB_UnhandledControlPacket(void);
-
- void UpdateStatus(uint8_t CurrentStatus);
+ void EVENT_USB_StartOfFrame(void);
#endif
diff --git a/Demos/Device/CDC/Descriptors.h b/Demos/Device/CDC/Descriptors.h
index 41b44300a..1a9dbb5bf 100644
--- a/Demos/Device/CDC/Descriptors.h
+++ b/Demos/Device/CDC/Descriptors.h
@@ -37,26 +37,12 @@
#define _DESCRIPTORS_H_
/* Includes: */
- #include <LUFA/Drivers/USB/USB.h>
-
#include <avr/pgmspace.h>
- /* Macros: */
- /** Macro to define a CDC class-specific functional descriptor. CDC functional descriptors have a
- * uniform structure but variable sized data payloads, thus cannot be represented accurately by
- * a single typedef struct. A macro is used instead so that functional descriptors can be created
- * easily by specifying the size of the payload. This allows sizeof() to work correctly.
- *
- * \param DataSize Size in bytes of the CDC functional descriptor's data payload
- */
- #define CDC_FUNCTIONAL_DESCRIPTOR(DataSize) \
- struct \
- { \
- USB_Descriptor_Header_t Header; \
- uint8_t SubType; \
- uint8_t Data[DataSize]; \
- }
-
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/CDC.h>
+
+ /* Macros: */
/** Endpoint number of the CDC device-to-host notification IN endpoint. */
#define CDC_NOTIFICATION_EPNUM 2
diff --git a/Demos/Device/CDC/makefile b/Demos/Device/CDC/makefile
index bc22be5c0..bd4ff36b9 100644
--- a/Demos/Device/CDC/makefile
+++ b/Demos/Device/CDC/makefile
@@ -125,7 +125,6 @@ LUFA_PATH = ../../..
# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c \
Descriptors.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 \
@@ -136,7 +135,7 @@ SRC = $(TARGET).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/CDC.c \
# List C++ source files here. (C dependencies are automatically generated.)
@@ -183,7 +182,7 @@ CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
diff --git a/Demos/Device/DualCDC/Descriptors.h b/Demos/Device/DualCDC/Descriptors.h
index 2c2311b9c..97165e5de 100644
--- a/Demos/Device/DualCDC/Descriptors.h
+++ b/Demos/Device/DualCDC/Descriptors.h
@@ -37,26 +37,12 @@
#define _DESCRIPTORS_H_
/* Includes: */
- #include <LUFA/Drivers/USB/USB.h>
-
#include <avr/pgmspace.h>
- /* Macros: */
- /** Macro to define a CDC class-specific functional descriptor. CDC functional descriptors have a
- * uniform structure but variable sized data payloads, thus cannot be represented accurately by
- * a single typedef struct. A macro is used instead so that functional descriptors can be created
- * easily by specifying the size of the payload. This allows sizeof() to work correctly.
- *
- * \param DataSize Size in bytes of the CDC functional descriptor's data payload
- */
- #define CDC_FUNCTIONAL_DESCRIPTOR(DataSize) \
- struct \
- { \
- USB_Descriptor_Header_t Header; \
- uint8_t SubType; \
- uint8_t Data[DataSize]; \
- }
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/CDC.h>
+ /* Macros: */
/** Endpoint number of the first CDC interface's device-to-host notification IN endpoint. */
#define CDC1_NOTIFICATION_EPNUM 3
diff --git a/Demos/Device/DualCDC/DualCDC.c b/Demos/Device/DualCDC/DualCDC.c
index 34d772ff0..26947f433 100644
--- a/Demos/Device/DualCDC/DualCDC.c
+++ b/Demos/Device/DualCDC/DualCDC.c
@@ -27,70 +27,63 @@
arising out of or in connection with the use or performance of
this software.
*/
-
-/** \file
- *
- * Main source file for the DualCDC demo. This file contains the main tasks of the demo and
- * is responsible for the initial application hardware configuration.
- */
#include "DualCDC.h"
-/* Scheduler Task List */
-TASK_LIST
-{
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },
- { .Task = CDC1_Task , .TaskStatus = TASK_STOP },
- { .Task = CDC2_Task , .TaskStatus = TASK_STOP },
-};
+USB_ClassInfo_CDC_t VirtualSerial1_CDC_Interface =
+ {
+ .ControlInterfaceNumber = 0,
-/* Globals: */
-/** Contains the current baud rate and other settings of the first virtual serial port. While this demo does not use
- * the physical USART and thus does not use these settings, they must still be retained and returned to the host
- * upon request or the host will assume the device is non-functional.
- *
- * These values are set by the host via a class-specific request, however they are not required to be used accurately.
- * It is possible to completely ignore these value or use other settings as the host is completely unaware of the physical
- * serial link characteristics and instead sends and receives data in endpoint streams.
- */
-CDC_Line_Coding_t LineCoding1 = { .BaudRateBPS = 9600,
- .CharFormat = OneStopBit,
- .ParityType = Parity_None,
- .DataBits = 8 };
+ .DataINEndpointNumber = CDC1_TX_EPNUM,
+ .DataINEndpointSize = CDC_TXRX_EPSIZE,
-/** Contains the current baud rate and other settings of the second virtual serial port. While this demo does not use
- * the physical USART and thus does not use these settings, they must still be retained and returned to the host
- * upon request or the host will assume the device is non-functional.
- *
- * These values are set by the host via a class-specific request, however they are not required to be used accurately.
- * It is possible to completely ignore these value or use other settings as the host is completely unaware of the physical
- * serial link characteristics and instead sends and receives data in endpoint streams.
- */
-CDC_Line_Coding_t LineCoding2 = { .BaudRateBPS = 9600,
- .CharFormat = OneStopBit,
- .ParityType = Parity_None,
- .DataBits = 8 };
-
-/** String to print through the first virtual serial port when the joystick is pressed upwards. */
-char JoystickUpString[] = "Joystick Up\r\n";
+ .DataOUTEndpointNumber = CDC1_RX_EPNUM,
+ .DataOUTEndpointSize = CDC_TXRX_EPSIZE,
-/** String to print through the first virtual serial port when the joystick is pressed downward. */
-char JoystickDownString[] = "Joystick Down\r\n";
+ .NotificationEndpointNumber = CDC1_NOTIFICATION_EPNUM,
+ .NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE,
+ };
+
+USB_ClassInfo_CDC_t VirtualSerial2_CDC_Interface =
+ {
+ .ControlInterfaceNumber = 0,
-/** String to print through the first virtual serial port when the joystick is pressed left. */
-char JoystickLeftString[] = "Joystick Left\r\n";
+ .DataINEndpointNumber = CDC2_TX_EPNUM,
+ .DataINEndpointSize = CDC_TXRX_EPSIZE,
-/** String to print through the first virtual serial port when the joystick is pressed right. */
-char JoystickRightString[] = "Joystick Right\r\n";
+ .DataOUTEndpointNumber = CDC2_RX_EPNUM,
+ .DataOUTEndpointSize = CDC_TXRX_EPSIZE,
-/** String to print through the first virtual serial port when the joystick is pressed inwards. */
-char JoystickPressedString[] = "Joystick Pressed\r\n";
+ .NotificationEndpointNumber = CDC2_NOTIFICATION_EPNUM,
+ .NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE,
+ };
-/** Main program entry point. This routine configures the hardware required by the application, then
- * starts the scheduler to run the application tasks.
- */
int main(void)
{
+ SetupHardware();
+
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+
+ for (;;)
+ {
+ CheckJoystickMovement();
+
+ uint16_t BytesToDiscard = USB_CDC_BytesReceived(&VirtualSerial1_CDC_Interface);
+ while (BytesToDiscard--)
+ USB_CDC_ReceiveByte(&VirtualSerial1_CDC_Interface);
+
+ uint16_t BytesToEcho = USB_CDC_BytesReceived(&VirtualSerial2_CDC_Interface);
+ while (BytesToEcho--)
+ USB_CDC_SendByte(&VirtualSerial2_CDC_Interface, USB_CDC_ReceiveByte(&VirtualSerial2_CDC_Interface));
+
+ USB_CDC_USBTask(&VirtualSerial1_CDC_Interface);
+ USB_CDC_USBTask(&VirtualSerial2_CDC_Interface);
+ USB_USBTask();
+ }
+}
+
+void SetupHardware(void)
+{
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
@@ -101,257 +94,68 @@ int main(void)
/* Hardware Initialization */
Joystick_Init();
LEDs_Init();
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
-
- /* Initialize Scheduler so that it can be used */
- Scheduler_Init();
-
- /* Initialize USB Subsystem */
USB_Init();
-
- /* Scheduling - routine never returns, so put this last in the main function */
- Scheduler_Start();
-}
-
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and
- * starts the library USB task to begin the enumeration and USB management process.
- */
-void EVENT_USB_Connect(void)
-{
- /* Start USB management task */
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);
-
- /* Indicate USB enumerating */
- UpdateStatus(Status_USBEnumerating);
-}
-
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
- * the status LEDs and stops the USB management and CDC management tasks.
- */
-void EVENT_USB_Disconnect(void)
-{
- /* Stop running CDC and USB management tasks */
- Scheduler_SetTaskMode(CDC1_Task, TASK_STOP);
- Scheduler_SetTaskMode(CDC2_Task, TASK_STOP);
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
-}
-
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
- * of the USB device after enumeration - the device endpoints are configured and the CDC management tasks are started.
- */
-void EVENT_USB_ConfigurationChanged(void)
-{
- /* Setup CDC Notification, Rx and Tx Endpoints for the first CDC */
- Endpoint_ConfigureEndpoint(CDC1_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,
- ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- Endpoint_ConfigureEndpoint(CDC1_TX_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- Endpoint_ConfigureEndpoint(CDC1_RX_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- /* Setup CDC Notification, Rx and Tx Endpoints for the second CDC */
- Endpoint_ConfigureEndpoint(CDC2_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,
- ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- Endpoint_ConfigureEndpoint(CDC2_TX_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- Endpoint_ConfigureEndpoint(CDC2_RX_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- /* Indicate USB connected and ready */
- UpdateStatus(Status_USBReady);
-
- /* Start CDC tasks */
- Scheduler_SetTaskMode(CDC1_Task, TASK_RUN);
- Scheduler_SetTaskMode(CDC2_Task, TASK_RUN);
-}
-
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
- * control requests that are not handled internally by the USB library (including the CDC control commands,
- * which are all issued via the control endpoint), so that they can be handled appropriately for the application.
- */
-void EVENT_USB_UnhandledControlPacket(void)
-{
- /* Determine which interface's Line Coding data is being set from the wIndex parameter */
- uint8_t* LineCodingData = (USB_ControlRequest.wIndex == 0) ? (uint8_t*)&LineCoding1 : (uint8_t*)&LineCoding2;
-
- /* Process CDC specific control requests */
- switch (USB_ControlRequest.bRequest)
- {
- case REQ_GetLineEncoding:
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- /* Acknowledge the SETUP packet, ready for data transfer */
- Endpoint_ClearSETUP();
-
- /* Write the line coding data to the control endpoint */
- Endpoint_Write_Control_Stream_LE(LineCodingData, sizeof(CDC_Line_Coding_t));
-
- /* Finalize the stream transfer to send the last packet or clear the host abort */
- Endpoint_ClearOUT();
- }
-
- break;
- case REQ_SetLineEncoding:
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- /* Acknowledge the SETUP packet, ready for data transfer */
- Endpoint_ClearSETUP();
-
- /* Read the line coding data in from the host into the global struct */
- Endpoint_Read_Control_Stream_LE(LineCodingData, sizeof(CDC_Line_Coding_t));
-
- /* Finalize the stream transfer to clear the last packet from the host */
- Endpoint_ClearIN();
- }
-
- break;
- case REQ_SetControlLineState:
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- /* Acknowledge the SETUP packet, ready for data transfer */
- Endpoint_ClearSETUP();
-
- /* Acknowledge status stage */
- while (!(Endpoint_IsINReady()));
- Endpoint_ClearIN();
- }
-
- break;
- }
-}
-
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to
- * log to a serial port, or anything else that is suitable for status updates.
- *
- * \param CurrentStatus Current status of the system, from the DualCDC_StatusCodes_t enum
- */
-void UpdateStatus(uint8_t CurrentStatus)
-{
- uint8_t LEDMask = LEDS_NO_LEDS;
-
- /* Set the LED mask to the appropriate LED mask based on the given status code */
- switch (CurrentStatus)
- {
- case Status_USBNotReady:
- LEDMask = (LEDS_LED1);
- break;
- case Status_USBEnumerating:
- LEDMask = (LEDS_LED1 | LEDS_LED2);
- break;
- case Status_USBReady:
- LEDMask = (LEDS_LED2 | LEDS_LED4);
- break;
- }
-
- /* Set the board LEDs to the new LED mask */
- LEDs_SetAllLEDs(LEDMask);
}
-/** Function to manage CDC data transmission and reception to and from the host for the first CDC interface, which sends joystick
- * movements to the host as ASCII strings.
- */
-TASK(CDC1_Task)
+void CheckJoystickMovement(void)
{
- char* ReportString = NULL;
- uint8_t JoyStatus_LCL = Joystick_GetStatus();
- static bool ActionSent = false;
+ uint8_t JoyStatus_LCL = Joystick_GetStatus();
+ char* ReportString = NULL;
+ static bool ActionSent = false;
+
+ char* JoystickStrings[] =
+ {
+ "Joystick Up\r\n",
+ "Joystick Down\r\n",
+ "Joystick Left\r\n",
+ "Joystick Right\r\n",
+ "Joystick Pressed\r\n",
+ };
- /* Determine if a joystick action has occurred */
if (JoyStatus_LCL & JOY_UP)
- ReportString = JoystickUpString;
+ ReportString = JoystickStrings[0];
else if (JoyStatus_LCL & JOY_DOWN)
- ReportString = JoystickDownString;
+ ReportString = JoystickStrings[1];
else if (JoyStatus_LCL & JOY_LEFT)
- ReportString = JoystickLeftString;
+ ReportString = JoystickStrings[2];
else if (JoyStatus_LCL & JOY_RIGHT)
- ReportString = JoystickRightString;
+ ReportString = JoystickStrings[3];
else if (JoyStatus_LCL & JOY_PRESS)
- ReportString = JoystickPressedString;
-
- /* Flag management - Only allow one string to be sent per action */
- if (ReportString == NULL)
- {
- ActionSent = false;
- }
- else if (ActionSent == false)
+ ReportString = JoystickStrings[4];
+ else
+ ActionSent = false;
+
+ if ((ReportString != NULL) && (ActionSent == false))
{
ActionSent = true;
- /* Select the Serial Tx Endpoint */
- Endpoint_SelectEndpoint(CDC1_TX_EPNUM);
-
- /* Write the String to the Endpoint */
- Endpoint_Write_Stream_LE(ReportString, strlen(ReportString));
-
- /* Finalize the stream transfer to send the last packet */
- Endpoint_ClearIN();
-
- /* Wait until the endpoint is ready for another packet */
- while (!(Endpoint_IsINReady()));
-
- /* Send an empty packet to ensure that the host does not buffer data sent to it */
- Endpoint_ClearIN();
+ USB_CDC_SendString(&VirtualSerial1_CDC_Interface, ReportString, strlen(ReportString));
}
-
- /* Select the Serial Rx Endpoint */
- Endpoint_SelectEndpoint(CDC1_RX_EPNUM);
-
- /* Throw away any received data from the host */
- if (Endpoint_IsOUTReceived())
- Endpoint_ClearOUT();
}
-/** Function to manage CDC data transmission and reception to and from the host for the second CDC interface, which echoes back
- * all data sent to it from the host.
- */
-TASK(CDC2_Task)
+void EVENT_USB_Connect(void)
{
- /* Select the Serial Rx Endpoint */
- Endpoint_SelectEndpoint(CDC2_RX_EPNUM);
-
- /* Check to see if any data has been received */
- if (Endpoint_IsOUTReceived())
- {
- /* Create a temp buffer big enough to hold the incoming endpoint packet */
- uint8_t Buffer[Endpoint_BytesInEndpoint()];
-
- /* Remember how large the incoming packet is */
- uint16_t DataLength = Endpoint_BytesInEndpoint();
-
- /* Read in the incoming packet into the buffer */
- Endpoint_Read_Stream_LE(&Buffer, DataLength);
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
+}
- /* Finalize the stream transfer to send the last packet */
- Endpoint_ClearOUT();
+void EVENT_USB_Disconnect(void)
+{
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+}
- /* Select the Serial Tx Endpoint */
- Endpoint_SelectEndpoint(CDC2_TX_EPNUM);
-
- /* Write the received data to the endpoint */
- Endpoint_Write_Stream_LE(&Buffer, DataLength);
+void EVENT_USB_ConfigurationChanged(void)
+{
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);
- /* Finalize the stream transfer to send the last packet */
- Endpoint_ClearIN();
+ if (!(USB_CDC_ConfigureEndpoints(&VirtualSerial1_CDC_Interface)))
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
- /* Wait until the endpoint is ready for the next packet */
- while (!(Endpoint_IsINReady()));
+ if (!(USB_CDC_ConfigureEndpoints(&VirtualSerial2_CDC_Interface)))
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
+}
- /* Send an empty packet to prevent host buffering */
- Endpoint_ClearIN();
- }
+void EVENT_USB_UnhandledControlPacket(void)
+{
+ USB_CDC_ProcessControlPacket(&VirtualSerial1_CDC_Interface);
+ USB_CDC_ProcessControlPacket(&VirtualSerial2_CDC_Interface);
}
diff --git a/Demos/Device/DualCDC/DualCDC.h b/Demos/Device/DualCDC/DualCDC.h
index 117af601e..3c1e29612 100644
--- a/Demos/Device/DualCDC/DualCDC.h
+++ b/Demos/Device/DualCDC/DualCDC.h
@@ -44,75 +44,26 @@
#include "Descriptors.h"
- #include <LUFA/Version.h> // Library Version Information
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality
- #include <LUFA/Drivers/Board/Joystick.h> // Joystick driver
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management
+ #include <LUFA/Version.h>
+ #include <LUFA/Drivers/Board/LEDs.h>
+ #include <LUFA/Drivers/Board/Joystick.h>
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/CDC.h>
/* Macros: */
- /** CDC Class specific request to get the current virtual serial port configuration settings. */
- #define REQ_GetLineEncoding 0x21
-
- /** CDC Class specific request to set the current virtual serial port configuration settings. */
- #define REQ_SetLineEncoding 0x20
-
- /** CDC Class specific request to set the current virtual serial port handshake line states. */
- #define REQ_SetControlLineState 0x22
-
- /* Type Defines: */
- /** Type define for the virtual serial port line encoding settings, for storing the current USART configuration
- * as set by the host via a class specific request.
- */
- typedef struct
- {
- uint32_t BaudRateBPS; /**< Baud rate of the virtual serial port, in bits per second */
- uint8_t CharFormat; /**< Character format of the virtual serial port, a value from the
- * CDCDevice_CDC_LineCodingFormats_t enum
- */
- uint8_t ParityType; /**< Parity setting of the virtual serial port, a value from the
- * CDCDevice_LineCodingParity_t enum
- */
- uint8_t DataBits; /**< Bits of data per character of the virtual serial port */
- } CDC_Line_Coding_t;
+ #define LEDMASK_USB_NOTREADY LEDS_LED1
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
- /* Enums: */
- /** Enum for the possible line encoding formats of a virtual serial port. */
- enum CDCDevice_CDC_LineCodingFormats_t
- {
- OneStopBit = 0, /**< Each frame contains one stop bit */
- OneAndAHalfStopBits = 1, /**< Each frame contains one and a half stop bits */
- TwoStopBits = 2, /**< Each frame contains two stop bits */
- };
-
- /** Enum for the possible line encoding parity settings of a virtual serial port. */
- enum CDCDevice_LineCodingParity_t
- {
- Parity_None = 0, /**< No parity bit mode on each frame */
- Parity_Odd = 1, /**< Odd parity bit mode on each frame */
- Parity_Even = 2, /**< Even parity bit mode on each frame */
- Parity_Mark = 3, /**< Mark parity bit mode on each frame */
- Parity_Space = 4, /**< Space parity bit mode on each frame */
- };
-
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */
- enum DualCDC_StatusCodes_t
- {
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */
- Status_USBEnumerating = 1, /**< USB interface is enumerating */
- Status_USBReady = 2, /**< USB interface is connected and ready */
- };
-
- /* Tasks: */
- TASK(CDC1_Task);
- TASK(CDC2_Task);
-
/* Function Prototypes: */
+ void SetupHardware(void);
+ void CheckJoystickMovement(void);
+
void EVENT_USB_Connect(void);
void EVENT_USB_Disconnect(void);
void EVENT_USB_ConfigurationChanged(void);
void EVENT_USB_UnhandledControlPacket(void);
-
- void UpdateStatus(uint8_t CurrentStatus);
+ void EVENT_USB_StartOfFrame(void);
#endif
diff --git a/Demos/Device/DualCDC/makefile b/Demos/Device/DualCDC/makefile
index 06d0e184b..5fbda61dd 100644
--- a/Demos/Device/DualCDC/makefile
+++ b/Demos/Device/DualCDC/makefile
@@ -125,7 +125,6 @@ LUFA_PATH = ../../..
# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c \
Descriptors.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 \
@@ -136,7 +135,7 @@ SRC = $(TARGET).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/CDC.c \
# List C++ source files here. (C dependencies are automatically generated.)
@@ -183,7 +182,7 @@ CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
diff --git a/Demos/Device/GenericHID/Descriptors.h b/Demos/Device/GenericHID/Descriptors.h
index 023687032..bc4c68ae6 100644
--- a/Demos/Device/GenericHID/Descriptors.h
+++ b/Demos/Device/GenericHID/Descriptors.h
@@ -37,30 +37,12 @@
#define _DESCRIPTORS_H_
/* Includes: */
- #include <LUFA/Drivers/USB/USB.h>
-
#include <avr/pgmspace.h>
- /* Type Defines: */
- /** Type define for the HID class specific HID descriptor, to describe the HID device's specifications. Refer to the HID
- * specification for details on the structure elements.
- */
- typedef struct
- {
- USB_Descriptor_Header_t Header;
-
- uint16_t HIDSpec;
- uint8_t CountryCode;
-
- uint8_t TotalReportDescriptors;
-
- uint8_t HIDReportType;
- uint16_t HIDReportLength;
- } USB_Descriptor_HID_t;
-
- /** Type define for the data type used to store HID report descriptor elements. */
- typedef uint8_t USB_Descriptor_HIDReport_Datatype_t;
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>
+ /** Type Defines: */
/** Type define for the device configuration descriptor structure. This must be defined in the
* application code, as the configuration descriptor contains several sub-descriptors which
* vary between devices, and which describe the device's usage to the host.
@@ -73,7 +55,7 @@
USB_Descriptor_Endpoint_t GenericINEndpoint;
USB_Descriptor_Endpoint_t GenericOUTEndpoint;
} USB_Descriptor_Configuration_t;
-
+
/* Macros: */
/** Endpoint number of the Generic HID reporting IN endpoint. */
#define GENERIC_IN_EPNUM 1
@@ -86,13 +68,7 @@
/** Size in bytes of the Generic HID reports (including report ID byte). */
#define GENERIC_REPORT_SIZE 8
-
- /** Descriptor header type value, to indicate a HID class HID descriptor. */
- #define DTYPE_HID 0x21
- /** Descriptor header type value, to indicate a HID class HID report descriptor. */
- #define DTYPE_Report 0x22
-
/* Function Prototypes: */
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
diff --git a/Demos/Device/GenericHID/GenericHID.c b/Demos/Device/GenericHID/GenericHID.c
index 058d269fe..4dfb8e455 100644
--- a/Demos/Device/GenericHID/GenericHID.c
+++ b/Demos/Device/GenericHID/GenericHID.c
@@ -28,30 +28,38 @@
this software.
*/
-/** \file
- *
- * Main source file for the GenericHID demo. This file contains the main tasks of the demo and
- * is responsible for the initial application hardware configuration.
- */
-
#include "GenericHID.h"
-/* Scheduler Task List */
-TASK_LIST
-{
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },
- { .Task = USB_HID_Report , .TaskStatus = TASK_STOP },
-};
+USB_ClassInfo_HID_t Generic_HID_Interface =
+ {
+ .InterfaceNumber = 0,
-/** Static buffer to hold the last received report from the host, so that it can be echoed back in the next sent report */
-static uint8_t LastReceived[GENERIC_REPORT_SIZE];
+ .ReportINEndpointNumber = GENERIC_IN_EPNUM,
+ .ReportINEndpointSize = GENERIC_EPSIZE,
+
+ .ReportOUTEndpointNumber = GENERIC_OUT_EPNUM,
+ .ReportOUTEndpointSize = GENERIC_EPSIZE,
+
+ .ReportBufferSize = GENERIC_REPORT_SIZE,
+ .UsingReportProtocol = true,
+ };
-/** Main program entry point. This routine configures the hardware required by the application, then
- * starts the scheduler to run the USB management task.
- */
int main(void)
{
+ SetupHardware();
+
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+
+ for (;;)
+ {
+ USB_HID_USBTask(&Generic_HID_Interface);
+ USB_USBTask();
+ }
+}
+
+void SetupHardware(void)
+{
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
@@ -61,220 +69,45 @@ int main(void)
/* Hardware Initialization */
LEDs_Init();
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
-
- /* Initialize Scheduler so that it can be used */
- Scheduler_Init();
-
- /* Initialize USB Subsystem */
USB_Init();
-
- /* Scheduling - routine never returns, so put this last in the main function */
- Scheduler_Start();
}
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and
- * starts the library USB task to begin the enumeration and USB management process.
- */
void EVENT_USB_Connect(void)
{
- /* Start USB management task */
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);
-
- /* Indicate USB enumerating */
- UpdateStatus(Status_USBEnumerating);
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
}
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
- * the status LEDs and stops the USB management task.
- */
void EVENT_USB_Disconnect(void)
{
- /* Stop running HID reporting and USB management tasks */
- Scheduler_SetTaskMode(USB_HID_Report, TASK_STOP);
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
}
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host sets the current configuration
- * of the USB device after enumeration, and configures the generic HID device endpoints.
- */
void EVENT_USB_ConfigurationChanged(void)
{
- /* Setup Generic IN Report Endpoint */
- Endpoint_ConfigureEndpoint(GENERIC_IN_EPNUM, EP_TYPE_INTERRUPT,
- ENDPOINT_DIR_IN, GENERIC_EPSIZE,
- ENDPOINT_BANK_SINGLE);
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);
- /* Setup Generic OUT Report Endpoint */
- Endpoint_ConfigureEndpoint(GENERIC_OUT_EPNUM, EP_TYPE_INTERRUPT,
- ENDPOINT_DIR_OUT, GENERIC_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- /* Indicate USB connected and ready */
- UpdateStatus(Status_USBReady);
+ if (!(USB_HID_ConfigureEndpoints(&Generic_HID_Interface)))
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
- * control requests that are not handled internally by the USB library (including the HID commands, which are
- * all issued via the control endpoint), so that they can be handled appropriately for the application.
- */
void EVENT_USB_UnhandledControlPacket(void)
{
- /* Handle HID Class specific requests */
- switch (USB_ControlRequest.bRequest)
- {
- case REQ_GetReport:
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- uint8_t GenericData[GENERIC_REPORT_SIZE];
-
- Endpoint_ClearSETUP();
-
- CreateGenericHIDReport(GenericData);
-
- /* Write the report data to the control endpoint */
- Endpoint_Write_Control_Stream_LE(&GenericData, sizeof(GenericData));
-
- /* Finalize the stream transfer to send the last packet or clear the host abort */
- Endpoint_ClearOUT();
- }
-
- break;
- case REQ_SetReport:
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- uint8_t GenericData[GENERIC_REPORT_SIZE];
-
- Endpoint_ClearSETUP();
-
- /* Wait until the generic report has been sent by the host */
- while (!(Endpoint_IsOUTReceived()));
-
- Endpoint_Read_Control_Stream_LE(&GenericData, sizeof(GenericData));
-
- ProcessGenericHIDReport(GenericData);
-
- /* Clear the endpoint data */
- Endpoint_ClearOUT();
-
- /* Wait until the host is ready to receive the request confirmation */
- while (!(Endpoint_IsINReady()));
-
- /* Handshake the request by sending an empty IN packet */
- Endpoint_ClearIN();
- }
-
- break;
- }
+ USB_HID_ProcessControlPacket(&Generic_HID_Interface);
}
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to
- * log to a serial port, or anything else that is suitable for status updates.
- *
- * \param CurrentStatus Current status of the system, from the GenericHID_StatusCodes_t enum
- */
-void UpdateStatus(uint8_t CurrentStatus)
+void EVENT_USB_StartOfFrame(void)
{
- uint8_t LEDMask = LEDS_NO_LEDS;
-
- /* Set the LED mask to the appropriate LED mask based on the given status code */
- switch (CurrentStatus)
- {
- case Status_USBNotReady:
- LEDMask = (LEDS_LED1);
- break;
- case Status_USBEnumerating:
- LEDMask = (LEDS_LED1 | LEDS_LED2);
- break;
- case Status_USBReady:
- LEDMask = (LEDS_LED2 | LEDS_LED4);
- break;
- }
-
- /* Set the board LEDs to the new LED mask */
- LEDs_SetAllLEDs(LEDMask);
+ USB_HID_RegisterStartOfFrame(&Generic_HID_Interface);
}
-/** Function to process the lest received report from the host.
- *
- * \param DataArray Pointer to a buffer where the last report data is stored
- */
-void ProcessGenericHIDReport(uint8_t* DataArray)
+uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData)
{
- /*
- This is where you need to process the reports being sent from the host to the device.
- DataArray is an array holding the last report from the host. This function is called
- each time the host has sent a report to the device.
- */
+ // Create generic HID report here
- for (uint8_t i = 0; i < GENERIC_REPORT_SIZE; i++)
- LastReceived[i] = DataArray[i];
+ return 0;
}
-/** Function to create the next report to send back to the host at the next reporting interval.
- *
- * \param DataArray Pointer to a buffer where the next report data should be stored
- */
-void CreateGenericHIDReport(uint8_t* DataArray)
+void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize)
{
- /*
- This is where you need to create reports to be sent to the host from the device. This
- function is called each time the host is ready to accept a new report. DataArray is
- an array to hold the report to the host.
- */
-
- for (uint8_t i = 0; i < GENERIC_REPORT_SIZE; i++)
- DataArray[i] = LastReceived[i];
-}
-
-TASK(USB_HID_Report)
-{
- /* Check if the USB system is connected to a host */
- if (USB_IsConnected)
- {
- Endpoint_SelectEndpoint(GENERIC_OUT_EPNUM);
-
- /* Check to see if a packet has been sent from the host */
- if (Endpoint_IsOUTReceived())
- {
- /* Check to see if the packet contains data */
- if (Endpoint_IsReadWriteAllowed())
- {
- /* Create a temporary buffer to hold the read in report from the host */
- uint8_t GenericData[GENERIC_REPORT_SIZE];
-
- /* Read Generic Report Data */
- Endpoint_Read_Stream_LE(&GenericData, sizeof(GenericData));
-
- /* Process Generic Report Data */
- ProcessGenericHIDReport(GenericData);
- }
-
- /* Finalize the stream transfer to send the last packet */
- Endpoint_ClearOUT();
- }
-
- Endpoint_SelectEndpoint(GENERIC_IN_EPNUM);
-
- /* Check to see if the host is ready to accept another packet */
- if (Endpoint_IsINReady())
- {
- /* Create a temporary buffer to hold the report to send to the host */
- uint8_t GenericData[GENERIC_REPORT_SIZE];
-
- /* Create Generic Report Data */
- CreateGenericHIDReport(GenericData);
-
- /* Write Generic Report Data */
- Endpoint_Write_Stream_LE(&GenericData, sizeof(GenericData));
-
- /* Finalize the stream transfer to send the last packet */
- Endpoint_ClearIN();
- }
- }
+ // Process received generic HID report here
}
diff --git a/Demos/Device/GenericHID/GenericHID.h b/Demos/Device/GenericHID/GenericHID.h
index 30354b756..27426431c 100644
--- a/Demos/Device/GenericHID/GenericHID.h
+++ b/Demos/Device/GenericHID/GenericHID.h
@@ -46,38 +46,28 @@
#include "Descriptors.h"
- #include <LUFA/Version.h> // Library Version Information
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver
-
- /* Macros: */
- /** HID Class specific request to get the next HID report from the device. */
- #define REQ_GetReport 0x01
-
- /** HID Class specific request to send the next HID report to the device. */
- #define REQ_SetReport 0x09
-
- /* Enums: */
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */
- enum GenericHID_StatusCodes_t
- {
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */
- Status_USBEnumerating = 1, /**< USB interface is enumerating */
- Status_USBReady = 2, /**< USB interface is connected and ready */
- };
+ #include <LUFA/Version.h>
+ #include <LUFA/Drivers/Board/LEDs.h>
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>
- /* Task Definitions: */
- TASK(USB_HID_Report);
+ /* Macros: */
+ #define LEDMASK_USB_NOTREADY LEDS_LED1
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
/* Function Prototypes: */
+ void SetupHardware(void);
+
void EVENT_USB_Connect(void);
void EVENT_USB_Disconnect(void);
void EVENT_USB_ConfigurationChanged(void);
void EVENT_USB_UnhandledControlPacket(void);
+ void EVENT_USB_StartOfFrame(void);
- void UpdateStatus(uint8_t CurrentStatus);
- void ProcessGenericHIDReport(uint8_t* DataArray);
- void CreateGenericHIDReport(uint8_t* DataArray);
+ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);
+ void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo,
+ void* ReportData, uint16_t ReportSize);
#endif
diff --git a/Demos/Device/GenericHID/makefile b/Demos/Device/GenericHID/makefile
index 9c6c891cd..5cc4b4a43 100644
--- a/Demos/Device/GenericHID/makefile
+++ b/Demos/Device/GenericHID/makefile
@@ -125,7 +125,6 @@ LUFA_PATH = ../../..
# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c \
Descriptors.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 \
@@ -136,7 +135,7 @@ SRC = $(TARGET).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.)
@@ -183,7 +182,7 @@ CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
diff --git a/Demos/Device/Joystick/Descriptors.h b/Demos/Device/Joystick/Descriptors.h
index 6121295fa..1241ad14e 100644
--- a/Demos/Device/Joystick/Descriptors.h
+++ b/Demos/Device/Joystick/Descriptors.h
@@ -37,30 +37,12 @@
#define _DESCRIPTORS_H_
/* Includes: */
- #include <LUFA/Drivers/USB/USB.h>
-
#include <avr/pgmspace.h>
- /* Type Defines: */
- /** Type define for the HID class specific HID descriptor, to describe the HID device's specifications. Refer to the HID
- * specification for details on the structure elements.
- */
- typedef struct
- {
- USB_Descriptor_Header_t Header;
-
- uint16_t HIDSpec;
- uint8_t CountryCode;
-
- uint8_t TotalReportDescriptors;
-
- uint8_t HIDReportType;
- uint16_t HIDReportLength;
- } USB_Descriptor_HID_t;
-
- /** Type define for the data type used to store HID report descriptor elements. */
- typedef uint8_t USB_Descriptor_HIDReport_Datatype_t;
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>
+ /* Type Defines: */
/** Type define for the device configuration descriptor structure. This must be defined in the
* application code, as the configuration descriptor contains several sub-descriptors which
* vary between devices, and which describe the device's usage to the host.
@@ -80,12 +62,6 @@
/** Size in bytes of the Joystick HID reporting IN endpoint. */
#define JOYSTICK_EPSIZE 8
- /** Descriptor header type value, to indicate a HID class HID descriptor. */
- #define DTYPE_HID 0x21
-
- /** Descriptor header type value, to indicate a HID class HID report descriptor. */
- #define DTYPE_Report 0x22
-
/* Function Prototypes: */
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
diff --git a/Demos/Device/Joystick/Joystick.c b/Demos/Device/Joystick/Joystick.c
index 8c50a2c16..e073a87fd 100644
--- a/Demos/Device/Joystick/Joystick.c
+++ b/Demos/Device/Joystick/Joystick.c
@@ -28,26 +28,35 @@
this software.
*/
-/** \file
- *
- * Main source file for the Joystick demo. This file contains the main tasks of the demo and
- * is responsible for the initial application hardware configuration.
- */
-
#include "Joystick.h"
-/* Scheduler Task List */
-TASK_LIST
-{
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },
- { .Task = USB_Joystick_Report , .TaskStatus = TASK_STOP },
-};
+USB_ClassInfo_HID_t Joystick_HID_Interface =
+ {
+ .InterfaceNumber = 0,
+
+ .ReportINEndpointNumber = JOYSTICK_EPNUM,
+ .ReportINEndpointSize = JOYSTICK_EPSIZE,
+
+ .ReportBufferSize = sizeof(USB_JoystickReport_Data_t),
+
+ .UsingReportProtocol = true,
+ };
-/** Main program entry point. This routine configures the hardware required by the application, then
- * starts the scheduler to run the application tasks.
- */
int main(void)
{
+ SetupHardware();
+
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+
+ for (;;)
+ {
+ USB_HID_USBTask(&Joystick_HID_Interface);
+ USB_USBTask();
+ }
+}
+
+void SetupHardware(void)
+{
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
@@ -59,188 +68,64 @@ int main(void)
Joystick_Init();
LEDs_Init();
Buttons_Init();
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
-
- /* Initialize Scheduler so that it can be used */
- Scheduler_Init();
-
- /* Initialize USB Subsystem */
USB_Init();
-
- /* Scheduling - routine never returns, so put this last in the main function */
- Scheduler_Start();
}
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and
- * starts the library USB task to begin the enumeration and USB management process.
- */
void EVENT_USB_Connect(void)
{
- /* Start USB management task */
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);
-
- /* Indicate USB enumerating */
- UpdateStatus(Status_USBEnumerating);
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
}
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
- * the status LEDs and stops the USB management and joystick reporting tasks.
- */
void EVENT_USB_Disconnect(void)
{
- /* Stop running joystick reporting and USB management tasks */
- Scheduler_SetTaskMode(USB_Joystick_Report, TASK_STOP);
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
}
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
- * of the USB device after enumeration - the device endpoints are configured and the joystick reporting task started.
- */
void EVENT_USB_ConfigurationChanged(void)
{
- /* Setup Joystick Report Endpoint */
- Endpoint_ConfigureEndpoint(JOYSTICK_EPNUM, EP_TYPE_INTERRUPT,
- ENDPOINT_DIR_IN, JOYSTICK_EPSIZE,
- ENDPOINT_BANK_SINGLE);
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);
- /* Indicate USB connected and ready */
- UpdateStatus(Status_USBReady);
-
- /* Start joystick reporting task */
- Scheduler_SetTaskMode(USB_Joystick_Report, TASK_RUN);
+ if (!(USB_HID_ConfigureEndpoints(&Joystick_HID_Interface)))
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
- * control requests that are not handled internally by the USB library (including the HID commands, which are
- * all issued via the control endpoint), so that they can be handled appropriately for the application.
- */
void EVENT_USB_UnhandledControlPacket(void)
{
- /* Handle HID Class specific requests */
- switch (USB_ControlRequest.bRequest)
- {
- case REQ_GetReport:
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- USB_JoystickReport_Data_t JoystickReportData;
-
- Endpoint_ClearSETUP();
-
- /* Create the next HID report to send to the host */
- GetNextReport(&JoystickReportData);
-
- /* Write the report data to the control endpoint */
- Endpoint_Write_Control_Stream_LE(&JoystickReportData, sizeof(JoystickReportData));
-
- /* Finalize the stream transfer to send the last packet or clear the host abort */
- Endpoint_ClearOUT();
- }
-
- break;
- }
+ USB_HID_ProcessControlPacket(&Joystick_HID_Interface);
}
-/** Fills the given HID report data structure with the next HID report to send to the host.
- *
- * \param ReportData Pointer to a HID report data structure to be filled
- *
- * \return Boolean true if the new report differs from the last report, false otherwise
- */
-bool GetNextReport(USB_JoystickReport_Data_t* ReportData)
+void EVENT_USB_StartOfFrame(void)
{
- static uint8_t PrevJoyStatus = 0;
- static uint8_t PrevButtonStatus = 0;
- uint8_t JoyStatus_LCL = Joystick_GetStatus();
- uint8_t ButtonStatus_LCL = Buttons_GetStatus();
- bool InputChanged = false;
+ USB_HID_RegisterStartOfFrame(&Joystick_HID_Interface);
+}
- /* Clear the report contents */
- memset(ReportData, 0, sizeof(USB_JoystickReport_Data_t));
+uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData)
+{
+ USB_JoystickReport_Data_t* JoystickReport = (USB_JoystickReport_Data_t*)ReportData;
+
+ uint8_t JoyStatus_LCL = Joystick_GetStatus();
+ uint8_t ButtonStatus_LCL = Buttons_GetStatus();
if (JoyStatus_LCL & JOY_UP)
- ReportData->Y = -100;
+ JoystickReport->Y = -100;
else if (JoyStatus_LCL & JOY_DOWN)
- ReportData->Y = 100;
+ JoystickReport->Y = 100;
if (JoyStatus_LCL & JOY_RIGHT)
- ReportData->X = 100;
+ JoystickReport->X = 100;
else if (JoyStatus_LCL & JOY_LEFT)
- ReportData->X = -100;
+ JoystickReport->X = -100;
if (JoyStatus_LCL & JOY_PRESS)
- ReportData->Button = (1 << 1);
+ JoystickReport->Button = (1 << 1);
if (ButtonStatus_LCL & BUTTONS_BUTTON1)
- ReportData->Button |= (1 << 0);
+ JoystickReport->Button |= (1 << 0);
- /* Check if the new report is different to the previous report */
- InputChanged = (uint8_t)(PrevJoyStatus ^ JoyStatus_LCL) | (uint8_t)(PrevButtonStatus ^ ButtonStatus_LCL);
-
- /* Save the current joystick status for later comparison */
- PrevJoyStatus = JoyStatus_LCL;
- PrevButtonStatus = ButtonStatus_LCL;
-
- /* Return whether the new report is different to the previous report or not */
- return InputChanged;
+ return sizeof(USB_JoystickReport_Data_t);
}
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to
- * log to a serial port, or anything else that is suitable for status updates.
- *
- * \param CurrentStatus Current status of the system, from the Joystick_StatusCodes_t enum
- */
-void UpdateStatus(uint8_t CurrentStatus)
+void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize)
{
- uint8_t LEDMask = LEDS_NO_LEDS;
-
- /* Set the LED mask to the appropriate LED mask based on the given status code */
- switch (CurrentStatus)
- {
- case Status_USBNotReady:
- LEDMask = (LEDS_LED1);
- break;
- case Status_USBEnumerating:
- LEDMask = (LEDS_LED1 | LEDS_LED2);
- break;
- case Status_USBReady:
- LEDMask = (LEDS_LED2 | LEDS_LED4);
- break;
- }
-
- /* Set the board LEDs to the new LED mask */
- LEDs_SetAllLEDs(LEDMask);
-}
-
-/** Function to manage HID report generation and transmission to the host. */
-TASK(USB_Joystick_Report)
-{
- /* Check if the USB System is connected to a Host */
- if (USB_IsConnected)
- {
- /* Select the Joystick Report Endpoint */
- Endpoint_SelectEndpoint(JOYSTICK_EPNUM);
-
- /* Check to see if the host is ready for another packet */
- if (Endpoint_IsINReady())
- {
- USB_JoystickReport_Data_t JoystickReportData;
-
- /* Create the next HID report to send to the host */
- GetNextReport(&JoystickReportData);
-
- /* Write Joystick Report Data */
- Endpoint_Write_Stream_LE(&JoystickReportData, sizeof(JoystickReportData));
-
- /* Finalize the stream transfer to send the last packet */
- Endpoint_ClearIN();
-
- /* Clear the report data afterwards */
- memset(&JoystickReportData, 0, sizeof(JoystickReportData));
- }
- }
+ // Unused (but mandatory for the HID class driver) in this demo, since there are no Host->Device reports
}
diff --git a/Demos/Device/Joystick/Joystick.h b/Demos/Device/Joystick/Joystick.h
index 9763cada3..461d0d0cc 100644
--- a/Demos/Device/Joystick/Joystick.h
+++ b/Demos/Device/Joystick/Joystick.h
@@ -44,19 +44,12 @@
#include "Descriptors.h"
- #include <LUFA/Version.h> // Library Version Information
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality
- #include <LUFA/Drivers/Board/Joystick.h> // Joystick driver
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver
- #include <LUFA/Drivers/Board/Buttons.h> // Board Buttons driver
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management
-
- /* Task Definitions: */
- TASK(USB_Joystick_Report);
-
- /* Macros: */
- /** HID Class specific request to get the next HID report from the device. */
- #define REQ_GetReport 0x01
+ #include <LUFA/Version.h>
+ #include <LUFA/Drivers/Board/Joystick.h>
+ #include <LUFA/Drivers/Board/LEDs.h>
+ #include <LUFA/Drivers/Board/Buttons.h>
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>
/* Type Defines: */
/** Type define for the joystick HID report structure, for creating and sending HID reports to the host PC.
@@ -69,22 +62,23 @@
uint8_t Button; /**< Bit mask of the currently pressed joystick buttons */
} USB_JoystickReport_Data_t;
- /* Enums: */
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */
- enum Joystick_StatusCodes_t
- {
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */
- Status_USBEnumerating = 1, /**< USB interface is enumerating */
- Status_USBReady = 2, /**< USB interface is connected and ready */
- };
+ /* Macros: */
+ #define LEDMASK_USB_NOTREADY LEDS_LED1
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
/* Function Prototypes: */
+ void SetupHardware(void);
+
void EVENT_USB_Connect(void);
void EVENT_USB_Disconnect(void);
void EVENT_USB_ConfigurationChanged(void);
void EVENT_USB_UnhandledControlPacket(void);
+ void EVENT_USB_StartOfFrame(void);
- bool GetNextReport(USB_JoystickReport_Data_t* ReportData);
- void UpdateStatus(uint8_t CurrentStatus);
+ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);
+ void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo,
+ void* ReportData, uint16_t ReportSize);
#endif
diff --git a/Demos/Device/Joystick/makefile b/Demos/Device/Joystick/makefile
index aaf69e80b..826766c30 100644
--- a/Demos/Device/Joystick/makefile
+++ b/Demos/Device/Joystick/makefile
@@ -125,7 +125,6 @@ LUFA_PATH = ../../..
# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c \
Descriptors.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 \
@@ -136,7 +135,7 @@ SRC = $(TARGET).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.)
@@ -183,7 +182,7 @@ CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
diff --git a/Demos/Device/Keyboard/Descriptors.h b/Demos/Device/Keyboard/Descriptors.h
index 92eb7b884..0a95ca06e 100644
--- a/Demos/Device/Keyboard/Descriptors.h
+++ b/Demos/Device/Keyboard/Descriptors.h
@@ -38,30 +38,12 @@
#define _DESCRIPTORS_H_
/* Includes: */
- #include <LUFA/Drivers/USB/USB.h>
-
#include <avr/pgmspace.h>
- /* Type Defines: */
- /** Type define for the HID class specific HID descriptor, to describe the HID device's specifications. Refer to the HID
- * specification for details on the structure elements.
- */
- typedef struct
- {
- USB_Descriptor_Header_t Header;
-
- uint16_t HIDSpec;
- uint8_t CountryCode;
-
- uint8_t TotalReportDescriptors;
-
- uint8_t HIDReportType;
- uint16_t HIDReportLength;
- } USB_Descriptor_HID_t;
-
- /** Type define for the data type used to store HID report descriptor elements. */
- typedef uint8_t USB_Descriptor_HIDReport_Datatype_t;
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>
+ /* Type Defines: */
/** Type define for the device configuration descriptor structure. This must be defined in the
* application code, as the configuration descriptor contains several sub-descriptors which
* vary between devices, and which describe the device's usage to the host.
@@ -85,12 +67,6 @@
/** Size in bytes of the Keyboard HID reporting IN and OUT endpoints. */
#define KEYBOARD_EPSIZE 8
- /** Descriptor header type value, to indicate a HID class HID descriptor. */
- #define DTYPE_HID 0x21
-
- /** Descriptor header type value, to indicate a HID class HID report descriptor. */
- #define DTYPE_Report 0x22
-
/* Function Prototypes: */
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
diff --git a/Demos/Device/Keyboard/Keyboard.c b/Demos/Device/Keyboard/Keyboard.c
index 6abd193f4..d8893bfaa 100644
--- a/Demos/Device/Keyboard/Keyboard.c
+++ b/Demos/Device/Keyboard/Keyboard.c
@@ -28,397 +28,120 @@
arising out of or in connection with the use or performance of
this software.
*/
-
-/** \file
- *
- * Main source file for the Keyboard demo. This file contains the main tasks of the demo and
- * is responsible for the initial application hardware configuration.
- */
#include "Keyboard.h"
-/* Scheduler Task List */
-TASK_LIST
-{
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },
- { .Task = USB_Keyboard_Report , .TaskStatus = TASK_STOP },
-};
-
-/* Global Variables */
-/** Indicates what report mode the host has requested, true for normal HID reporting mode, false for special boot
- * protocol reporting mode.
- */
-bool UsingReportProtocol = true;
+USB_ClassInfo_HID_t Keyboard_HID_Interface =
+ {
+ .InterfaceNumber = 0,
-/** Current Idle period. This is set by the host via a Set Idle HID class request to silence the device's reports
- * for either the entire idle duration, or until the report status changes (e.g. the user presses a key).
- */
-uint16_t IdleCount = 500;
+ .ReportINEndpointNumber = KEYBOARD_EPNUM,
+ .ReportINEndpointSize = KEYBOARD_EPSIZE,
-/** Current Idle period remaining. When the IdleCount value is set, this tracks the remaining number of idle
- * milliseconds. This is separate to the IdleCount timer and is incremented and compared as the host may request
- * the current idle period via a Get Idle HID class request, thus its value must be preserved.
- */
-uint16_t IdleMSRemaining = 0;
+ .ReportOUTEndpointNumber = KEYBOARD_LEDS_EPNUM,
+ .ReportOUTEndpointSize = KEYBOARD_EPSIZE,
+
+ .ReportBufferSize = sizeof(USB_KeyboardReport_Data_t),
+ .IdleCount = 500,
+ };
-/** Main program entry point. This routine configures the hardware required by the application, then
- * starts the scheduler to run the USB management task.
- */
int main(void)
{
- /* Disable watchdog if enabled by bootloader/fuses */
- MCUSR &= ~(1 << WDRF);
- wdt_disable();
-
- /* Disable clock division */
- clock_prescale_set(clock_div_1);
-
- /* Hardware Initialization */
- Joystick_Init();
- LEDs_Init();
-
- /* Millisecond timer initialization, with output compare interrupt enabled for the idle timing */
- OCR0A = 0x7D;
- TCCR0A = (1 << WGM01);
- TCCR0B = ((1 << CS01) | (1 << CS00));
- TIMSK0 = (1 << OCIE0A);
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
-
- /* Initialize Scheduler so that it can be used */
- Scheduler_Init();
+ SetupHardware();
+
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+
+ for (;;)
+ {
+ USB_HID_USBTask(&Keyboard_HID_Interface);
+ USB_USBTask();
+ }
+}
- /* Initialize USB Subsystem */
- USB_Init();
-
- /* Scheduling - routine never returns, so put this last in the main function */
- Scheduler_Start();
+void SetupHardware()
+{
+ /* Disable watchdog if enabled by bootloader/fuses */
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable();
+
+ /* Disable clock division */
+ clock_prescale_set(clock_div_1);
+
+ /* Hardware Initialization */
+ Joystick_Init();
+ LEDs_Init();
+ Buttons_Init();
+ USB_Init();
}
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and
- * starts the library USB task to begin the enumeration and USB management process.
- */
void EVENT_USB_Connect(void)
{
- /* Start USB management task */
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);
-
- /* Indicate USB enumerating */
- UpdateStatus(Status_USBEnumerating);
-
- /* Default to report protocol on connect */
- UsingReportProtocol = true;
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
}
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
- * the status LEDs.
- */
void EVENT_USB_Disconnect(void)
{
- /* Stop running keyboard reporting and USB management tasks */
- Scheduler_SetTaskMode(USB_Keyboard_Report, TASK_STOP);
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
}
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host sets the current configuration
- * of the USB device after enumeration, and configures the keyboard device endpoints.
- */
void EVENT_USB_ConfigurationChanged(void)
{
- /* Setup Keyboard Keycode Report Endpoint */
- Endpoint_ConfigureEndpoint(KEYBOARD_EPNUM, EP_TYPE_INTERRUPT,
- ENDPOINT_DIR_IN, KEYBOARD_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- /* Setup Keyboard LED Report Endpoint */
- Endpoint_ConfigureEndpoint(KEYBOARD_LEDS_EPNUM, EP_TYPE_INTERRUPT,
- ENDPOINT_DIR_OUT, KEYBOARD_EPSIZE,
- ENDPOINT_BANK_SINGLE);
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);
- /* Indicate USB connected and ready */
- UpdateStatus(Status_USBReady);
-
- /* Start running keyboard reporting task */
- Scheduler_SetTaskMode(USB_Keyboard_Report, TASK_RUN);
+ if (!(USB_HID_ConfigureEndpoints(&Keyboard_HID_Interface)))
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
- * control requests that are not handled internally by the USB library (including the HID commands, which are
- * all issued via the control endpoint), so that they can be handled appropriately for the application.
- */
void EVENT_USB_UnhandledControlPacket(void)
{
- /* Handle HID Class specific requests */
- switch (USB_ControlRequest.bRequest)
- {
- case REQ_GetReport:
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- USB_KeyboardReport_Data_t KeyboardReportData;
-
- Endpoint_ClearSETUP();
-
- /* Create the next keyboard report for transmission to the host */
- CreateKeyboardReport(&KeyboardReportData);
-
- /* Write the report data to the control endpoint */
- Endpoint_Write_Control_Stream_LE(&KeyboardReportData, sizeof(KeyboardReportData));
-
- /* Finalize the stream transfer to send the last packet or clear the host abort */
- Endpoint_ClearOUT();
- }
-
- break;
- case REQ_SetReport:
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Wait until the LED report has been sent by the host */
- while (!(Endpoint_IsOUTReceived()));
-
- /* Read in the LED report from the host */
- uint8_t LEDStatus = Endpoint_Read_Byte();
-
- /* Process the incoming LED report */
- ProcessLEDReport(LEDStatus);
-
- /* Clear the endpoint data */
- Endpoint_ClearOUT();
-
- /* Acknowledge status stage */
- while (!(Endpoint_IsINReady()));
- Endpoint_ClearIN();
- }
-
- break;
- case REQ_GetProtocol:
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Write the current protocol flag to the host */
- Endpoint_Write_Byte(UsingReportProtocol);
-
- /* Send the flag to the host */
- Endpoint_ClearIN();
-
- /* Acknowledge status stage */
- while (!(Endpoint_IsOUTReceived()));
- Endpoint_ClearOUT();
- }
-
- break;
- case REQ_SetProtocol:
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Set or clear the flag depending on what the host indicates that the current Protocol should be */
- UsingReportProtocol = (USB_ControlRequest.wValue != 0);
-
- /* Acknowledge status stage */
- while (!(Endpoint_IsINReady()));
- Endpoint_ClearIN();
- }
-
- break;
- case REQ_SetIdle:
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Get idle period in MSB */
- IdleCount = (USB_ControlRequest.wValue >> 8);
-
- /* Acknowledge status stage */
- while (!(Endpoint_IsINReady()));
- Endpoint_ClearIN();
- }
-
- break;
- case REQ_GetIdle:
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Write the current idle duration to the host */
- Endpoint_Write_Byte(IdleCount);
-
- /* Send the flag to the host */
- Endpoint_ClearIN();
-
- /* Acknowledge status stage */
- while (!(Endpoint_IsOUTReceived()));
- Endpoint_ClearOUT();
- }
-
- break;
- }
+ USB_HID_ProcessControlPacket(&Keyboard_HID_Interface);
}
-/** ISR for the timer 0 compare vector. This ISR fires once each millisecond, and increments the
- * scheduler elapsed idle period counter when the host has set an idle period.
- */
-ISR(TIMER0_COMPA_vect, ISR_BLOCK)
+void EVENT_USB_StartOfFrame(void)
{
- /* One millisecond has elapsed, decrement the idle time remaining counter if it has not already elapsed */
- if (IdleMSRemaining)
- IdleMSRemaining--;
-}
-
-/** Fills the given HID report data structure with the next HID report to send to the host.
- *
- * \param ReportData Pointer to a HID report data structure to be filled
- */
-void CreateKeyboardReport(USB_KeyboardReport_Data_t* ReportData)
-{
- uint8_t JoyStatus_LCL = Joystick_GetStatus();
-
- /* Clear the report contents */
- memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));
-
- if (JoyStatus_LCL & JOY_UP)
- ReportData->KeyCode[0] = 0x04; // A
- else if (JoyStatus_LCL & JOY_DOWN)
- ReportData->KeyCode[0] = 0x05; // B
-
- if (JoyStatus_LCL & JOY_LEFT)
- ReportData->KeyCode[0] = 0x06; // C
- else if (JoyStatus_LCL & JOY_RIGHT)
- ReportData->KeyCode[0] = 0x07; // D
-
- if (JoyStatus_LCL & JOY_PRESS)
- ReportData->KeyCode[0] = 0x08; // E
-}
-
-/** Processes a received LED report, and updates the board LEDs states to match.
- *
- * \param LEDReport LED status report from the host
- */
-void ProcessLEDReport(uint8_t LEDReport)
-{
- uint8_t LEDMask = LEDS_LED2;
-
- if (LEDReport & 0x01) // NUM Lock
- LEDMask |= LEDS_LED1;
-
- if (LEDReport & 0x02) // CAPS Lock
- LEDMask |= LEDS_LED3;
-
- if (LEDReport & 0x04) // SCROLL Lock
- LEDMask |= LEDS_LED4;
-
- /* Set the status LEDs to the current Keyboard LED status */
- LEDs_SetAllLEDs(LEDMask);
-}
-
-/** Sends the next HID report to the host, via the keyboard data endpoint. */
-void SendNextReport(void)
-{
- static USB_KeyboardReport_Data_t PrevKeyboardReportData;
- USB_KeyboardReport_Data_t KeyboardReportData;
- bool SendReport = true;
-
- /* Create the next keyboard report for transmission to the host */
- CreateKeyboardReport(&KeyboardReportData);
-
- /* Check to see if the report data has changed - if so a report MUST be sent */
- SendReport = (memcmp(&PrevKeyboardReportData, &KeyboardReportData, sizeof(USB_KeyboardReport_Data_t)) != 0);
-
- /* Save the current report data for later comparison to check for changes */
- PrevKeyboardReportData = KeyboardReportData;
-
- /* Check if the idle period is set and has elapsed */
- if ((IdleCount != HID_IDLE_CHANGESONLY) && (!(IdleMSRemaining)))
- {
- /* Reset the idle time remaining counter, must multiply by 4 to get the duration in milliseconds */
- IdleMSRemaining = (IdleCount << 2);
-
- /* Idle period is set and has elapsed, must send a report to the host */
- SendReport = true;
- }
-
- /* Select the Keyboard Report Endpoint */
- Endpoint_SelectEndpoint(KEYBOARD_EPNUM);
-
- /* Check if Keyboard Endpoint Ready for Read/Write and if we should send a new report */
- if (Endpoint_IsReadWriteAllowed() && SendReport)
- {
- /* Write Keyboard Report Data */
- Endpoint_Write_Stream_LE(&KeyboardReportData, sizeof(KeyboardReportData));
-
- /* Finalize the stream transfer to send the last packet */
- Endpoint_ClearIN();
- }
-}
-
-/** Reads the next LED status report from the host from the LED data endpoint, if one has been sent. */
-void ReceiveNextReport(void)
-{
- /* Select the Keyboard LED Report Endpoint */
- Endpoint_SelectEndpoint(KEYBOARD_LEDS_EPNUM);
-
- /* Check if Keyboard LED Endpoint contains a packet */
- if (Endpoint_IsOUTReceived())
- {
- /* Check to see if the packet contains data */
- if (Endpoint_IsReadWriteAllowed())
- {
- /* Read in the LED report from the host */
- uint8_t LEDReport = Endpoint_Read_Byte();
-
- /* Process the read LED report from the host */
- ProcessLEDReport(LEDReport);
- }
-
- /* Handshake the OUT Endpoint - clear endpoint and ready for next report */
- Endpoint_ClearOUT();
- }
+ USB_HID_RegisterStartOfFrame(&Keyboard_HID_Interface);
}
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to
- * log to a serial port, or anything else that is suitable for status updates.
- *
- * \param CurrentStatus Current status of the system, from the Keyboard_StatusCodes_t enum
- */
-void UpdateStatus(uint8_t CurrentStatus)
+uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData)
{
- uint8_t LEDMask = LEDS_NO_LEDS;
-
- /* Set the LED mask to the appropriate LED mask based on the given status code */
- switch (CurrentStatus)
- {
- case Status_USBNotReady:
- LEDMask = (LEDS_LED1);
- break;
- case Status_USBEnumerating:
- LEDMask = (LEDS_LED1 | LEDS_LED2);
- break;
- case Status_USBReady:
- LEDMask = (LEDS_LED2 | LEDS_LED4);
- break;
- }
-
- /* Set the board LEDs to the new LED mask */
- LEDs_SetAllLEDs(LEDMask);
+ USB_KeyboardReport_Data_t* KeyboardReport = (USB_KeyboardReport_Data_t*)ReportData;
+
+ uint8_t JoyStatus_LCL = Joystick_GetStatus();
+ uint8_t ButtonStatus_LCL = Buttons_GetStatus();
+
+ if (JoyStatus_LCL & JOY_UP)
+ KeyboardReport->KeyCode[0] = 0x04; // A
+ else if (JoyStatus_LCL & JOY_DOWN)
+ KeyboardReport->KeyCode[0] = 0x05; // B
+
+ if (JoyStatus_LCL & JOY_LEFT)
+ KeyboardReport->KeyCode[0] = 0x06; // C
+ else if (JoyStatus_LCL & JOY_RIGHT)
+ KeyboardReport->KeyCode[0] = 0x07; // D
+
+ if (JoyStatus_LCL & JOY_PRESS)
+ KeyboardReport->KeyCode[0] = 0x08; // E
+
+ if (ButtonStatus_LCL & BUTTONS_BUTTON1)
+ KeyboardReport->KeyCode[0] = 0x09; // F
+
+ return sizeof(USB_KeyboardReport_Data_t);
}
-/** Function to manage HID report generation and transmission to the host, when in report mode. */
-TASK(USB_Keyboard_Report)
+void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize)
{
- /* Check if the USB system is connected to a host */
- if (USB_IsConnected)
- {
- /* Send the next keypress report to the host */
- SendNextReport();
-
- /* Process the LED report sent from the host */
- ReceiveNextReport();
- }
+ uint8_t LEDMask = LEDS_NO_LEDS;
+ uint8_t* LEDReport = (uint8_t*)ReportData;
+
+ if (*LEDReport & 0x01) // NUM Lock
+ LEDMask |= LEDS_LED1;
+
+ if (*LEDReport & 0x02) // CAPS Lock
+ LEDMask |= LEDS_LED3;
+
+ if (*LEDReport & 0x04) // SCROLL Lock
+ LEDMask |= LEDS_LED4;
+
+ LEDs_SetAllLEDs(LEDMask);
}
diff --git a/Demos/Device/Keyboard/Keyboard.h b/Demos/Device/Keyboard/Keyboard.h
index c4ed6e07c..eeb7be9b7 100644
--- a/Demos/Device/Keyboard/Keyboard.h
+++ b/Demos/Device/Keyboard/Keyboard.h
@@ -47,36 +47,12 @@
#include "Descriptors.h"
- #include <LUFA/Version.h> // Library Version Information
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality
- #include <LUFA/Drivers/Board/Joystick.h> // Joystick driver
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver
-
- /* Macros: */
- /** Idle period indicating that reports should be sent only when the inputs have changed */
- #define HID_IDLE_CHANGESONLY 0
-
- /** HID Class specific request to get the next HID report from the device. */
- #define REQ_GetReport 0x01
-
- /** HID Class specific request to get the idle timeout period of the device. */
- #define REQ_GetIdle 0x02
-
- /** HID Class specific request to send the next HID report to the device. */
- #define REQ_SetReport 0x09
-
- /** HID Class specific request to set the idle timeout period of the device. */
- #define REQ_SetIdle 0x0A
-
- /** HID Class specific request to get the current HID protocol in use, either report or boot. */
- #define REQ_GetProtocol 0x03
-
- /** HID Class specific request to set the current HID protocol in use, either report or boot. */
- #define REQ_SetProtocol 0x0B
-
- /* Task Definitions: */
- TASK(USB_Keyboard_Report);
+ #include <LUFA/Version.h>
+ #include <LUFA/Drivers/Board/Joystick.h>
+ #include <LUFA/Drivers/Board/LEDs.h>
+ #include <LUFA/Drivers/Board/Buttons.h>
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>
/* Type Defines: */
/** Type define for the keyboard HID report structure, for creating and sending HID reports to the host PC.
@@ -89,25 +65,23 @@
uint8_t KeyCode[6]; /**< Array of up to six simultaneous key codes of pressed keys */
} USB_KeyboardReport_Data_t;
- /* Enums: */
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */
- enum Keyboard_StatusCodes_t
- {
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */
- Status_USBEnumerating = 1, /**< USB interface is enumerating */
- Status_USBReady = 2, /**< USB interface is connected and ready */
- };
+ /* Macros: */
+ #define LEDMASK_USB_NOTREADY LEDS_LED1
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
/* Function Prototypes: */
+ void SetupHardware(void);
+
void EVENT_USB_Connect(void);
void EVENT_USB_Disconnect(void);
void EVENT_USB_ConfigurationChanged(void);
void EVENT_USB_UnhandledControlPacket(void);
+ void EVENT_USB_StartOfFrame(void);
- void CreateKeyboardReport(USB_KeyboardReport_Data_t* ReportData);
- void ProcessLEDReport(uint8_t LEDReport);
- void SendNextReport(void);
- void ReceiveNextReport(void);
- void UpdateStatus(uint8_t CurrentStatus);
+ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);
+ void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo,
+ void* ReportData, uint16_t ReportSize);
#endif
diff --git a/Demos/Device/Keyboard/makefile b/Demos/Device/Keyboard/makefile
index 88e4de0e6..98cda2f89 100644
--- a/Demos/Device/Keyboard/makefile
+++ b/Demos/Device/Keyboard/makefile
@@ -125,7 +125,6 @@ LUFA_PATH = ../../..
# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c \
Descriptors.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 \
@@ -136,7 +135,7 @@ SRC = $(TARGET).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.)
@@ -183,7 +182,7 @@ CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
diff --git a/Demos/Device/KeyboardMouse/Descriptors.h b/Demos/Device/KeyboardMouse/Descriptors.h
index 43c345a21..152e5111a 100644
--- a/Demos/Device/KeyboardMouse/Descriptors.h
+++ b/Demos/Device/KeyboardMouse/Descriptors.h
@@ -38,30 +38,12 @@
#define _DESCRIPTORS_H_
/* Includes: */
- #include <LUFA/Drivers/USB/USB.h>
-
#include <avr/pgmspace.h>
- /* Type Defines: */
- /** Type define for the HID class specific HID descriptor, to describe the HID device's specifications. Refer to the HID
- * specification for details on the structure elements.
- */
- typedef struct
- {
- USB_Descriptor_Header_t Header;
-
- uint16_t HIDSpec;
- uint8_t CountryCode;
-
- uint8_t TotalReportDescriptors;
-
- uint8_t HIDReportType;
- uint16_t HIDReportLength;
- } USB_Descriptor_HID_t;
-
- /** Type define for the data type used to store HID report descriptor elements. */
- typedef uint8_t USB_Descriptor_HIDReport_Datatype_t;
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>
+ /* Type Defines: */
/** Type define for the device configuration descriptor structure. This must be defined in the
* application code, as the configuration descriptor contains several sub-descriptors which
* vary between devices, and which describe the device's usage to the host.
@@ -91,12 +73,6 @@
/** Size in bytes of each of the HID reporting IN and OUT endpoints. */
#define HID_EPSIZE 8
- /** Descriptor header type value, to indicate a HID class HID descriptor. */
- #define DTYPE_HID 0x21
-
- /** Descriptor header type value, to indicate a HID class HID report descriptor. */
- #define DTYPE_Report 0x22
-
/* Function Prototypes: */
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
diff --git a/Demos/Device/KeyboardMouse/KeyboardMouse.c b/Demos/Device/KeyboardMouse/KeyboardMouse.c
index 25d633e43..8f6a573a6 100644
--- a/Demos/Device/KeyboardMouse/KeyboardMouse.c
+++ b/Demos/Device/KeyboardMouse/KeyboardMouse.c
@@ -28,35 +28,53 @@
arising out of or in connection with the use or performance of
this software.
*/
-
-/** \file
- *
- * Main source file for the KeyboardMouse demo. This file contains the main tasks of the demo and
- * is responsible for the initial application hardware configuration.
- */
#include "KeyboardMouse.h"
-/* Scheduler Task List */
-TASK_LIST
-{
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },
- { .Task = USB_Mouse , .TaskStatus = TASK_RUN },
- { .Task = USB_Keyboard , .TaskStatus = TASK_RUN },
-};
+USB_ClassInfo_HID_t Keyboard_HID_Interface =
+ {
+ .InterfaceNumber = 0,
+
+ .ReportINEndpointNumber = KEYBOARD_IN_EPNUM,
+ .ReportINEndpointSize = HID_EPSIZE,
+
+ .ReportOUTEndpointNumber = KEYBOARD_OUT_EPNUM,
+ .ReportOUTEndpointSize = HID_EPSIZE,
+
+ .ReportBufferSize = sizeof(USB_KeyboardReport_Data_t),
+
+ .IdleCount = 500,
+ };
+
+USB_ClassInfo_HID_t Mouse_HID_Interface =
+ {
+ .InterfaceNumber = 0,
-/* Global Variables */
-/** Global structure to hold the current keyboard interface HID report, for transmission to the host */
-USB_KeyboardReport_Data_t KeyboardReportData;
+ .ReportINEndpointNumber = MOUSE_IN_EPNUM,
+ .ReportINEndpointSize = HID_EPSIZE,
-/** Global structure to hold the current mouse interface HID report, for transmission to the host */
-USB_MouseReport_Data_t MouseReportData;
+ .ReportBufferSize = sizeof(USB_MouseReport_Data_t),
-/** Main program entry point. This routine configures the hardware required by the application, then
- * starts the scheduler to run the USB management task.
- */
+ .ReportOUTEndpointNumber = 0,
+ .ReportOUTEndpointSize = 0,
+ };
+
int main(void)
{
+ SetupHardware();
+
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+
+ for (;;)
+ {
+ USB_HID_USBTask(&Keyboard_HID_Interface);
+ USB_HID_USBTask(&Mouse_HID_Interface);
+ USB_USBTask();
+ }
+}
+
+void SetupHardware()
+{
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
@@ -67,284 +85,111 @@ int main(void)
/* Hardware Initialization */
Joystick_Init();
LEDs_Init();
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
-
- /* Initialize Scheduler so that it can be used */
- Scheduler_Init();
-
- /* Initialize USB Subsystem */
- USB_Init();
-
- /* Scheduling - routine never returns, so put this last in the main function */
- Scheduler_Start();
+ USB_Init();
}
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and
- * starts the library USB task to begin the enumeration and USB management process.
- */
void EVENT_USB_Connect(void)
{
- /* Start USB management task */
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);
-
- /* Indicate USB enumerating */
- UpdateStatus(Status_USBEnumerating);
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
}
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
- * the status LEDs and stops the USB management task.
- */
void EVENT_USB_Disconnect(void)
{
- /* Stop running HID reporting and USB management tasks */
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
}
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host sets the current configuration
- * of the USB device after enumeration, and configures the keyboard and mouse device endpoints.
- */
void EVENT_USB_ConfigurationChanged(void)
{
- /* Setup Keyboard Report Endpoint */
- Endpoint_ConfigureEndpoint(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT,
- ENDPOINT_DIR_IN, HID_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- /* Setup Keyboard LED Report Endpoint */
- Endpoint_ConfigureEndpoint(KEYBOARD_OUT_EPNUM, EP_TYPE_INTERRUPT,
- ENDPOINT_DIR_OUT, HID_EPSIZE,
- ENDPOINT_BANK_SINGLE);
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);
- /* Setup Mouse Report Endpoint */
- Endpoint_ConfigureEndpoint(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT,
- ENDPOINT_DIR_IN, HID_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- /* Indicate USB connected and ready */
- UpdateStatus(Status_USBReady);
+ if (!(USB_HID_ConfigureEndpoints(&Keyboard_HID_Interface)))
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
+
+ if (!(USB_HID_ConfigureEndpoints(&Mouse_HID_Interface)))
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
- * control requests that are not handled internally by the USB library (including the HID commands, which are
- * all issued via the control endpoint), so that they can be handled appropriately for the application.
- */
void EVENT_USB_UnhandledControlPacket(void)
{
- uint8_t* ReportData;
- uint8_t ReportSize;
-
- /* Handle HID Class specific requests */
- switch (USB_ControlRequest.bRequest)
- {
- case REQ_GetReport:
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Determine if it is the mouse or the keyboard data that is being requested */
- if (!(USB_ControlRequest.wIndex))
- {
- ReportData = (uint8_t*)&KeyboardReportData;
- ReportSize = sizeof(KeyboardReportData);
- }
- else
- {
- ReportData = (uint8_t*)&MouseReportData;
- ReportSize = sizeof(MouseReportData);
- }
-
- /* Write the report data to the control endpoint */
- Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
-
- /* Clear the report data afterwards */
- memset(ReportData, 0, ReportSize);
-
- /* Finalize the stream transfer to send the last packet or clear the host abort */
- Endpoint_ClearOUT();
- }
-
- break;
- case REQ_SetReport:
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Wait until the LED report has been sent by the host */
- while (!(Endpoint_IsOUTReceived()));
-
- /* Read in the LED report from the host */
- uint8_t LEDStatus = Endpoint_Read_Byte();
- uint8_t LEDMask = LEDS_LED2;
-
- if (LEDStatus & 0x01) // NUM Lock
- LEDMask |= LEDS_LED1;
-
- if (LEDStatus & 0x02) // CAPS Lock
- LEDMask |= LEDS_LED3;
-
- if (LEDStatus & 0x04) // SCROLL Lock
- LEDMask |= LEDS_LED4;
-
- /* Set the status LEDs to the current HID LED status */
- LEDs_SetAllLEDs(LEDMask);
-
- /* Clear the endpoint data */
- Endpoint_ClearOUT();
-
- /* Acknowledge status stage */
- while (!(Endpoint_IsINReady()));
- Endpoint_ClearIN();
- }
-
- break;
- }
+ USB_HID_ProcessControlPacket(&Keyboard_HID_Interface);
+ USB_HID_ProcessControlPacket(&Mouse_HID_Interface);
}
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to
- * log to a serial port, or anything else that is suitable for status updates.
- *
- * \param CurrentStatus Current status of the system, from the KeyboardMouse_StatusCodes_t enum
- */
-void UpdateStatus(uint8_t CurrentStatus)
+void EVENT_USB_StartOfFrame(void)
{
- uint8_t LEDMask = LEDS_NO_LEDS;
-
- /* Set the LED mask to the appropriate LED mask based on the given status code */
- switch (CurrentStatus)
- {
- case Status_USBNotReady:
- LEDMask = (LEDS_LED1);
- break;
- case Status_USBEnumerating:
- LEDMask = (LEDS_LED1 | LEDS_LED2);
- break;
- case Status_USBReady:
- LEDMask = (LEDS_LED2 | LEDS_LED4);
- break;
- }
-
- /* Set the board LEDs to the new LED mask */
- LEDs_SetAllLEDs(LEDMask);
+ USB_HID_RegisterStartOfFrame(&Keyboard_HID_Interface);
+ USB_HID_RegisterStartOfFrame(&Mouse_HID_Interface);
}
-/** Keyboard task. This generates the next keyboard HID report for the host, and transmits it via the
- * keyboard IN endpoint when the host is ready for more data. Additionally, it processes host LED status
- * reports sent to the device via the keyboard OUT reporting endpoint.
- */
-TASK(USB_Keyboard)
+uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData)
{
- uint8_t JoyStatus_LCL = Joystick_GetStatus();
+ uint8_t JoyStatus_LCL = Joystick_GetStatus();
+ uint8_t ButtonStatus_LCL = Buttons_GetStatus();
- /* Check if board button is not pressed, if so mouse mode enabled */
- if (!(Buttons_GetStatus() & BUTTONS_BUTTON1))
+ if (HIDInterfaceInfo == &Keyboard_HID_Interface)
{
+ USB_KeyboardReport_Data_t* KeyboardReport = (USB_KeyboardReport_Data_t*)ReportData;
+
+ /* If first board button not being held down, no keyboard report */
+ if (!(ButtonStatus_LCL & BUTTONS_BUTTON1))
+ return 0;
+
if (JoyStatus_LCL & JOY_UP)
- KeyboardReportData.KeyCode[0] = 0x04; // A
+ KeyboardReport->KeyCode[0] = 0x04; // A
else if (JoyStatus_LCL & JOY_DOWN)
- KeyboardReportData.KeyCode[0] = 0x05; // B
+ KeyboardReport->KeyCode[0] = 0x05; // B
if (JoyStatus_LCL & JOY_LEFT)
- KeyboardReportData.KeyCode[0] = 0x06; // C
+ KeyboardReport->KeyCode[0] = 0x06; // C
else if (JoyStatus_LCL & JOY_RIGHT)
- KeyboardReportData.KeyCode[0] = 0x07; // D
+ KeyboardReport->KeyCode[0] = 0x07; // D
if (JoyStatus_LCL & JOY_PRESS)
- KeyboardReportData.KeyCode[0] = 0x08; // E
+ KeyboardReport->KeyCode[0] = 0x08; // E
+
+ return sizeof(USB_KeyboardReport_Data_t);
}
-
- /* Check if the USB system is connected to a host and report protocol mode is enabled */
- if (USB_IsConnected)
+ else
{
- /* Select the Keyboard Report Endpoint */
- Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
-
- /* Check if Keyboard Endpoint Ready for Read/Write */
- if (Endpoint_IsReadWriteAllowed())
- {
- /* Write Keyboard Report Data */
- Endpoint_Write_Stream_LE(&KeyboardReportData, sizeof(KeyboardReportData));
-
- /* Finalize the stream transfer to send the last packet */
- Endpoint_ClearIN();
-
- /* Clear the report data afterwards */
- memset(&KeyboardReportData, 0, sizeof(KeyboardReportData));
- }
+ USB_MouseReport_Data_t* MouseReport = (USB_MouseReport_Data_t*)ReportData;
- /* Select the Keyboard LED Report Endpoint */
- Endpoint_SelectEndpoint(KEYBOARD_OUT_EPNUM);
-
- /* Check if Keyboard LED Endpoint Ready for Read/Write */
- if (Endpoint_IsReadWriteAllowed())
- {
- /* Read in the LED report from the host */
- uint8_t LEDStatus = Endpoint_Read_Byte();
- uint8_t LEDMask = LEDS_LED2;
-
- if (LEDStatus & 0x01) // NUM Lock
- LEDMask |= LEDS_LED1;
-
- if (LEDStatus & 0x02) // CAPS Lock
- LEDMask |= LEDS_LED3;
-
- if (LEDStatus & 0x04) // SCROLL Lock
- LEDMask |= LEDS_LED4;
-
- /* Set the status LEDs to the current Keyboard LED status */
- LEDs_SetAllLEDs(LEDMask);
-
- /* Handshake the OUT Endpoint - clear endpoint and ready for next report */
- Endpoint_ClearOUT();
- }
- }
-}
-
-/** Mouse task. This generates the next mouse HID report for the host, and transmits it via the
- * mouse IN endpoint when the host is ready for more data.
- */
-TASK(USB_Mouse)
-{
- uint8_t JoyStatus_LCL = Joystick_GetStatus();
-
- /* Check if board button is pressed, if so mouse mode enabled */
- if (Buttons_GetStatus() & BUTTONS_BUTTON1)
- {
+ /* If first board button being held down, no mouse report */
+ if (ButtonStatus_LCL & BUTTONS_BUTTON1)
+ return 0;
+
if (JoyStatus_LCL & JOY_UP)
- MouseReportData.Y = 1;
+ MouseReport->Y = -1;
else if (JoyStatus_LCL & JOY_DOWN)
- MouseReportData.Y = -1;
+ MouseReport->Y = 1;
if (JoyStatus_LCL & JOY_RIGHT)
- MouseReportData.X = 1;
+ MouseReport->X = 1;
else if (JoyStatus_LCL & JOY_LEFT)
- MouseReportData.X = -1;
+ MouseReport->X = -1;
if (JoyStatus_LCL & JOY_PRESS)
- MouseReportData.Button = (1 << 0);
+ MouseReport->Button = (1 << 0);
+
+ return sizeof(USB_MouseReport_Data_t);
}
+}
- /* Check if the USB system is connected to a host and report protocol mode is enabled */
- if (USB_IsConnected)
+void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize)
+{
+ if (HIDInterfaceInfo == &Keyboard_HID_Interface)
{
- /* Select the Mouse Report Endpoint */
- Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
-
- /* Check if Mouse Endpoint Ready for Read/Write */
- if (Endpoint_IsReadWriteAllowed())
- {
- /* Write Mouse Report Data */
- Endpoint_Write_Stream_LE(&MouseReportData, sizeof(MouseReportData));
+ uint8_t LEDMask = LEDS_NO_LEDS;
+ uint8_t* LEDReport = (uint8_t*)ReportData;
- /* Finalize the stream transfer to send the last packet */
- Endpoint_ClearIN();
+ if (*LEDReport & 0x01) // NUM Lock
+ LEDMask |= LEDS_LED1;
+
+ if (*LEDReport & 0x02) // CAPS Lock
+ LEDMask |= LEDS_LED3;
- /* Clear the report data afterwards */
- memset(&MouseReportData, 0, sizeof(MouseReportData));
- }
+ if (*LEDReport & 0x04) // SCROLL Lock
+ LEDMask |= LEDS_LED4;
+
+ LEDs_SetAllLEDs(LEDMask);
}
-}
+} \ No newline at end of file
diff --git a/Demos/Device/KeyboardMouse/KeyboardMouse.h b/Demos/Device/KeyboardMouse/KeyboardMouse.h
index e3f943402..a5c3c5db2 100644
--- a/Demos/Device/KeyboardMouse/KeyboardMouse.h
+++ b/Demos/Device/KeyboardMouse/KeyboardMouse.h
@@ -41,38 +41,18 @@
#include "Descriptors.h"
- #include <LUFA/Version.h> // Library Version Information
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality
- #include <LUFA/Drivers/Board/Joystick.h> // Joystick driver
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver
- #include <LUFA/Drivers/Board/Buttons.h> // Board Buttons driver
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management
-
- /* Task Definitions: */
- TASK(USB_Keyboard);
- TASK(USB_Mouse);
+ #include <LUFA/Version.h>
+ #include <LUFA/Drivers/Board/Joystick.h>
+ #include <LUFA/Drivers/Board/LEDs.h>
+ #include <LUFA/Drivers/Board/Buttons.h>
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>
- /* Enums: */
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */
- enum KeyboardMouse_StatusCodes_t
- {
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */
- Status_USBEnumerating = 1, /**< USB interface is enumerating */
- Status_USBReady = 2, /**< USB interface is connected and ready */
- };
-
/* Macros: */
- /** HID Class specific request to get the next HID report from the device. */
- #define REQ_GetReport 0x01
-
- /** HID Class specific request to send the next HID report to the device. */
- #define REQ_SetReport 0x09
-
- /** HID Class specific request to get the current HID protocol in use, either report or boot. */
- #define REQ_GetProtocol 0x03
-
- /** HID Class specific request to set the current HID protocol in use, either report or boot. */
- #define REQ_SetProtocol 0x0B
+ #define LEDMASK_USB_NOTREADY LEDS_LED1
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
/* Type Defines: */
/** Type define for the keyboard HID report structure, for creating and sending HID reports to the host PC.
@@ -96,11 +76,16 @@
} USB_MouseReport_Data_t;
/* Function Prototypes: */
+ void SetupHardware(void);
+
void EVENT_USB_Connect(void);
void EVENT_USB_Disconnect(void);
void EVENT_USB_ConfigurationChanged(void);
void EVENT_USB_UnhandledControlPacket(void);
+ void EVENT_USB_StartOfFrame(void);
- void UpdateStatus(uint8_t CurrentStatus);
+ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);
+ void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo,
+ void* ReportData, uint16_t ReportSize);
#endif
diff --git a/Demos/Device/KeyboardMouse/makefile b/Demos/Device/KeyboardMouse/makefile
index c6b34d96e..ddad7d24b 100644
--- a/Demos/Device/KeyboardMouse/makefile
+++ b/Demos/Device/KeyboardMouse/makefile
@@ -125,7 +125,6 @@ LUFA_PATH = ../../..
# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c \
Descriptors.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 \
@@ -136,7 +135,7 @@ SRC = $(TARGET).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.)
@@ -183,7 +182,7 @@ CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
diff --git a/Demos/Device/MIDI/makefile b/Demos/Device/MIDI/makefile
index 18fc3b154..485cdc710 100644
--- a/Demos/Device/MIDI/makefile
+++ b/Demos/Device/MIDI/makefile
@@ -183,7 +183,7 @@ CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
diff --git a/Demos/Device/MassStorage/Lib/DataflashManager.c b/Demos/Device/MassStorage/Lib/DataflashManager.c
index 4b624190f..87edef12b 100644
--- a/Demos/Device/MassStorage/Lib/DataflashManager.c
+++ b/Demos/Device/MassStorage/Lib/DataflashManager.c
@@ -46,7 +46,7 @@
* \param BlockAddress Data block starting address for the write sequence
* \param TotalBlocks Number of blocks of data to write
*/
-void DataflashManager_WriteBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks)
+void DataflashManager_WriteBlocks(USB_ClassInfo_MS_t* MSInterfaceInfo, const uint32_t BlockAddress, uint16_t TotalBlocks)
{
uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);
uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);
@@ -142,7 +142,7 @@ void DataflashManager_WriteBlocks(const uint32_t BlockAddress, uint16_t TotalBlo
BytesInBlockDiv16++;
/* Check if the current command is being aborted by the host */
- if (IsMassStoreReset)
+ if (MSInterfaceInfo->IsMassStoreReset)
return;
}
@@ -171,7 +171,7 @@ void DataflashManager_WriteBlocks(const uint32_t BlockAddress, uint16_t TotalBlo
* \param BlockAddress Data block starting address for the read sequence
* \param TotalBlocks Number of blocks of data to read
*/
-void DataflashManager_ReadBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks)
+void DataflashManager_ReadBlocks(USB_ClassInfo_MS_t* MSInterfaceInfo, const uint32_t BlockAddress, uint16_t TotalBlocks)
{
uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);
uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);
@@ -250,7 +250,7 @@ void DataflashManager_ReadBlocks(const uint32_t BlockAddress, uint16_t TotalBloc
BytesInBlockDiv16++;
/* Check if the current command is being aborted by the host */
- if (IsMassStoreReset)
+ if (MSInterfaceInfo->IsMassStoreReset)
return;
}
@@ -341,11 +341,7 @@ void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t Tota
CurrDFPageByteDiv16++;
/* Increment the block 16 byte block counter */
- BytesInBlockDiv16++;
-
- /* Check if the current command is being aborted by the host */
- if (IsMassStoreReset)
- return;
+ BytesInBlockDiv16++;
}
/* Decrement the blocks remaining counter and reset the sub block counter */
@@ -421,10 +417,6 @@ void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, uint16_t Total
/* Increment the block 16 byte block counter */
BytesInBlockDiv16++;
-
- /* Check if the current command is being aborted by the host */
- if (IsMassStoreReset)
- return;
}
/* Decrement the blocks remaining counter */
diff --git a/Demos/Device/MassStorage/Lib/DataflashManager.h b/Demos/Device/MassStorage/Lib/DataflashManager.h
index 1332fd3a3..b828051aa 100644
--- a/Demos/Device/MassStorage/Lib/DataflashManager.h
+++ b/Demos/Device/MassStorage/Lib/DataflashManager.h
@@ -64,8 +64,8 @@
#define VIRTUAL_MEMORY_BLOCKS (VIRTUAL_MEMORY_BYTES / VIRTUAL_MEMORY_BLOCK_SIZE)
/* Function Prototypes: */
- void DataflashManager_WriteBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks);
- void DataflashManager_ReadBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks);
+ void DataflashManager_WriteBlocks(USB_ClassInfo_MS_t* MSInterfaceInfo, const uint32_t BlockAddress, uint16_t TotalBlocks);
+ void DataflashManager_ReadBlocks(USB_ClassInfo_MS_t* MSInterfaceInfo, const uint32_t BlockAddress, uint16_t TotalBlocks);
void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks,
uint8_t* BufferPtr) ATTR_NON_NULL_PTR_ARG(3);
void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks,
diff --git a/Demos/Device/MassStorage/Lib/SCSI.c b/Demos/Device/MassStorage/Lib/SCSI.c
index 5993a546d..8f3167a47 100644
--- a/Demos/Device/MassStorage/Lib/SCSI.c
+++ b/Demos/Device/MassStorage/Lib/SCSI.c
@@ -84,37 +84,37 @@ SCSI_Request_Sense_Response_t SenseData =
* to the appropriate SCSI command handling routine if the issued command is supported by the device, else it returns
* a command failure due to a ILLEGAL REQUEST.
*/
-void SCSI_DecodeSCSICommand(void)
+bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_t* MSInterfaceInfo)
{
bool CommandSuccess = false;
/* Run the appropriate SCSI command hander function based on the passed command */
- switch (CommandBlock.SCSICommandData[0])
+ switch (MSInterfaceInfo->CommandBlock.SCSICommandData[0])
{
case SCSI_CMD_INQUIRY:
- CommandSuccess = SCSI_Command_Inquiry();
+ CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo);
break;
case SCSI_CMD_REQUEST_SENSE:
- CommandSuccess = SCSI_Command_Request_Sense();
+ CommandSuccess = SCSI_Command_Request_Sense(MSInterfaceInfo);
break;
case SCSI_CMD_READ_CAPACITY_10:
- CommandSuccess = SCSI_Command_Read_Capacity_10();
+ CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo);
break;
case SCSI_CMD_SEND_DIAGNOSTIC:
- CommandSuccess = SCSI_Command_Send_Diagnostic();
+ CommandSuccess = SCSI_Command_Send_Diagnostic(MSInterfaceInfo);
break;
case SCSI_CMD_WRITE_10:
- CommandSuccess = SCSI_Command_ReadWrite_10(DATA_WRITE);
+ CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
break;
case SCSI_CMD_READ_10:
- CommandSuccess = SCSI_Command_ReadWrite_10(DATA_READ);
+ CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
break;
case SCSI_CMD_TEST_UNIT_READY:
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
case SCSI_CMD_VERIFY_10:
/* These commands should just succeed, no handling required */
CommandSuccess = true;
- CommandBlock.DataTransferLength = 0;
+ MSInterfaceInfo->CommandBlock.DataTransferLength = 0;
break;
default:
/* Update the SENSE key to reflect the invalid command */
@@ -123,22 +123,18 @@ void SCSI_DecodeSCSICommand(void)
SCSI_ASENSEQ_NO_QUALIFIER);
break;
}
-
+
/* Check if command was successfully processed */
if (CommandSuccess)
{
- /* Command succeeded - set the CSW status and update the SENSE key */
- CommandStatus.Status = Command_Pass;
-
SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
- SCSI_ASENSEQ_NO_QUALIFIER);
- }
- else
- {
- /* Command failed - set the CSW status - failed command function updates the SENSE key */
- CommandStatus.Status = Command_Fail;
+ SCSI_ASENSEQ_NO_QUALIFIER);
+
+ return true;
}
+
+ return false;
}
/** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features
@@ -146,16 +142,16 @@ void SCSI_DecodeSCSICommand(void)
*
* \return Boolean true if the command completed successfully, false otherwise.
*/
-static bool SCSI_Command_Inquiry(void)
+static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_t* MSInterfaceInfo)
{
- uint16_t AllocationLength = (((uint16_t)CommandBlock.SCSICommandData[3] << 8) |
- CommandBlock.SCSICommandData[4]);
+ uint16_t AllocationLength = (((uint16_t)MSInterfaceInfo->CommandBlock.SCSICommandData[3] << 8) |
+ MSInterfaceInfo->CommandBlock.SCSICommandData[4]);
uint16_t BytesTransferred = (AllocationLength < sizeof(InquiryData))? AllocationLength :
sizeof(InquiryData);
/* Only the standard INQUIRY data is supported, check if any optional INQUIRY bits set */
- if ((CommandBlock.SCSICommandData[1] & ((1 << 0) | (1 << 1))) ||
- CommandBlock.SCSICommandData[2])
+ if ((MSInterfaceInfo->CommandBlock.SCSICommandData[1] & ((1 << 0) | (1 << 1))) ||
+ MSInterfaceInfo->CommandBlock.SCSICommandData[2])
{
/* Optional but unsupported bits set - update the SENSE key and fail the request */
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
@@ -164,20 +160,19 @@ static bool SCSI_Command_Inquiry(void)
return false;
}
-
- /* Write the INQUIRY data to the endpoint */
- Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, StreamCallback_AbortOnMassStoreReset);
+
+ Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NO_STREAM_CALLBACK);
uint8_t PadBytes[AllocationLength - BytesTransferred];
/* Pad out remaining bytes with 0x00 */
- Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), StreamCallback_AbortOnMassStoreReset);
+ Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), NO_STREAM_CALLBACK);
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
/* Succeed the command and update the bytes transferred counter */
- CommandBlock.DataTransferLength -= BytesTransferred;
+ MSInterfaceInfo->CommandBlock.DataTransferLength -= BytesTransferred;
return true;
}
@@ -187,24 +182,19 @@ static bool SCSI_Command_Inquiry(void)
*
* \return Boolean true if the command completed successfully, false otherwise.
*/
-static bool SCSI_Command_Request_Sense(void)
+static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_t* MSInterfaceInfo)
{
- uint8_t AllocationLength = CommandBlock.SCSICommandData[4];
+ uint8_t AllocationLength = MSInterfaceInfo->CommandBlock.SCSICommandData[4];
uint8_t BytesTransferred = (AllocationLength < sizeof(SenseData))? AllocationLength : sizeof(SenseData);
- /* Send the SENSE data - this indicates to the host the status of the last command */
- Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, StreamCallback_AbortOnMassStoreReset);
-
uint8_t PadBytes[AllocationLength - BytesTransferred];
-
- /* Pad out remaining bytes with 0x00 */
- Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), StreamCallback_AbortOnMassStoreReset);
- /* Finalize the stream transfer to send the last packet */
+ Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, NO_STREAM_CALLBACK);
+ Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), NO_STREAM_CALLBACK);
Endpoint_ClearIN();
/* Succeed the command and update the bytes transferred counter */
- CommandBlock.DataTransferLength -= BytesTransferred;
+ MSInterfaceInfo->CommandBlock.DataTransferLength -= BytesTransferred;
return true;
}
@@ -214,23 +204,17 @@ static bool SCSI_Command_Request_Sense(void)
*
* \return Boolean true if the command completed successfully, false otherwise.
*/
-static bool SCSI_Command_Read_Capacity_10(void)
+static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_t* MSInterfaceInfo)
{
- /* Send the total number of logical blocks in the current LUN */
- Endpoint_Write_DWord_BE(LUN_MEDIA_BLOCKS - 1);
+ uint32_t TotalLUNs = (LUN_MEDIA_BLOCKS - 1);
+ uint32_t MediaBlockSize = VIRTUAL_MEMORY_BLOCK_SIZE;
- /* Send the logical block size of the device (must be 512 bytes) */
- Endpoint_Write_DWord_BE(VIRTUAL_MEMORY_BLOCK_SIZE);
-
- /* Check if the current command is being aborted by the host */
- if (IsMassStoreReset)
- return false;
-
- /* Send the endpoint data packet to the host */
+ Endpoint_Write_Stream_BE(&TotalLUNs, sizeof(TotalLUNs), NO_STREAM_CALLBACK);
+ Endpoint_Write_Stream_BE(&MediaBlockSize, sizeof(MediaBlockSize), NO_STREAM_CALLBACK);
Endpoint_ClearIN();
-
+
/* Succeed the command and update the bytes transferred counter */
- CommandBlock.DataTransferLength -= 8;
+ MSInterfaceInfo->CommandBlock.DataTransferLength -= 8;
return true;
}
@@ -241,12 +225,12 @@ static bool SCSI_Command_Read_Capacity_10(void)
*
* \return Boolean true if the command completed successfully, false otherwise.
*/
-static bool SCSI_Command_Send_Diagnostic(void)
+static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_t* MSInterfaceInfo)
{
uint8_t ReturnByte;
/* Check to see if the SELF TEST bit is not set */
- if (!(CommandBlock.SCSICommandData[1] & (1 << 2)))
+ if (!(MSInterfaceInfo->CommandBlock.SCSICommandData[1] & (1 << 2)))
{
/* Only self-test supported - update SENSE key and fail the command */
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
@@ -293,7 +277,7 @@ static bool SCSI_Command_Send_Diagnostic(void)
#endif
/* Succeed the command and update the bytes transferred counter */
- CommandBlock.DataTransferLength = 0;
+ MSInterfaceInfo->CommandBlock.DataTransferLength = 0;
return true;
}
@@ -306,20 +290,20 @@ static bool SCSI_Command_Send_Diagnostic(void)
*
* \return Boolean true if the command completed successfully, false otherwise.
*/
-static bool SCSI_Command_ReadWrite_10(const bool IsDataRead)
+static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_t* MSInterfaceInfo, const bool IsDataRead)
{
uint32_t BlockAddress;
uint16_t TotalBlocks;
/* Load in the 32-bit block address (SCSI uses big-endian, so have to do it byte-by-byte) */
- ((uint8_t*)&BlockAddress)[3] = CommandBlock.SCSICommandData[2];
- ((uint8_t*)&BlockAddress)[2] = CommandBlock.SCSICommandData[3];
- ((uint8_t*)&BlockAddress)[1] = CommandBlock.SCSICommandData[4];
- ((uint8_t*)&BlockAddress)[0] = CommandBlock.SCSICommandData[5];
+ ((uint8_t*)&BlockAddress)[3] = MSInterfaceInfo->CommandBlock.SCSICommandData[2];
+ ((uint8_t*)&BlockAddress)[2] = MSInterfaceInfo->CommandBlock.SCSICommandData[3];
+ ((uint8_t*)&BlockAddress)[1] = MSInterfaceInfo->CommandBlock.SCSICommandData[4];
+ ((uint8_t*)&BlockAddress)[0] = MSInterfaceInfo->CommandBlock.SCSICommandData[5];
/* Load in the 16-bit total blocks (SCSI uses big-endian, so have to do it byte-by-byte) */
- ((uint8_t*)&TotalBlocks)[1] = CommandBlock.SCSICommandData[7];
- ((uint8_t*)&TotalBlocks)[0] = CommandBlock.SCSICommandData[8];
+ ((uint8_t*)&TotalBlocks)[1] = MSInterfaceInfo->CommandBlock.SCSICommandData[7];
+ ((uint8_t*)&TotalBlocks)[0] = MSInterfaceInfo->CommandBlock.SCSICommandData[8];
/* Check if the block address is outside the maximum allowable value for the LUN */
if (BlockAddress >= LUN_MEDIA_BLOCKS)
@@ -334,17 +318,17 @@ static bool SCSI_Command_ReadWrite_10(const bool IsDataRead)
#if (TOTAL_LUNS > 1)
/* Adjust the given block address to the real media address based on the selected LUN */
- BlockAddress += ((uint32_t)CommandBlock.LUN * LUN_MEDIA_BLOCKS);
+ BlockAddress += ((uint32_t)MSInterfaceInfo->CommandBlock.LUN * LUN_MEDIA_BLOCKS);
#endif
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
if (IsDataRead == DATA_READ)
- DataflashManager_ReadBlocks(BlockAddress, TotalBlocks);
+ DataflashManager_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
else
- DataflashManager_WriteBlocks(BlockAddress, TotalBlocks);
+ DataflashManager_WriteBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
/* Update the bytes transferred counter and succeed the command */
- CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);
+ MSInterfaceInfo->CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);
return true;
}
diff --git a/Demos/Device/MassStorage/Lib/SCSI.h b/Demos/Device/MassStorage/Lib/SCSI.h
index d7693cafb..3fd751dee 100644
--- a/Demos/Device/MassStorage/Lib/SCSI.h
+++ b/Demos/Device/MassStorage/Lib/SCSI.h
@@ -40,9 +40,8 @@
#include <avr/io.h>
#include <avr/pgmspace.h>
- #include <LUFA/Common/Common.h> // Function Attribute, Atomic, Debug and ISR Macros
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/MassStorage.h>
#include "MassStorage.h"
#include "Descriptors.h"
@@ -63,16 +62,16 @@
SenseData.AdditionalSenseQualifier = aqual; }MACROE
/** Macro for the SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */
- #define DATA_READ true
+ #define DATA_READ true
/** Macro for the SCSI_Command_ReadWrite_10() function, to indicate that data is to be written to the storage medium. */
- #define DATA_WRITE false
+ #define DATA_WRITE false
/** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a Block Media device. */
- #define DEVICE_TYPE_BLOCK 0x00
+ #define DEVICE_TYPE_BLOCK 0x00
/** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a CD-ROM device. */
- #define DEVICE_TYPE_CDROM 0x05
+ #define DEVICE_TYPE_CDROM 0x05
/* Type Defines: */
/** Type define for a SCSI response structure to a SCSI INQUIRY command. For details of the
@@ -136,14 +135,14 @@
} SCSI_Request_Sense_Response_t;
/* Function Prototypes: */
- void SCSI_DecodeSCSICommand(void);
+ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_t* MSInterfaceInfo);
#if defined(INCLUDE_FROM_SCSI_C)
- static bool SCSI_Command_Inquiry(void);
- static bool SCSI_Command_Request_Sense(void);
- static bool SCSI_Command_Read_Capacity_10(void);
- static bool SCSI_Command_Send_Diagnostic(void);
- static bool SCSI_Command_ReadWrite_10(const bool IsDataRead);
+ static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_t* MSInterfaceInfo);
+ static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_t* MSInterfaceInfo);
+ static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_t* MSInterfaceInfo);
+ static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_t* MSInterfaceInfo);
+ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_t* MSInterfaceInfo, const bool IsDataRead);
#endif
#endif
diff --git a/Demos/Device/MassStorage/MassStorage.c b/Demos/Device/MassStorage/MassStorage.c
index 72a230219..8e2b9f450 100644
--- a/Demos/Device/MassStorage/MassStorage.c
+++ b/Demos/Device/MassStorage/MassStorage.c
@@ -28,36 +28,36 @@
this software.
*/
-/** \file
- *
- * Main source file for the Mass Storage demo. This file contains the main tasks of the demo and
- * is responsible for the initial application hardware configuration.
- */
-
-#define INCLUDE_FROM_MASSSTORAGE_C
#include "MassStorage.h"
-/* Scheduler Task List */
-TASK_LIST
-{
- { .Task = USB_MassStorage , .TaskStatus = TASK_STOP },
-};
+USB_ClassInfo_MS_t Disk_MS_Interface =
+ {
+ .InterfaceNumber = 0,
-/* Global Variables */
-/** Structure to hold the latest Command Block Wrapper issued by the host, containing a SCSI command to execute. */
-CommandBlockWrapper_t CommandBlock;
+ .DataINEndpointNumber = MASS_STORAGE_IN_EPNUM,
+ .DataINEndpointSize = MASS_STORAGE_IO_EPSIZE,
-/** Structure to hold the latest Command Status Wrapper to return to the host, containing the status of the last issued command. */
-CommandStatusWrapper_t CommandStatus = { .Signature = CSW_SIGNATURE };
+ .DataOUTEndpointNumber = MASS_STORAGE_OUT_EPNUM,
+ .DataOUTEndpointSize = MASS_STORAGE_IO_EPSIZE,
-/** Flag to asynchronously abort any in-progress data transfers upon the reception of a mass storage reset command. */
-volatile bool IsMassStoreReset = false;
+ .TotalLUNs = TOTAL_LUNS,
+ };
-/** Main program entry point. This routine configures the hardware required by the application, then
- * starts the scheduler to run the application tasks.
- */
int main(void)
{
+ SetupHardware();
+
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+
+ for (;;)
+ {
+ USB_MS_USBTask(&Disk_MS_Interface);
+ USB_USBTask();
+ }
+}
+
+void SetupHardware(void)
+{
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
@@ -68,303 +68,42 @@ int main(void)
/* Hardware Initialization */
LEDs_Init();
Dataflash_Init(SPI_SPEED_FCPU_DIV_2);
+ USB_Init();
/* Clear Dataflash sector protections, if enabled */
DataflashManager_ResetDataflashProtections();
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
-
- /* Initialize Scheduler so that it can be used */
- Scheduler_Init();
-
- /* Initialize USB Subsystem */
- USB_Init();
-
- /* Scheduling - routine never returns, so put this last in the main function */
- Scheduler_Start();
}
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */
void EVENT_USB_Connect(void)
{
- /* Indicate USB enumerating */
- UpdateStatus(Status_USBEnumerating);
-
- /* Reset the MSReset flag upon connection */
- IsMassStoreReset = false;
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
}
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
- * the status LEDs and stops the Mass Storage management task.
- */
void EVENT_USB_Disconnect(void)
{
- /* Stop running mass storage task */
- Scheduler_SetTaskMode(USB_MassStorage, TASK_STOP);
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
}
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
- * of the USB device after enumeration - the device endpoints are configured and the Mass Storage management task started.
- */
void EVENT_USB_ConfigurationChanged(void)
{
- /* Setup Mass Storage In and Out Endpoints */
- Endpoint_ConfigureEndpoint(MASS_STORAGE_IN_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_IN, MASS_STORAGE_IO_EPSIZE,
- ENDPOINT_BANK_DOUBLE);
-
- Endpoint_ConfigureEndpoint(MASS_STORAGE_OUT_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_OUT, MASS_STORAGE_IO_EPSIZE,
- ENDPOINT_BANK_DOUBLE);
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);
- /* Indicate USB connected and ready */
- UpdateStatus(Status_USBReady);
-
- /* Start mass storage task */
- Scheduler_SetTaskMode(USB_MassStorage, TASK_RUN);
+ if (!(USB_MS_ConfigureEndpoints(&Disk_MS_Interface)))
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
- * control requests that are not handled internally by the USB library (including the Mass Storage class-specific
- * requests) so that they can be handled appropriately for the application.
- */
void EVENT_USB_UnhandledControlPacket(void)
{
- /* Process UFI specific control requests */
- switch (USB_ControlRequest.bRequest)
- {
- case REQ_MassStorageReset:
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Indicate that the current transfer should be aborted */
- IsMassStoreReset = true;
-
- /* Acknowledge status stage */
- while (!(Endpoint_IsINReady()));
- Endpoint_ClearIN();
- }
-
- break;
- case REQ_GetMaxLUN:
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Indicate to the host the number of supported LUNs (virtual disks) on the device */
- Endpoint_Write_Byte(TOTAL_LUNS - 1);
-
- Endpoint_ClearIN();
-
- /* Acknowledge status stage */
- while (!(Endpoint_IsOUTReceived()));
- Endpoint_ClearOUT();
- }
-
- break;
- }
-}
-
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to
- * log to a serial port, or anything else that is suitable for status updates.
- *
- * \param CurrentStatus Current status of the system, from the MassStorage_StatusCodes_t enum
- */
-void UpdateStatus(uint8_t CurrentStatus)
-{
- uint8_t LEDMask = LEDS_NO_LEDS;
-
- /* Set the LED mask to the appropriate LED mask based on the given status code */
- switch (CurrentStatus)
- {
- case Status_USBNotReady:
- LEDMask = (LEDS_LED1);
- break;
- case Status_USBEnumerating:
- LEDMask = (LEDS_LED1 | LEDS_LED2);
- break;
- case Status_USBReady:
- LEDMask = (LEDS_LED2 | LEDS_LED4);
- break;
- case Status_CommandBlockError:
- LEDMask = (LEDS_LED1);
- break;
- case Status_ProcessingCommandBlock:
- LEDMask = (LEDS_LED1 | LEDS_LED2);
- break;
- }
-
- /* Set the board LEDs to the new LED mask */
- LEDs_SetAllLEDs(LEDMask);
-}
-
-/** Task to manage the Mass Storage interface, reading in Command Block Wrappers from the host, processing the SCSI commands they
- * contain, and returning Command Status Wrappers back to the host to indicate the success or failure of the last issued command.
- */
-TASK(USB_MassStorage)
-{
- /* Check if the USB System is connected to a Host */
- if (USB_IsConnected)
- {
- /* Select the Data Out Endpoint */
- Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);
-
- /* Check to see if a command from the host has been issued */
- if (Endpoint_IsReadWriteAllowed())
- {
- /* Indicate busy */
- UpdateStatus(Status_ProcessingCommandBlock);
-
- /* Process sent command block from the host */
- if (ReadInCommandBlock())
- {
- /* Check direction of command, select Data IN endpoint if data is from the device */
- if (CommandBlock.Flags & COMMAND_DIRECTION_DATA_IN)
- Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);
-
- /* Decode the received SCSI command */
- SCSI_DecodeSCSICommand();
-
- /* Load in the CBW tag into the CSW to link them together */
- CommandStatus.Tag = CommandBlock.Tag;
-
- /* Load in the data residue counter into the CSW */
- CommandStatus.DataTransferResidue = CommandBlock.DataTransferLength;
-
- /* Stall the selected data pipe if command failed (if data is still to be transferred) */
- if ((CommandStatus.Status == Command_Fail) && (CommandStatus.DataTransferResidue))
- Endpoint_StallTransaction();
-
- /* Return command status block to the host */
- ReturnCommandStatus();
-
- /* Check if a Mass Storage Reset occurred */
- if (IsMassStoreReset)
- {
- /* Reset the data endpoint banks */
- Endpoint_ResetFIFO(MASS_STORAGE_OUT_EPNUM);
- Endpoint_ResetFIFO(MASS_STORAGE_IN_EPNUM);
-
- Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);
- Endpoint_ClearStall();
- Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);
- Endpoint_ClearStall();
-
- /* Clear the abort transfer flag */
- IsMassStoreReset = false;
- }
-
- /* Indicate ready */
- UpdateStatus(Status_USBReady);
- }
- else
- {
- /* Indicate error reading in the command block from the host */
- UpdateStatus(Status_CommandBlockError);
- }
- }
- }
-}
-
-/** Function to read in a command block from the host, via the bulk data OUT endpoint. This function reads in the next command block
- * if one has been issued, and performs validation to ensure that the block command is valid.
- *
- * \return Boolean true if a valid command block has been read in from the endpoint, false otherwise
- */
-static bool ReadInCommandBlock(void)
-{
- /* Select the Data Out endpoint */
- Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);
-
- /* Read in command block header */
- Endpoint_Read_Stream_LE(&CommandBlock, (sizeof(CommandBlock) - sizeof(CommandBlock.SCSICommandData)),
- StreamCallback_AbortOnMassStoreReset);
-
- /* Check if the current command is being aborted by the host */
- if (IsMassStoreReset)
- return false;
-
- /* Verify the command block - abort if invalid */
- if ((CommandBlock.Signature != CBW_SIGNATURE) ||
- (CommandBlock.LUN >= TOTAL_LUNS) ||
- (CommandBlock.SCSICommandLength > MAX_SCSI_COMMAND_LENGTH))
- {
- /* Stall both data pipes until reset by host */
- Endpoint_StallTransaction();
- Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);
- Endpoint_StallTransaction();
-
- return false;
- }
-
- /* Read in command block command data */
- Endpoint_Read_Stream_LE(&CommandBlock.SCSICommandData,
- CommandBlock.SCSICommandLength,
- StreamCallback_AbortOnMassStoreReset);
-
- /* Check if the current command is being aborted by the host */
- if (IsMassStoreReset)
- return false;
-
- /* Finalize the stream transfer to send the last packet */
- Endpoint_ClearOUT();
-
- return true;
+ USB_MS_ProcessControlPacket(&Disk_MS_Interface);
}
-/** Returns the filled Command Status Wrapper back to the host via the bulk data IN endpoint, waiting for the host to clear any
- * stalled data endpoints as needed.
- */
-static void ReturnCommandStatus(void)
+bool CALLBACK_USB_MS_SCSICommandReceived(USB_ClassInfo_MS_t* MSInterfaceInfo)
{
- /* Select the Data Out endpoint */
- Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);
-
- /* While data pipe is stalled, wait until the host issues a control request to clear the stall */
- while (Endpoint_IsStalled())
- {
- /* Check if the current command is being aborted by the host */
- if (IsMassStoreReset)
- return;
- }
-
- /* Select the Data In endpoint */
- Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);
-
- /* While data pipe is stalled, wait until the host issues a control request to clear the stall */
- while (Endpoint_IsStalled())
- {
- /* Check if the current command is being aborted by the host */
- if (IsMassStoreReset)
- return;
- }
+ bool CommandSuccess;
- /* Write the CSW to the endpoint */
- Endpoint_Write_Stream_LE(&CommandStatus, sizeof(CommandStatus),
- StreamCallback_AbortOnMassStoreReset);
-
- /* Check if the current command is being aborted by the host */
- if (IsMassStoreReset)
- return;
-
- /* Finalize the stream transfer to send the last packet */
- Endpoint_ClearIN();
-}
-
-/** Stream callback function for the Endpoint stream read and write functions. This callback will abort the current stream transfer
- * if a Mass Storage Reset request has been issued to the control endpoint.
- */
-uint8_t StreamCallback_AbortOnMassStoreReset(void)
-{
- /* Abort if a Mass Storage reset command was received */
- if (IsMassStoreReset)
- return STREAMCALLBACK_Abort;
+ LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
+ CommandSuccess = SCSI_DecodeSCSICommand(MSInterfaceInfo);
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);
- /* Continue with the current stream operation */
- return STREAMCALLBACK_Continue;
+ return CommandSuccess;
}
diff --git a/Demos/Device/MassStorage/MassStorage.h b/Demos/Device/MassStorage/MassStorage.h
index cbd3cd931..a50edac99 100644
--- a/Demos/Device/MassStorage/MassStorage.h
+++ b/Demos/Device/MassStorage/MassStorage.h
@@ -46,104 +46,33 @@
#include "Lib/SCSI.h"
#include "Lib/DataflashManager.h"
- #include <LUFA/Version.h> // Library Version Information
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver
- #include <LUFA/Drivers/Board/Dataflash.h> // Dataflash chip driver
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management
+ #include <LUFA/Version.h>
+ #include <LUFA/Drivers/Board/Joystick.h>
+ #include <LUFA/Drivers/Board/LEDs.h>
+ #include <LUFA/Drivers/Board/Buttons.h>
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/MassStorage.h>
/* Macros: */
- /** Mass Storage Class specific request to reset the Mass Storage interface, ready for the next command. */
- #define REQ_MassStorageReset 0xFF
-
- /** Mass Storage Class specific request to retrieve the total number of Logical Units (drives) in the SCSI device. */
- #define REQ_GetMaxLUN 0xFE
-
- /** Maximum length of a SCSI command which can be issued by the device or host in a Mass Storage bulk wrapper. */
- #define MAX_SCSI_COMMAND_LENGTH 16
+ #define LEDMASK_USB_NOTREADY LEDS_LED1
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
+ #define LEDMASK_USB_BUSY LEDS_LED2
- /** Total number of Logical Units (drives) in the device. The total device capacity is shared equally between
- * each drive - this can be set to any positive non-zero amount.
- */
- #define TOTAL_LUNS 2
+ #define TOTAL_LUNS 2
/** Blocks in each LUN, calculated from the total capacity divided by the total number of Logical Units in the device. */
- #define LUN_MEDIA_BLOCKS (VIRTUAL_MEMORY_BLOCKS / TOTAL_LUNS)
-
- /** Magic signature for a Command Block Wrapper used in the Mass Storage Bulk-Only transport protocol. */
- #define CBW_SIGNATURE 0x43425355UL
-
- /** Magic signature for a Command Status Wrapper used in the Mass Storage Bulk-Only transport protocol. */
- #define CSW_SIGNATURE 0x53425355UL
-
- /** Mask for a Command Block Wrapper's flags attribute to specify a command with data sent from host-to-device. */
- #define COMMAND_DIRECTION_DATA_OUT (0 << 7)
-
- /** Mask for a Command Block Wrapper's flags attribute to specify a command with data sent from device-to-host. */
- #define COMMAND_DIRECTION_DATA_IN (1 << 7)
-
- /* Type defines: */
- /** Type define for a Command Block Wrapper, used in the Mass Storage Bulk-Only Transport protocol. */
- typedef struct
- {
- uint32_t Signature; /**< Command block signature, must be CBW_SIGNATURE to indicate a valid Command Block */
- uint32_t Tag; /**< Unique command ID value, to associate a command block wrapper with its command status wrapper */
- uint32_t DataTransferLength; /** Length of the optional data portion of the issued command, in bytes */
- uint8_t Flags; /**< Command block flags, indicating command data direction */
- uint8_t LUN; /**< Logical Unit number this command is issued to */
- uint8_t SCSICommandLength; /**< Length of the issued SCSI command within the SCSI command data array */
- uint8_t SCSICommandData[MAX_SCSI_COMMAND_LENGTH]; /**< Issued SCSI command in the Command Block */
- } CommandBlockWrapper_t;
-
- /** Type define for a Command Status Wrapper, used in the Mass Storage Bulk-Only Transport protocol. */
- typedef struct
- {
- uint32_t Signature; /**< Status block signature, must be CSW_SIGNATURE to indicate a valid Command Status */
- uint32_t Tag; /**< Unique command ID value, to associate a command block wrapper with its command status wrapper */
- uint32_t DataTransferResidue; /**< Number of bytes of data not processed in the SCSI command */
- uint8_t Status; /**< Status code of the issued command - a value from the MassStorage_CommandStatusCodes_t enum */
- } CommandStatusWrapper_t;
-
- /* Enums: */
- /** Enum for the possible command status wrapper return status codes. */
- enum MassStorage_CommandStatusCodes_t
- {
- Command_Pass = 0, /**< Command completed with no error */
- Command_Fail = 1, /**< Command failed to complete - host may check the exact error via a SCSI REQUEST SENSE command */
- Phase_Error = 2 /**< Command failed due to being invalid in the current phase */
- };
-
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */
- enum MassStorage_StatusCodes_t
- {
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */
- Status_USBEnumerating = 1, /**< USB interface is enumerating */
- Status_USBReady = 2, /**< USB interface is connected and ready */
- Status_CommandBlockError = 3, /**< Processing a SCSI command block from the host */
- Status_ProcessingCommandBlock = 4, /**< Error during the processing of a SCSI command block from the host */
- };
-
- /* Global Variables: */
- extern CommandBlockWrapper_t CommandBlock;
- extern CommandStatusWrapper_t CommandStatus;
- extern volatile bool IsMassStoreReset;
-
- /* Task Definitions: */
- TASK(USB_MassStorage);
+ #define LUN_MEDIA_BLOCKS (VIRTUAL_MEMORY_BLOCKS / TOTAL_LUNS)
/* Function Prototypes: */
+ void SetupHardware(void);
+
void EVENT_USB_Connect(void);
void EVENT_USB_Disconnect(void);
void EVENT_USB_ConfigurationChanged(void);
void EVENT_USB_UnhandledControlPacket(void);
- void UpdateStatus(uint8_t CurrentStatus);
-
- #if defined(INCLUDE_FROM_MASSSTORAGE_C)
- static bool ReadInCommandBlock(void);
- static void ReturnCommandStatus(void);
- #endif
-
- uint8_t StreamCallback_AbortOnMassStoreReset(void);
+ bool CALLBACK_USB_MS_SCSICommandReceived(USB_ClassInfo_MS_t* MSInterfaceInfo);
#endif
diff --git a/Demos/Device/MassStorage/makefile b/Demos/Device/MassStorage/makefile
index 93f895727..c4adfc9be 100644
--- a/Demos/Device/MassStorage/makefile
+++ b/Demos/Device/MassStorage/makefile
@@ -127,7 +127,6 @@ SRC = $(TARGET).c \
Descriptors.c \
Lib/SCSI.c \
Lib/DataflashManager.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 \
@@ -138,7 +137,7 @@ SRC = $(TARGET).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/MassStorage.c \
# List C++ source files here. (C dependencies are automatically generated.)
@@ -188,7 +187,6 @@ CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)
CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
-CDEFS += -DINTERRUPT_CONTROL_ENDPOINT
# Place -D or -U options here for ASM sources
diff --git a/Demos/Device/Mouse/Descriptors.h b/Demos/Device/Mouse/Descriptors.h
index 883ef31e8..ef3215ca6 100644
--- a/Demos/Device/Mouse/Descriptors.h
+++ b/Demos/Device/Mouse/Descriptors.h
@@ -37,30 +37,12 @@
#define _DESCRIPTORS_H_
/* Includes: */
- #include <LUFA/Drivers/USB/USB.h>
-
#include <avr/pgmspace.h>
- /* Type Defines: */
- /** Type define for the HID class specific HID descriptor, to describe the HID device's specifications. Refer to the HID
- * specification for details on the structure elements.
- */
- typedef struct
- {
- USB_Descriptor_Header_t Header;
-
- uint16_t HIDSpec;
- uint8_t CountryCode;
-
- uint8_t TotalReportDescriptors;
-
- uint8_t HIDReportType;
- uint16_t HIDReportLength;
- } USB_Descriptor_HID_t;
-
- /** Type define for the data type used to store HID report descriptor elements. */
- typedef uint8_t USB_Descriptor_HIDReport_Datatype_t;
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>
+ /* Type Defines: */
/** Type define for the device configuration descriptor structure. This must be defined in the
* application code, as the configuration descriptor contains several sub-descriptors which
* vary between devices, and which describe the device's usage to the host.
@@ -80,12 +62,6 @@
/** Size in bytes of the Mouse HID reporting IN endpoint. */
#define MOUSE_EPSIZE 8
- /** Descriptor header type value, to indicate a HID class HID descriptor. */
- #define DTYPE_HID 0x21
-
- /** Descriptor header type value, to indicate a HID class HID report descriptor. */
- #define DTYPE_Report 0x22
-
/* Function Prototypes: */
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
diff --git a/Demos/Device/Mouse/Mouse.c b/Demos/Device/Mouse/Mouse.c
index 32b12fc61..57c1aa114 100644
--- a/Demos/Device/Mouse/Mouse.c
+++ b/Demos/Device/Mouse/Mouse.c
@@ -27,44 +27,33 @@
arising out of or in connection with the use or performance of
this software.
*/
-
-/** \file
- *
- * Main source file for the Mouse demo. This file contains the main tasks of the demo and
- * is responsible for the initial application hardware configuration.
- */
#include "Mouse.h"
-/* Scheduler Task List */
-TASK_LIST
-{
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },
- { .Task = USB_Mouse_Report , .TaskStatus = TASK_STOP },
-};
+USB_ClassInfo_HID_t Mouse_HID_Interface =
+ {
+ .InterfaceNumber = 0,
-/* Global Variables */
-/** Indicates what report mode the host has requested, true for normal HID reporting mode, false for special boot
- * protocol reporting mode.
- */
-bool UsingReportProtocol = true;
+ .ReportINEndpointNumber = MOUSE_EPNUM,
+ .ReportINEndpointSize = MOUSE_EPSIZE,
-/** Current Idle period. This is set by the host via a Set Idle HID class request to silence the device's reports
- * for either the entire idle duration, or until the report status changes (e.g. the user moves the mouse).
- */
-uint16_t IdleCount = HID_IDLE_CHANGESONLY;
+ .ReportBufferSize = sizeof(USB_MouseReport_Data_t),
+ };
-/** Current Idle period remaining. When the IdleCount value is set, this tracks the remaining number of idle
- * milliseconds. This is separate to the IdleCount timer and is incremented and compared as the host may request
- * the current idle period via a Get Idle HID class request, thus its value must be preserved.
- */
-uint16_t IdleMSRemaining = 0;
+int main(void)
+{
+ SetupHardware();
+
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+ for (;;)
+ {
+ USB_HID_USBTask(&Mouse_HID_Interface);
+ USB_USBTask();
+ }
+}
-/** Main program entry point. This routine configures the hardware required by the application, then
- * starts the scheduler to run the application tasks.
- */
-int main(void)
+void SetupHardware(void)
{
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
@@ -77,284 +66,64 @@ int main(void)
Joystick_Init();
LEDs_Init();
Buttons_Init();
-
- /* Millisecond timer initialization, with output compare interrupt enabled for the idle timing */
- OCR0A = 0x7D;
- TCCR0A = (1 << WGM01);
- TCCR0B = ((1 << CS01) | (1 << CS00));
- TIMSK0 = (1 << OCIE0A);
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
-
- /* Initialize Scheduler so that it can be used */
- Scheduler_Init();
-
- /* Initialize USB Subsystem */
USB_Init();
-
- /* Scheduling - routine never returns, so put this last in the main function */
- Scheduler_Start();
}
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and
- * starts the library USB task to begin the enumeration and USB management process.
- */
void EVENT_USB_Connect(void)
{
- /* Start USB management task */
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);
-
- /* Indicate USB enumerating */
- UpdateStatus(Status_USBEnumerating);
-
- /* Default to report protocol on connect */
- UsingReportProtocol = true;
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
}
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
- * the status LEDs and stops the USB management and Mouse reporting tasks.
- */
void EVENT_USB_Disconnect(void)
{
- /* Stop running mouse reporting and USB management tasks */
- Scheduler_SetTaskMode(USB_Mouse_Report, TASK_STOP);
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
}
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host sets the current configuration
- * of the USB device after enumeration - the device endpoints are configured and the mouse reporting task started.
- */
void EVENT_USB_ConfigurationChanged(void)
{
- /* Setup Mouse Report Endpoint */
- Endpoint_ConfigureEndpoint(MOUSE_EPNUM, EP_TYPE_INTERRUPT,
- ENDPOINT_DIR_IN, MOUSE_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- /* Indicate USB connected and ready */
- UpdateStatus(Status_USBReady);
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);
- /* Start running mouse reporting task */
- Scheduler_SetTaskMode(USB_Mouse_Report, TASK_RUN);
+ if (!(USB_HID_ConfigureEndpoints(&Mouse_HID_Interface)))
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
- * control requests that are not handled internally by the USB library (including the HID commands, which are
- * all issued via the control endpoint), so that they can be handled appropriately for the application.
- */
void EVENT_USB_UnhandledControlPacket(void)
{
- /* Handle HID Class specific requests */
- switch (USB_ControlRequest.bRequest)
- {
- case REQ_GetReport:
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- USB_MouseReport_Data_t MouseReportData;
-
- Endpoint_ClearSETUP();
-
- /* Create the next mouse report for transmission to the host */
- CreateMouseReport(&MouseReportData);
-
- /* Write the report data to the control endpoint */
- Endpoint_Write_Control_Stream_LE(&MouseReportData, sizeof(MouseReportData));
-
- /* Clear the report data afterwards */
- memset(&MouseReportData, 0, sizeof(MouseReportData));
-
- /* Finalize the stream transfer to send the last packet or clear the host abort */
- Endpoint_ClearOUT();
- }
-
- break;
- case REQ_GetProtocol:
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Write the current protocol flag to the host */
- Endpoint_Write_Byte(UsingReportProtocol);
-
- /* Send the flag to the host */
- Endpoint_ClearIN();
-
- /* Acknowledge status stage */
- while (!(Endpoint_IsOUTReceived()));
- Endpoint_ClearOUT();
- }
-
- break;
- case REQ_SetProtocol:
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Set or clear the flag depending on what the host indicates that the current Protocol should be */
- UsingReportProtocol = (USB_ControlRequest.wValue != 0);
-
- /* Acknowledge status stage */
- while (!(Endpoint_IsINReady()));
- Endpoint_ClearIN();
- }
-
- break;
- case REQ_SetIdle:
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Get idle period in MSB */
- IdleCount = (USB_ControlRequest.wValue >> 8);
-
- /* Acknowledge status stage */
- while (!(Endpoint_IsINReady()));
- Endpoint_ClearIN();
- }
-
- break;
- case REQ_GetIdle:
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Write the current idle duration to the host */
- Endpoint_Write_Byte(IdleCount);
-
- /* Send the flag to the host */
- Endpoint_ClearIN();
-
- /* Acknowledge status stage */
- while (!(Endpoint_IsOUTReceived()));
- Endpoint_ClearOUT();
- }
-
- break;
- }
+ USB_HID_ProcessControlPacket(&Mouse_HID_Interface);
}
-/** ISR for the timer 0 compare vector. This ISR fires once each millisecond, and increments the
- * scheduler elapsed idle period counter when the host has set an idle period.
- */
-ISR(TIMER0_COMPA_vect, ISR_BLOCK)
+void EVENT_USB_StartOfFrame(void)
{
- /* One millisecond has elapsed, decrement the idle time remaining counter if it has not already elapsed */
- if (IdleMSRemaining)
- IdleMSRemaining--;
+ USB_HID_RegisterStartOfFrame(&Mouse_HID_Interface);
}
-/** Fills the given HID report data structure with the next HID report to send to the host.
- *
- * \param ReportData Pointer to a HID report data structure to be filled
- */
-void CreateMouseReport(USB_MouseReport_Data_t* ReportData)
+uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData)
{
+ USB_MouseReport_Data_t* MouseReport = (USB_MouseReport_Data_t*)ReportData;
+
uint8_t JoyStatus_LCL = Joystick_GetStatus();
uint8_t ButtonStatus_LCL = Buttons_GetStatus();
-
- /* Clear the report contents */
- memset(ReportData, 0, sizeof(USB_MouseReport_Data_t));
if (JoyStatus_LCL & JOY_UP)
- ReportData->Y = -1;
+ MouseReport->Y = -1;
else if (JoyStatus_LCL & JOY_DOWN)
- ReportData->Y = 1;
+ MouseReport->Y = 1;
if (JoyStatus_LCL & JOY_RIGHT)
- ReportData->X = 1;
+ MouseReport->X = 1;
else if (JoyStatus_LCL & JOY_LEFT)
- ReportData->X = -1;
+ MouseReport->X = -1;
if (JoyStatus_LCL & JOY_PRESS)
- ReportData->Button = (1 << 0);
+ MouseReport->Button = (1 << 0);
if (ButtonStatus_LCL & BUTTONS_BUTTON1)
- ReportData->Button |= (1 << 1);
-}
-
-/** Sends the next HID report to the host, via the keyboard data endpoint. */
-void SendNextReport(void)
-{
- static USB_MouseReport_Data_t PrevMouseReportData;
- USB_MouseReport_Data_t MouseReportData;
- bool SendReport;
-
- /* Create the next mouse report for transmission to the host */
- CreateMouseReport(&MouseReportData);
-
- /* Check to see if the report data has changed - if so a report MUST be sent */
- SendReport = (memcmp(&PrevMouseReportData, &MouseReportData, sizeof(USB_MouseReport_Data_t)) != 0);
-
- /* Override the check if the Y or X values are non-zero - we want continuous movement while the joystick
- * is being held down (via continuous reports), otherwise the cursor will only move once per joystick toggle */
- if ((MouseReportData.Y != 0) || (MouseReportData.X != 0))
- SendReport = true;
-
- /* Save the current report data for later comparison to check for changes */
- PrevMouseReportData = MouseReportData;
-
- /* Check if the idle period is set and has elapsed */
- if ((IdleCount != HID_IDLE_CHANGESONLY) && (!(IdleMSRemaining)))
- {
- /* Reset the idle time remaining counter, must multiply by 4 to get the duration in milliseconds */
- IdleMSRemaining = (IdleCount << 2);
-
- /* Idle period is set and has elapsed, must send a report to the host */
- SendReport = true;
- }
+ MouseReport->Button |= (1 << 1);
- /* Select the Mouse Report Endpoint */
- Endpoint_SelectEndpoint(MOUSE_EPNUM);
-
- /* Check if Mouse Endpoint Ready for Read/Write and if we should send a new report */
- if (Endpoint_IsReadWriteAllowed() && SendReport)
- {
- /* Write Mouse Report Data */
- Endpoint_Write_Stream_LE(&MouseReportData, sizeof(MouseReportData));
-
- /* Finalize the stream transfer to send the last packet */
- Endpoint_ClearIN();
- }
+ return sizeof(USB_MouseReport_Data_t);
}
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to
- * log to a serial port, or anything else that is suitable for status updates.
- *
- * \param CurrentStatus Current status of the system, from the Mouse_StatusCodes_t enum
- */
-void UpdateStatus(uint8_t CurrentStatus)
+void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize)
{
- uint8_t LEDMask = LEDS_NO_LEDS;
-
- /* Set the LED mask to the appropriate LED mask based on the given status code */
- switch (CurrentStatus)
- {
- case Status_USBNotReady:
- LEDMask = (LEDS_LED1);
- break;
- case Status_USBEnumerating:
- LEDMask = (LEDS_LED1 | LEDS_LED2);
- break;
- case Status_USBReady:
- LEDMask = (LEDS_LED2 | LEDS_LED4);
- break;
- }
-
- /* Set the board LEDs to the new LED mask */
- LEDs_SetAllLEDs(LEDMask);
-}
-
-/** Task to manage HID report generation and transmission to the host, when in report mode. */
-TASK(USB_Mouse_Report)
-{
- /* Check if the USB system is connected to a host */
- if (USB_IsConnected)
- {
- /* Send the next mouse report to the host */
- SendNextReport();
- }
+ // Unused (but mandatory for the HID class driver) in this demo, since there are no Host->Device reports
}
diff --git a/Demos/Device/Mouse/Mouse.h b/Demos/Device/Mouse/Mouse.h
index 65879da8e..5c8049590 100644
--- a/Demos/Device/Mouse/Mouse.h
+++ b/Demos/Device/Mouse/Mouse.h
@@ -46,37 +46,12 @@
#include "Descriptors.h"
- #include <LUFA/Version.h> // Library Version Information
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality
- #include <LUFA/Drivers/Board/Joystick.h> // Joystick driver
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver
- #include <LUFA/Drivers/Board/Buttons.h> // Board Buttons driver
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management
-
- /* Task Definitions: */
- TASK(USB_Mouse_Report);
-
- /* Macros: */
- /** Idle period indicating that reports should be sent only when the inputs have changed */
- #define HID_IDLE_CHANGESONLY 0
-
- /** HID Class specific request to get the next HID report from the device. */
- #define REQ_GetReport 0x01
-
- /** HID Class specific request to get the idle timeout period of the device. */
- #define REQ_GetIdle 0x02
-
- /** HID Class specific request to send the next HID report to the device. */
- #define REQ_SetReport 0x09
-
- /** HID Class specific request to set the idle timeout period of the device. */
- #define REQ_SetIdle 0x0A
-
- /** HID Class specific request to get the current HID protocol in use, either report or boot. */
- #define REQ_GetProtocol 0x03
-
- /** HID Class specific request to set the current HID protocol in use, either report or boot. */
- #define REQ_SetProtocol 0x0B
+ #include <LUFA/Version.h>
+ #include <LUFA/Drivers/Board/Joystick.h>
+ #include <LUFA/Drivers/Board/LEDs.h>
+ #include <LUFA/Drivers/Board/Buttons.h>
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/HID.h>
/* Type Defines: */
/** Type define for the mouse HID report structure, for creating and sending HID reports to the host PC.
@@ -89,22 +64,23 @@
int8_t Y; /**< Current mouse delta Y movement, as a signed 8-bit integer */
} USB_MouseReport_Data_t;
- /* Enums: */
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */
- enum Mouse_StatusCodes_t
- {
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */
- Status_USBEnumerating = 1, /**< USB interface is enumerating */
- Status_USBReady = 2, /**< USB interface is connected and ready */
- };
+ /* Macros: */
+ #define LEDMASK_USB_NOTREADY LEDS_LED1
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
/* Function Prototypes: */
+ void SetupHardware(void);
+
void EVENT_USB_Connect(void);
void EVENT_USB_Disconnect(void);
void EVENT_USB_ConfigurationChanged(void);
void EVENT_USB_UnhandledControlPacket(void);
+ void EVENT_USB_StartOfFrame(void);
- void CreateMouseReport(USB_MouseReport_Data_t* ReportData);
- void UpdateStatus(uint8_t CurrentStatus);
+ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);
+ void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo,
+ void* ReportData, uint16_t ReportSize);
#endif
diff --git a/Demos/Device/Mouse/makefile b/Demos/Device/Mouse/makefile
index 632bf91ae..4c18f9d4a 100644
--- a/Demos/Device/Mouse/makefile
+++ b/Demos/Device/Mouse/makefile
@@ -125,7 +125,6 @@ LUFA_PATH = ../../..
# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c \
Descriptors.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 \
@@ -136,7 +135,7 @@ SRC = $(TARGET).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.)
CPPSRC =
@@ -182,7 +181,7 @@ CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
diff --git a/Demos/Device/RNDISEthernet/Lib/ARP.h b/Demos/Device/RNDISEthernet/Lib/ARP.h
index 8551df85b..f05d8f093 100644
--- a/Demos/Device/RNDISEthernet/Lib/ARP.h
+++ b/Demos/Device/RNDISEthernet/Lib/ARP.h
@@ -38,9 +38,7 @@
/* Includes: */
#include <avr/io.h>
- #include <string.h>
-
- #include <LUFA/Scheduler/Scheduler.h>
+ #include <string.h>
#include "EthernetProtocols.h"
#include "Ethernet.h"
diff --git a/Demos/Device/RNDISEthernet/Lib/Ethernet.c b/Demos/Device/RNDISEthernet/Lib/Ethernet.c
index 3d34f716a..57380a082 100644
--- a/Demos/Device/RNDISEthernet/Lib/Ethernet.c
+++ b/Demos/Device/RNDISEthernet/Lib/Ethernet.c
@@ -38,12 +38,6 @@
#include "Ethernet.h"
/* Global Variables: */
-/** Ethernet Frame buffer structure, to hold the incoming Ethernet frame from the host. */
-Ethernet_Frame_Info_t FrameIN;
-
-/** Ethernet Frame buffer structure, to hold the outgoing Ethernet frame to the host. */
-Ethernet_Frame_Info_t FrameOUT;
-
/** Constant for convenience when checking against or setting a MAC address to the virtual server MAC address. */
const MAC_Address_t ServerMACAddress = {SERVER_MAC_ADDRESS};
@@ -63,31 +57,31 @@ const IP_Address_t ClientIPAddress = {CLIENT_IP_ADDRESS};
/** Processes an incoming Ethernet frame, and writes the appropriate response to the output Ethernet
* frame buffer if the sub protocol handlers create a valid response.
*/
-void Ethernet_ProcessPacket(void)
+void Ethernet_ProcessPacket(Ethernet_Frame_Info_t* FrameIN, Ethernet_Frame_Info_t* FrameOUT)
{
- DecodeEthernetFrameHeader(FrameIN.FrameData);
+ DecodeEthernetFrameHeader(FrameIN->FrameData);
/* Cast the incoming Ethernet frame to the Ethernet header type */
- Ethernet_Frame_Header_t* FrameINHeader = (Ethernet_Frame_Header_t*)&FrameIN.FrameData;
- Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&FrameOUT.FrameData;
+ Ethernet_Frame_Header_t* FrameINHeader = (Ethernet_Frame_Header_t*)&FrameIN->FrameData;
+ Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&FrameOUT->FrameData;
int16_t RetSize = NO_RESPONSE;
/* Ensure frame is addressed to either all (broadcast) or the virtual webserver, and is a type II frame */
if ((MAC_COMPARE(&FrameINHeader->Destination, &ServerMACAddress) ||
- MAC_COMPARE(&FrameINHeader->Destination, &BroadcastMACAddress)) &&
- (SwapEndian_16(FrameIN.FrameLength) > ETHERNET_VER2_MINSIZE))
+ MAC_COMPARE(&FrameINHeader->Destination, &BroadcastMACAddress)))
{
/* Process the packet depending on its protocol */
switch (SwapEndian_16(FrameINHeader->EtherType))
{
case ETHERTYPE_ARP:
- RetSize = ARP_ProcessARPPacket(&FrameIN.FrameData[sizeof(Ethernet_Frame_Header_t)],
- &FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)]);
+ RetSize = ARP_ProcessARPPacket(&FrameIN->FrameData[sizeof(Ethernet_Frame_Header_t)],
+ &FrameOUT->FrameData[sizeof(Ethernet_Frame_Header_t)]);
break;
case ETHERTYPE_IPV4:
- RetSize = IP_ProcessIPPacket(&FrameIN.FrameData[sizeof(Ethernet_Frame_Header_t)],
- &FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)]);
+ RetSize = IP_ProcessIPPacket(FrameIN,
+ &FrameIN->FrameData[sizeof(Ethernet_Frame_Header_t)],
+ &FrameOUT->FrameData[sizeof(Ethernet_Frame_Header_t)]);
break;
}
@@ -100,8 +94,8 @@ void Ethernet_ProcessPacket(void)
FrameOUTHeader->EtherType = FrameINHeader->EtherType;
/* Set the response length in the buffer and indicate that a response is ready to be sent */
- FrameOUT.FrameLength = (sizeof(Ethernet_Frame_Header_t) + RetSize);
- FrameOUT.FrameInBuffer = true;
+ FrameOUT->FrameLength = (sizeof(Ethernet_Frame_Header_t) + RetSize);
+ FrameOUT->FrameInBuffer = true;
}
}
@@ -109,7 +103,7 @@ void Ethernet_ProcessPacket(void)
if (RetSize != NO_PROCESS)
{
/* Clear the frame buffer */
- FrameIN.FrameInBuffer = false;
+ FrameIN->FrameInBuffer = false;
}
}
diff --git a/Demos/Device/RNDISEthernet/Lib/Ethernet.h b/Demos/Device/RNDISEthernet/Lib/Ethernet.h
index b360f07ae..b3002523a 100644
--- a/Demos/Device/RNDISEthernet/Lib/Ethernet.h
+++ b/Demos/Device/RNDISEthernet/Lib/Ethernet.h
@@ -39,6 +39,8 @@
/* Includes: */
#include <avr/io.h>
#include <string.h>
+
+ #include <LUFA/Drivers/USB/Class/Device/RNDIS.h>
#include "EthernetProtocols.h"
#include "ProtocolDecoders.h"
@@ -50,6 +52,9 @@
#include "IP.h"
/* Macros: */
+ /** Physical MAC address of the USB RNDIS network adapter */
+ #define ADAPTER_MAC_ADDRESS {0x00, 0x02, 0x00, 0x02, 0x00, 0x02}
+
/** Physical MAC address of the virtual server on the network */
#define SERVER_MAC_ADDRESS {0x00, 0x01, 0x00, 0x01, 0x00, 0x01}
@@ -64,12 +69,6 @@
* \return True if the addresses match, false otherwise
*/
#define MAC_COMPARE(MAC1, MAC2) (memcmp(MAC1, MAC2, sizeof(MAC_Address_t)) == 0)
-
- /** Maximum size of an incoming or outgoing Ethernet frame in bytes */
- #define ETHERNET_FRAME_SIZE_MAX 1500
-
- /** Minimum size of an Ethernet packet in bytes, to conform to the Ethernet V2 packet standard */
- #define ETHERNET_VER2_MINSIZE 0x0600
/** Return value for all sub protocol handling routines, indicating that no response packet has been generated */
#define NO_RESPONSE 0
@@ -78,14 +77,6 @@
#define NO_PROCESS -1
/* Type Defines: */
- /** Type define for an Ethernet frame buffer. */
- typedef struct
- {
- uint8_t FrameData[ETHERNET_FRAME_SIZE_MAX]; /**< Ethernet frame contents */
- uint16_t FrameLength; /**< Length in bytes of the Ethernet frame stored in the buffer */
- bool FrameInBuffer; /**< Indicates if a frame is currently stored in the buffer */
- } Ethernet_Frame_Info_t;
-
/** Type define for an Ethernet frame header */
typedef struct
{
@@ -100,9 +91,6 @@
} Ethernet_Frame_Header_t;
/* External Variables: */
- extern Ethernet_Frame_Info_t FrameIN;
- extern Ethernet_Frame_Info_t FrameOUT;
-
extern const MAC_Address_t ServerMACAddress;
extern const IP_Address_t ServerIPAddress;
extern const MAC_Address_t BroadcastMACAddress;
@@ -110,7 +98,7 @@
extern const IP_Address_t ClientIPAddress;
/* Function Prototypes: */
- void Ethernet_ProcessPacket(void);
+ void Ethernet_ProcessPacket(Ethernet_Frame_Info_t* FrameIN, Ethernet_Frame_Info_t* FrameOUT);
uint16_t Ethernet_Checksum16(void* Data, uint16_t Bytes);
#endif
diff --git a/Demos/Device/RNDISEthernet/Lib/EthernetProtocols.h b/Demos/Device/RNDISEthernet/Lib/EthernetProtocols.h
index 3ff3433ae..1ec5961e1 100644
--- a/Demos/Device/RNDISEthernet/Lib/EthernetProtocols.h
+++ b/Demos/Device/RNDISEthernet/Lib/EthernetProtocols.h
@@ -71,13 +71,7 @@
#define PROTOCOL_OSPF 89
#define PROTOCOL_SCTP 132
- /* Type Defines: */
- /** Type define for a physical MAC address of a device on a network */
- typedef struct
- {
- uint8_t Octets[6]; /**< Individual bytes of a MAC address */
- } MAC_Address_t;
-
+ /* Type Defines: */
/** Type define for a protocol IP address of a device on a network */
typedef struct
{
diff --git a/Demos/Device/RNDISEthernet/Lib/ICMP.c b/Demos/Device/RNDISEthernet/Lib/ICMP.c
index da4ffcfa1..ba6e1db68 100644
--- a/Demos/Device/RNDISEthernet/Lib/ICMP.c
+++ b/Demos/Device/RNDISEthernet/Lib/ICMP.c
@@ -45,7 +45,7 @@
*
* \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise
*/
-int16_t ICMP_ProcessICMPPacket(void* InDataStart, void* OutDataStart)
+int16_t ICMP_ProcessICMPPacket(Ethernet_Frame_Info_t* FrameIN, void* InDataStart, void* OutDataStart)
{
ICMP_Header_t* ICMPHeaderIN = (ICMP_Header_t*)InDataStart;
ICMP_Header_t* ICMPHeaderOUT = (ICMP_Header_t*)OutDataStart;
@@ -62,7 +62,7 @@ int16_t ICMP_ProcessICMPPacket(void* InDataStart, void* OutDataStart)
ICMPHeaderOUT->Id = ICMPHeaderIN->Id;
ICMPHeaderOUT->Sequence = ICMPHeaderIN->Sequence;
- uint16_t DataSize = FrameIN.FrameLength - ((((uint16_t)InDataStart + sizeof(ICMP_Header_t)) - (uint16_t)FrameIN.FrameData));
+ uint16_t DataSize = FrameIN->FrameLength - ((((uint16_t)InDataStart + sizeof(ICMP_Header_t)) - (uint16_t)FrameIN->FrameData));
/* Copy the remaining payload to the response - echo requests should echo back any sent data */
memcpy(&((uint8_t*)OutDataStart)[sizeof(ICMP_Header_t)],
diff --git a/Demos/Device/RNDISEthernet/Lib/ICMP.h b/Demos/Device/RNDISEthernet/Lib/ICMP.h
index b20a557e9..56749c09c 100644
--- a/Demos/Device/RNDISEthernet/Lib/ICMP.h
+++ b/Demos/Device/RNDISEthernet/Lib/ICMP.h
@@ -75,6 +75,6 @@
} ICMP_Header_t;
/* Function Prototypes: */
- int16_t ICMP_ProcessICMPPacket(void* InDataStart, void* OutDataStart);
+ int16_t ICMP_ProcessICMPPacket(Ethernet_Frame_Info_t* FrameIN, void* InDataStart, void* OutDataStart);
#endif
diff --git a/Demos/Device/RNDISEthernet/Lib/IP.c b/Demos/Device/RNDISEthernet/Lib/IP.c
index 8fb0b446d..08500450c 100644
--- a/Demos/Device/RNDISEthernet/Lib/IP.c
+++ b/Demos/Device/RNDISEthernet/Lib/IP.c
@@ -46,7 +46,7 @@
* response was generated, NO_PROCESS if the packet processing was deferred until the
* next Ethernet packet handler iteration
*/
-int16_t IP_ProcessIPPacket(void* InDataStart, void* OutDataStart)
+int16_t IP_ProcessIPPacket(Ethernet_Frame_Info_t* FrameIN, void* InDataStart, void* OutDataStart)
{
DecodeIPHeader(InDataStart);
@@ -69,7 +69,8 @@ int16_t IP_ProcessIPPacket(void* InDataStart, void* OutDataStart)
switch (IPHeaderIN->Protocol)
{
case PROTOCOL_ICMP:
- RetSize = ICMP_ProcessICMPPacket(&((uint8_t*)InDataStart)[HeaderLengthBytes],
+ RetSize = ICMP_ProcessICMPPacket(FrameIN,
+ &((uint8_t*)InDataStart)[HeaderLengthBytes],
&((uint8_t*)OutDataStart)[sizeof(IP_Header_t)]);
break;
case PROTOCOL_TCP:
diff --git a/Demos/Device/RNDISEthernet/Lib/IP.h b/Demos/Device/RNDISEthernet/Lib/IP.h
index fc1a46aef..f77c772d8 100644
--- a/Demos/Device/RNDISEthernet/Lib/IP.h
+++ b/Demos/Device/RNDISEthernet/Lib/IP.h
@@ -88,6 +88,6 @@
} IP_Header_t;
/* Function Prototypes: */
- int16_t IP_ProcessIPPacket(void* InDataStart, void* OutDataStart);
+ int16_t IP_ProcessIPPacket(Ethernet_Frame_Info_t* FrameIN, void* InDataStart, void* OutDataStart);
#endif
diff --git a/Demos/Device/RNDISEthernet/Lib/RNDIS.c b/Demos/Device/RNDISEthernet/Lib/RNDIS.c
deleted file mode 100644
index c5202bcd1..000000000
--- a/Demos/Device/RNDISEthernet/Lib/RNDIS.c
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2009.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, and distribute this software
- and its documentation for any purpose and without fee is hereby
- granted, provided that the above copyright notice appear in all
- copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * RNDIS command handler functions. This handles RNDIS commands according to
- * the Microsoft RNDIS specification, creating a USB Ethernet network adapter.
- */
-
-#define INCLUDE_FROM_RNDIS_C
-#include "RNDIS.h"
-
-/* Global Variables: */
-/** Physical MAC address of the network adapter, which becomes the MAC address of the host for packets sent to the adapter. */
-static MAC_Address_t PROGMEM AdapterMACAddress = {ADAPTER_MAC_ADDRESS};
-
-/** Vendor description of the adapter. This is overridden by the INF file required to install the appropriate RNDIS drivers for
- * the device, but may still be used by the OS in some circumstances.
- */
-static char PROGMEM AdapterVendorDescription[] = "LUFA RNDIS Adapter";
-
-/** List of RNDIS OID commands supported by this adapter. */
-static const uint32_t PROGMEM AdapterSupportedOIDList[] =
- {
- OID_GEN_SUPPORTED_LIST,
- OID_GEN_PHYSICAL_MEDIUM,
- OID_GEN_HARDWARE_STATUS,
- OID_GEN_MEDIA_SUPPORTED,
- OID_GEN_MEDIA_IN_USE,
- OID_GEN_MAXIMUM_FRAME_SIZE,
- OID_GEN_MAXIMUM_TOTAL_SIZE,
- OID_GEN_LINK_SPEED,
- OID_GEN_TRANSMIT_BLOCK_SIZE,
- OID_GEN_RECEIVE_BLOCK_SIZE,
- OID_GEN_VENDOR_ID,
- OID_GEN_VENDOR_DESCRIPTION,
- OID_GEN_CURRENT_PACKET_FILTER,
- OID_GEN_MAXIMUM_TOTAL_SIZE,
- OID_GEN_MEDIA_CONNECT_STATUS,
- OID_GEN_XMIT_OK,
- OID_GEN_RCV_OK,
- OID_GEN_XMIT_ERROR,
- OID_GEN_RCV_ERROR,
- OID_GEN_RCV_NO_BUFFER,
- OID_802_3_PERMANENT_ADDRESS,
- OID_802_3_CURRENT_ADDRESS,
- OID_802_3_MULTICAST_LIST,
- OID_802_3_MAXIMUM_LIST_SIZE,
- OID_802_3_RCV_ERROR_ALIGNMENT,
- OID_802_3_XMIT_ONE_COLLISION,
- OID_802_3_XMIT_MORE_COLLISIONS,
- };
-
-/** Buffer for RNDIS messages (as distinct from Ethernet frames sent through the adapter. This must be big enough to hold the entire
- * 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
- * reason, care must be taken when constructing RNDIS responses that unread data is not overwritten when writing in responses.
- */
-uint8_t RNDISMessageBuffer[sizeof(AdapterSupportedOIDList) + sizeof(RNDIS_QUERY_CMPLT_t)];
-
-/** Pointer to the RNDIS message header at the top of the RNDIS message buffer, for convenience. */
-RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISMessageBuffer;
-
-/** Indicates if a RNDIS message response is ready to be sent back to the host. */
-bool ResponseReady = false;
-
-/** Current RNDIS adapter state, a value from the RNDIS_States_t enum. */
-uint8_t CurrRNDISState = RNDIS_Uninitialized;
-
-/** Current Ethernet packet filter mask. This is non-zero when the adapter is initialized, or zero when disabled. */
-uint32_t CurrPacketFilter = 0;
-
-
-/** Processes the RNDIS message received by the host and stored in the RNDISMessageBuffer global buffer. If a response is
- * created, the ResponseReady global is updated so that the response is written back to the host upon request.
- */
-void ProcessRNDISControlMessage(void)
-{
- /* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of
- this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */
-
- switch (MessageHeader->MessageType)
- {
- case REMOTE_NDIS_INITIALIZE_MSG:
- /* Initialize the adapter - return information about the supported RNDIS version and buffer sizes */
-
- ResponseReady = true;
-
- RNDIS_INITIALIZE_MSG_t* INITIALIZE_Message = (RNDIS_INITIALIZE_MSG_t*)&RNDISMessageBuffer;
- RNDIS_INITIALIZE_CMPLT_t* INITIALIZE_Response = (RNDIS_INITIALIZE_CMPLT_t*)&RNDISMessageBuffer;
-
- INITIALIZE_Response->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
- INITIALIZE_Response->MessageLength = sizeof(RNDIS_INITIALIZE_CMPLT_t);
- INITIALIZE_Response->RequestId = INITIALIZE_Message->RequestId;
- INITIALIZE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
-
- INITIALIZE_Response->MajorVersion = REMOTE_NDIS_VERSION_MAJOR;
- INITIALIZE_Response->MinorVersion = REMOTE_NDIS_VERSION_MINOR;
- INITIALIZE_Response->DeviceFlags = REMOTE_NDIS_DF_CONNECTIONLESS;
- INITIALIZE_Response->Medium = REMOTE_NDIS_MEDIUM_802_3;
- INITIALIZE_Response->MaxPacketsPerTransfer = 1;
- INITIALIZE_Response->MaxTransferSize = (sizeof(RNDIS_PACKET_MSG_t) + ETHERNET_FRAME_SIZE_MAX);
- INITIALIZE_Response->PacketAlignmentFactor = 0;
- INITIALIZE_Response->AFListOffset = 0;
- INITIALIZE_Response->AFListSize = 0;
-
- CurrRNDISState = RNDIS_Initialized;
-
- break;
- case REMOTE_NDIS_HALT_MSG:
- /* Halt the adapter, reset the adapter state - note that no response should be returned when completed */
-
- ResponseReady = false;
- MessageHeader->MessageLength = 0;
-
- CurrRNDISState = RNDIS_Uninitialized;
-
- break;
- case REMOTE_NDIS_QUERY_MSG:
- /* Request for information about a parameter about the adapter, specified as an OID token */
-
- ResponseReady = true;
-
- RNDIS_QUERY_MSG_t* QUERY_Message = (RNDIS_QUERY_MSG_t*)&RNDISMessageBuffer;
- RNDIS_QUERY_CMPLT_t* QUERY_Response = (RNDIS_QUERY_CMPLT_t*)&RNDISMessageBuffer;
- uint32_t Query_Oid = QUERY_Message->Oid;
-
- void* QueryData = &RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
- QUERY_Message->InformationBufferOffset];
- void* ResponseData = &RNDISMessageBuffer[sizeof(RNDIS_QUERY_CMPLT_t)];
- uint16_t ResponseSize;
-
- QUERY_Response->MessageType = REMOTE_NDIS_QUERY_CMPLT;
- QUERY_Response->MessageLength = sizeof(RNDIS_QUERY_CMPLT_t);
-
- if (ProcessNDISQuery(Query_Oid, QueryData, QUERY_Message->InformationBufferLength,
- ResponseData, &ResponseSize))
- {
- QUERY_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
- QUERY_Response->MessageLength += ResponseSize;
-
- QUERY_Response->InformationBufferLength = ResponseSize;
- QUERY_Response->InformationBufferOffset = (sizeof(RNDIS_QUERY_CMPLT_t) - sizeof(RNDIS_Message_Header_t));
- }
- else
- {
- QUERY_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;
-
- QUERY_Response->InformationBufferLength = 0;
- QUERY_Response->InformationBufferOffset = 0;
- }
-
- break;
- case REMOTE_NDIS_SET_MSG:
- /* Request to set a parameter of the adapter, specified as an OID token */
-
- ResponseReady = true;
-
- RNDIS_SET_MSG_t* SET_Message = (RNDIS_SET_MSG_t*)&RNDISMessageBuffer;
- RNDIS_SET_CMPLT_t* SET_Response = (RNDIS_SET_CMPLT_t*)&RNDISMessageBuffer;
- uint32_t SET_Oid = SET_Message->Oid;
-
- SET_Response->MessageType = REMOTE_NDIS_SET_CMPLT;
- SET_Response->MessageLength = sizeof(RNDIS_SET_CMPLT_t);
- SET_Response->RequestId = SET_Message->RequestId;
-
- void* SetData = &RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
- SET_Message->InformationBufferOffset];
-
- if (ProcessNDISSet(SET_Oid, SetData, SET_Message->InformationBufferLength))
- SET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
- else
- SET_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;
-
- break;
- case REMOTE_NDIS_RESET_MSG:
- /* Soft reset the adapter */
-
- ResponseReady = true;
-
- RNDIS_RESET_CMPLT_t* RESET_Response = (RNDIS_RESET_CMPLT_t*)&RNDISMessageBuffer;
-
- RESET_Response->MessageType = REMOTE_NDIS_RESET_CMPLT;
- RESET_Response->MessageLength = sizeof(RNDIS_RESET_CMPLT_t);
- RESET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
- RESET_Response->AddressingReset = 0;
-
- break;
- case REMOTE_NDIS_KEEPALIVE_MSG:
- /* Keep alive message sent to the adapter every 5 seconds when idle to ensure it is still responding */
-
- ResponseReady = true;
-
- RNDIS_KEEPALIVE_MSG_t* KEEPALIVE_Message = (RNDIS_KEEPALIVE_MSG_t*)&RNDISMessageBuffer;
- RNDIS_KEEPALIVE_CMPLT_t* KEEPALIVE_Response = (RNDIS_KEEPALIVE_CMPLT_t*)&RNDISMessageBuffer;
-
- KEEPALIVE_Response->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
- KEEPALIVE_Response->MessageLength = sizeof(RNDIS_KEEPALIVE_CMPLT_t);
- KEEPALIVE_Response->RequestId = KEEPALIVE_Message->RequestId;
- KEEPALIVE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
-
- break;
- }
-}
-
-/** Processes RNDIS query commands, retrieving information from the adapter and reporting it back to the host. The requested
- * parameter is given as an OID value.
- *
- * \param OId OId value of the parameter being queried
- * \param QueryData Pointer to any extra query data being sent by the host to the device inside the RNDIS message buffer
- * \param QuerySize Size in bytes of the extra query data being sent by the host
- * \param ResponseData Pointer to the start of the query response inside the RNDIS message buffer
- * \param ResponseSize Pointer to the size in bytes of the response data being sent to the host
- *
- * \return Boolean true if the query was handled, false otherwise
- */
-static bool ProcessNDISQuery(uint32_t OId, void* QueryData, uint16_t QuerySize,
- void* ResponseData, uint16_t* ResponseSize)
-{
- /* Handler for REMOTE_NDIS_QUERY_MSG messages */
-
- switch (OId)
- {
- case OID_GEN_SUPPORTED_LIST:
- *ResponseSize = sizeof(AdapterSupportedOIDList);
-
- /* Copy the list of supported NDIS OID tokens to the response buffer */
- memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));
-
- return true;
- case OID_GEN_PHYSICAL_MEDIUM:
- *ResponseSize = sizeof(uint32_t);
-
- /* Indicate that the device is a true ethernet link */
- *((uint32_t*)ResponseData) = 0;
-
- return true;
- case OID_GEN_HARDWARE_STATUS:
- *ResponseSize = sizeof(uint32_t);
-
- /* Always indicate hardware ready */
- *((uint32_t*)ResponseData) = NdisHardwareStatusReady;
-
- return true;
- case OID_GEN_MEDIA_SUPPORTED:
- case OID_GEN_MEDIA_IN_USE:
- *ResponseSize = sizeof(uint32_t);
-
- /* Indicate 802.3 (Ethernet) supported by the adapter */
- *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIUM_802_3;
-
- return true;
- case OID_GEN_VENDOR_ID:
- *ResponseSize = sizeof(uint32_t);
-
- /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */
- *((uint32_t*)ResponseData) = 0x00FFFFFF;
-
- return true;
- case OID_GEN_MAXIMUM_FRAME_SIZE:
- case OID_GEN_TRANSMIT_BLOCK_SIZE:
- case OID_GEN_RECEIVE_BLOCK_SIZE:
- *ResponseSize = sizeof(uint32_t);
-
- /* Indicate that the maximum frame size is the size of the ethernet frame buffer */
- *((uint32_t*)ResponseData) = ETHERNET_FRAME_SIZE_MAX;
-
- return true;
- case OID_GEN_VENDOR_DESCRIPTION:
- *ResponseSize = sizeof(AdapterVendorDescription);
-
- /* Copy vendor description string to the response buffer */
- memcpy_P(ResponseData, AdapterVendorDescription, sizeof(AdapterVendorDescription));
-
- return true;
- case OID_GEN_MEDIA_CONNECT_STATUS:
- *ResponseSize = sizeof(uint32_t);
-
- /* Always indicate that the adapter is connected to a network */
- *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIA_STATE_CONNECTED;
-
- return true;
- case OID_GEN_LINK_SPEED:
- *ResponseSize = sizeof(uint32_t);
-
- /* Indicate 10Mb/s link speed */
- *((uint32_t*)ResponseData) = 100000;
-
- return true;
- case OID_802_3_PERMANENT_ADDRESS:
- case OID_802_3_CURRENT_ADDRESS:
- *ResponseSize = sizeof(MAC_Address_t);
-
- /* Copy over the fixed adapter MAC to the response buffer */
- memcpy_P(ResponseData, &AdapterMACAddress, sizeof(MAC_Address_t));
-
- return true;
- case OID_802_3_MAXIMUM_LIST_SIZE:
- *ResponseSize = sizeof(uint32_t);
-
- /* Indicate only one multicast address supported */
- *((uint32_t*)ResponseData) = 1;
-
- return true;
- case OID_GEN_CURRENT_PACKET_FILTER:
- *ResponseSize = sizeof(uint32_t);
-
- /* Indicate the current packet filter mask */
- *((uint32_t*)ResponseData) = CurrPacketFilter;
-
- return true;
- case OID_GEN_XMIT_OK:
- case OID_GEN_RCV_OK:
- case OID_GEN_XMIT_ERROR:
- case OID_GEN_RCV_ERROR:
- case OID_GEN_RCV_NO_BUFFER:
- case OID_802_3_RCV_ERROR_ALIGNMENT:
- case OID_802_3_XMIT_ONE_COLLISION:
- case OID_802_3_XMIT_MORE_COLLISIONS:
- *ResponseSize = sizeof(uint32_t);
-
- /* Unused statistic OIDs - always return 0 for each */
- *((uint32_t*)ResponseData) = 0;
-
- return true;
- case OID_GEN_MAXIMUM_TOTAL_SIZE:
- *ResponseSize = sizeof(uint32_t);
-
- /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */
- *((uint32_t*)ResponseData) = (sizeof(RNDISMessageBuffer) + ETHERNET_FRAME_SIZE_MAX);
-
- return true;
- default:
- return false;
- }
-}
-
-/** Processes RNDIS set commands, setting adapter parameters to values given by the host. The requested parameter is given
- * as an OID value.
- *
- * \param OId OId value of the parameter being set
- * \param SetData Pointer to the parameter value in the RNDIS message buffer
- * \param SetSize Size in bytes of the parameter value being sent by the host
- *
- * \return Boolean true if the set was handled, false otherwise
- */
-static bool ProcessNDISSet(uint32_t OId, void* SetData, uint16_t SetSize)
-{
- /* Handler for REMOTE_NDIS_SET_MSG messages */
-
- switch (OId)
- {
- case OID_GEN_CURRENT_PACKET_FILTER:
- /* Save the packet filter mask in case the host queries it again later */
- CurrPacketFilter = *((uint32_t*)SetData);
-
- /* Set the RNDIS state to initialized if the packet filter is non-zero */
- CurrRNDISState = ((CurrPacketFilter) ? RNDIS_Data_Initialized : RNDIS_Data_Initialized);
-
- return true;
- case OID_802_3_MULTICAST_LIST:
- /* Do nothing - throw away the value from the host as it is unused */
-
- return true;
- default:
- return false;
- }
-}
diff --git a/Demos/Device/RNDISEthernet/Lib/RNDIS.h b/Demos/Device/RNDISEthernet/Lib/RNDIS.h
deleted file mode 100644
index 88c9a9eb9..000000000
--- a/Demos/Device/RNDISEthernet/Lib/RNDIS.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2009.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, and distribute this software
- and its documentation for any purpose and without fee is hereby
- granted, provided that the above copyright notice appear in all
- copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * Header file for RNDIS.c.
- */
-
-#ifndef _RNDIS_H_
-#define _RNDIS_H_
-
- /* Includes: */
- #include <avr/io.h>
- #include <stdbool.h>
-
- #include "RNDISEthernet.h"
- #include "RNDISConstants.h"
- #include "Ethernet.h"
-
- /* Macros: */
- /** Physical MAC Address of the USB network adapter */
- #define ADAPTER_MAC_ADDRESS {0x02, 0x00, 0x02, 0x00, 0x02, 0x00}
-
- /** Implemented RNDIS Version Major */
- #define REMOTE_NDIS_VERSION_MAJOR 0x01
-
- /** Implemented RNDIS Version Minor */
- #define REMOTE_NDIS_VERSION_MINOR 0x00
-
- /** RNDIS request to issue a host-to-device NDIS command */
- #define REQ_SendEncapsulatedCommand 0x00
-
- /** RNDIS request to issue a device-to-host NDIS response */
- #define REQ_GetEncapsulatedResponse 0x01
-
- /* Enums: */
- /** Enum for the possible NDIS adapter states. */
- enum RNDIS_States_t
- {
- RNDIS_Uninitialized = 0, /**< Adapter currently uninitialized */
- RNDIS_Initialized = 1, /**< Adapter currently initialized but not ready for data transfers */
- RNDIS_Data_Initialized = 2, /**< Adapter currently initialized and ready for data transfers */
- };
-
- /** Enum for the NDIS hardware states */
- enum NDIS_Hardware_Status_t
- {
- NdisHardwareStatusReady, /**< Hardware Ready to accept commands from the host */
- NdisHardwareStatusInitializing, /**< Hardware busy initializing */
- NdisHardwareStatusReset, /**< Hardware reset */
- NdisHardwareStatusClosing, /**< Hardware currently closing */
- NdisHardwareStatusNotReady /**< Hardware not ready to accept commands from the host */
- };
-
- /* Type Defines: */
- /** Type define for a RNDIS message header, sent before RNDIS messages */
- typedef struct
- {
- uint32_t MessageType; /**< RNDIS message type, a REMOTE_NDIS_*_MSG constant */
- uint32_t MessageLength; /**< Total length of the RNDIS message, in bytes */
- } RNDIS_Message_Header_t;
-
- /** Type define for a RNDIS packet message, used to encapsulate Ethernet packets sent to and from the adapter */
- typedef struct
- {
- uint32_t MessageType;
- uint32_t MessageLength;
- uint32_t DataOffset;
- uint32_t DataLength;
- uint32_t OOBDataOffset;
- uint32_t OOBDataLength;
- uint32_t NumOOBDataElements;
- uint32_t PerPacketInfoOffset;
- uint32_t PerPacketInfoLength;
- uint32_t VcHandle;
- uint32_t Reserved;
- } RNDIS_PACKET_MSG_t;
-
- /** Type define for a RNDIS Initialize command message */
- typedef struct
- {
- uint32_t MessageType;
- uint32_t MessageLength;
- uint32_t RequestId;
-
- uint32_t MajorVersion;
- uint32_t MinorVersion;
- uint32_t MaxTransferSize;
- } RNDIS_INITIALIZE_MSG_t;
-
- /** Type define for a RNDIS Initialize complete response message */
- typedef struct
- {
- uint32_t MessageType;
- uint32_t MessageLength;
- uint32_t RequestId;
- uint32_t Status;
-
- uint32_t MajorVersion;
- uint32_t MinorVersion;
- uint32_t DeviceFlags;
- uint32_t Medium;
- uint32_t MaxPacketsPerTransfer;
- uint32_t MaxTransferSize;
- uint32_t PacketAlignmentFactor;
- uint32_t AFListOffset;
- uint32_t AFListSize;
- } RNDIS_INITIALIZE_CMPLT_t;
-
- /** Type define for a RNDIS Keepalive command message */
- typedef struct
- {
- uint32_t MessageType;
- uint32_t MessageLength;
- uint32_t RequestId;
- } RNDIS_KEEPALIVE_MSG_t;
-
- /** Type define for a RNDIS Keepalive complete message */
- typedef struct
- {
- uint32_t MessageType;
- uint32_t MessageLength;
- uint32_t RequestId;
- uint32_t Status;
- } RNDIS_KEEPALIVE_CMPLT_t;
-
- /** Type define for a RNDIS Reset complete message */
- typedef struct
- {
- uint32_t MessageType;
- uint32_t MessageLength;
- uint32_t Status;
-
- uint32_t AddressingReset;
- } RNDIS_RESET_CMPLT_t;
-
- /** Type define for a RNDIS Set command message */
- typedef struct
- {
- uint32_t MessageType;
- uint32_t MessageLength;
- uint32_t RequestId;
-
- uint32_t Oid;
- uint32_t InformationBufferLength;
- uint32_t InformationBufferOffset;
- uint32_t DeviceVcHandle;
- } RNDIS_SET_MSG_t;
-
- /** Type define for a RNDIS Set complete response message */
- typedef struct
- {
- uint32_t MessageType;
- uint32_t MessageLength;
- uint32_t RequestId;
- uint32_t Status;
- } RNDIS_SET_CMPLT_t;
-
- /** Type define for a RNDIS Query command message */
- typedef struct
- {
- uint32_t MessageType;
- uint32_t MessageLength;
- uint32_t RequestId;
-
- uint32_t Oid;
- uint32_t InformationBufferLength;
- uint32_t InformationBufferOffset;
- uint32_t DeviceVcHandle;
- } RNDIS_QUERY_MSG_t;
-
- /** Type define for a RNDIS Query complete response message */
- typedef struct
- {
- uint32_t MessageType;
- uint32_t MessageLength;
- uint32_t RequestId;
- uint32_t Status;
-
- uint32_t InformationBufferLength;
- uint32_t InformationBufferOffset;
- } RNDIS_QUERY_CMPLT_t;
-
- /* External Variables: */
- extern uint8_t RNDISMessageBuffer[];
- extern RNDIS_Message_Header_t* MessageHeader;
- extern bool ResponseReady;
- extern uint8_t CurrRNDISState;
-
- /* Function Prototypes: */
- void ProcessRNDISControlMessage(void);
-
- #if defined(INCLUDE_FROM_RNDIS_C)
- static bool ProcessNDISQuery(uint32_t OId, void* QueryData, uint16_t QuerySize,
- void* ResponseData, uint16_t* ResponseSize);
- static bool ProcessNDISSet(uint32_t OId, void* SetData, uint16_t SetSize);
- #endif
-
-#endif
diff --git a/Demos/Device/RNDISEthernet/Lib/RNDISConstants.h b/Demos/Device/RNDISEthernet/Lib/RNDISConstants.h
deleted file mode 100644
index ad66f62db..000000000
--- a/Demos/Device/RNDISEthernet/Lib/RNDISConstants.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2009.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, and distribute this software
- and its documentation for any purpose and without fee is hereby
- granted, provided that the above copyright notice appear in all
- copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * RNDIS specification related constants. For more information on these
- * constants, please refer to the Microsoft RNDIS specification.
- */
-
-#ifndef _RNDIS_CONSTANTS_H_
-#define _RNDIS_CONSTANTS_H_
-
- /* Macros: */
- #define REMOTE_NDIS_PACKET_MSG 0x00000001UL
- #define REMOTE_NDIS_INITIALIZE_MSG 0x00000002UL
- #define REMOTE_NDIS_HALT_MSG 0x00000003UL
- #define REMOTE_NDIS_QUERY_MSG 0x00000004UL
- #define REMOTE_NDIS_SET_MSG 0x00000005UL
- #define REMOTE_NDIS_RESET_MSG 0x00000006UL
- #define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007UL
- #define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008UL
-
- #define REMOTE_NDIS_INITIALIZE_CMPLT 0x80000002UL
- #define REMOTE_NDIS_QUERY_CMPLT 0x80000004UL
- #define REMOTE_NDIS_SET_CMPLT 0x80000005UL
- #define REMOTE_NDIS_RESET_CMPLT 0x80000006UL
- #define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008UL
-
- #define REMOTE_NDIS_STATUS_SUCCESS 0x00000000UL
- #define REMOTE_NDIS_STATUS_FAILURE 0xC0000001UL
- #define REMOTE_NDIS_STATUS_INVALID_DATA 0xC0010015UL
- #define REMOTE_NDIS_STATUS_NOT_SUPPORTED 0xC00000BBUL
- #define REMOTE_NDIS_STATUS_MEDIA_CONNECT 0x4001000BUL
- #define REMOTE_NDIS_STATUS_MEDIA_DISCONNECT 0x4001000CUL
-
- #define REMOTE_NDIS_MEDIA_STATE_CONNECTED 0x00000000UL
- #define REMOTE_NDIS_MEDIA_STATE_DISCONNECTED 0x00000001UL
-
- #define REMOTE_NDIS_MEDIUM_802_3 0x00000000UL
-
- #define REMOTE_NDIS_DF_CONNECTIONLESS 0x00000001UL
- #define REMOTE_NDIS_DF_CONNECTION_ORIENTED 0x00000002UL
-
- #define OID_GEN_SUPPORTED_LIST 0x00010101UL
- #define OID_GEN_HARDWARE_STATUS 0x00010102UL
- #define OID_GEN_MEDIA_SUPPORTED 0x00010103UL
- #define OID_GEN_MEDIA_IN_USE 0x00010104UL
- #define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106UL
- #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL
- #define OID_GEN_LINK_SPEED 0x00010107UL
- #define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010AUL
- #define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010BUL
- #define OID_GEN_VENDOR_ID 0x0001010CUL
- #define OID_GEN_VENDOR_DESCRIPTION 0x0001010DUL
- #define OID_GEN_CURRENT_PACKET_FILTER 0x0001010EUL
- #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL
- #define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114UL
- #define OID_GEN_PHYSICAL_MEDIUM 0x00010202UL
- #define OID_GEN_XMIT_OK 0x00020101UL
- #define OID_GEN_RCV_OK 0x00020102UL
- #define OID_GEN_XMIT_ERROR 0x00020103UL
- #define OID_GEN_RCV_ERROR 0x00020104UL
- #define OID_GEN_RCV_NO_BUFFER 0x00020105UL
- #define OID_802_3_PERMANENT_ADDRESS 0x01010101UL
- #define OID_802_3_CURRENT_ADDRESS 0x01010102UL
- #define OID_802_3_MULTICAST_LIST 0x01010103UL
- #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104UL
- #define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101UL
- #define OID_802_3_XMIT_ONE_COLLISION 0x01020102UL
- #define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103UL
-
-#endif
diff --git a/Demos/Device/RNDISEthernet/Lib/TCP.c b/Demos/Device/RNDISEthernet/Lib/TCP.c
index f259aad02..1ebd15435 100644
--- a/Demos/Device/RNDISEthernet/Lib/TCP.c
+++ b/Demos/Device/RNDISEthernet/Lib/TCP.c
@@ -56,7 +56,7 @@ TCP_ConnectionState_t ConnectionStateTable[MAX_TCP_CONNECTIONS];
* level. If an application produces a response, this task constructs the appropriate Ethernet frame and places it into the Ethernet OUT
* buffer for later transmission.
*/
-TASK(TCP_Task)
+void TCP_TCPTask(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo)
{
/* Task to hand off TCP packets to and from the listening applications. */
@@ -76,7 +76,7 @@ TASK(TCP_Task)
}
/* Bail out early if there is already a frame waiting to be sent in the Ethernet OUT buffer */
- if (FrameOUT.FrameInBuffer)
+ if (RNDISInterfaceInfo->FrameOUT.FrameInBuffer)
return;
/* Send response packets from each application as the TCP packet buffers are filled by the applications */
@@ -86,13 +86,13 @@ TASK(TCP_Task)
if ((ConnectionStateTable[CSTableEntry].Info.Buffer.Direction == TCP_PACKETDIR_OUT) &&
(ConnectionStateTable[CSTableEntry].Info.Buffer.Ready))
{
- Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&FrameOUT.FrameData;
- IP_Header_t* IPHeaderOUT = (IP_Header_t*)&FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)];
- TCP_Header_t* TCPHeaderOUT = (TCP_Header_t*)&FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) +
- sizeof(IP_Header_t)];
- void* TCPDataOUT = &FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) +
- sizeof(IP_Header_t) +
- sizeof(TCP_Header_t)];
+ Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&RNDISInterfaceInfo->FrameOUT.FrameData;
+ IP_Header_t* IPHeaderOUT = (IP_Header_t*)&RNDISInterfaceInfo->FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)];
+ TCP_Header_t* TCPHeaderOUT = (TCP_Header_t*)&RNDISInterfaceInfo->FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) +
+ sizeof(IP_Header_t)];
+ void* TCPDataOUT = &RNDISInterfaceInfo->FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) +
+ sizeof(IP_Header_t) +
+ sizeof(TCP_Header_t)];
uint16_t PacketSize = ConnectionStateTable[CSTableEntry].Info.Buffer.Length;
@@ -145,8 +145,8 @@ TASK(TCP_Task)
PacketSize += sizeof(Ethernet_Frame_Header_t);
/* Set the response length in the buffer and indicate that a response is ready to be sent */
- FrameOUT.FrameLength = PacketSize;
- FrameOUT.FrameInBuffer = true;
+ RNDISInterfaceInfo->FrameOUT.FrameLength = PacketSize;
+ RNDISInterfaceInfo->FrameOUT.FrameInBuffer = true;
ConnectionStateTable[CSTableEntry].Info.Buffer.Ready = false;
diff --git a/Demos/Device/RNDISEthernet/Lib/TCP.h b/Demos/Device/RNDISEthernet/Lib/TCP.h
index d4b72a519..3448245ed 100644
--- a/Demos/Device/RNDISEthernet/Lib/TCP.h
+++ b/Demos/Device/RNDISEthernet/Lib/TCP.h
@@ -38,9 +38,7 @@
/* Includes: */
#include <avr/io.h>
- #include <stdbool.h>
-
- #include <LUFA/Scheduler/Scheduler.h>
+ #include <stdbool.h>
#include "EthernetProtocols.h"
#include "Ethernet.h"
@@ -229,14 +227,12 @@
uint16_t Checksum; /**< TCP checksum */
uint16_t UrgentPointer; /**< Urgent data pointer */
} TCP_Header_t;
-
- /* Tasks: */
- TASK(TCP_Task);
/* External Variables: */
TCP_PortState_t PortStateTable[MAX_OPEN_TCP_PORTS];
/* Function Prototypes: */
+ void TCP_TCPTask(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo);
void TCP_Init(void);
bool TCP_SetPortState(uint16_t Port, uint8_t State, void (*Handler)(TCP_ConnectionState_t*, TCP_ConnectionBuffer_t*));
uint8_t TCP_GetPortState(uint16_t Port);
diff --git a/Demos/Device/RNDISEthernet/RNDISEthernet.c b/Demos/Device/RNDISEthernet/RNDISEthernet.c
index b046f7870..3246cd8bc 100644
--- a/Demos/Device/RNDISEthernet/RNDISEthernet.c
+++ b/Demos/Device/RNDISEthernet/RNDISEthernet.c
@@ -28,28 +28,51 @@
this software.
*/
-/** \file
- *
- * Main source file for the RNDISEthernet demo. This file contains the main tasks of the demo and
- * is responsible for the initial application hardware configuration.
- */
-
#include "RNDISEthernet.h"
-/* Scheduler Task List */
-TASK_LIST
-{
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },
- { .Task = Ethernet_Task , .TaskStatus = TASK_STOP },
- { .Task = TCP_Task , .TaskStatus = TASK_STOP },
- { .Task = RNDIS_Task , .TaskStatus = TASK_STOP },
-};
+USB_ClassInfo_RNDIS_t Ethernet_RNDIS_Interface =
+ {
+ .ControlInterfaceNumber = 0,
-/** Main program entry point. This routine configures the hardware required by the application, then
- * starts the scheduler to run the USB management task.
- */
+ .DataINEndpointNumber = CDC_TX_EPNUM,
+ .DataINEndpointSize = CDC_TXRX_EPSIZE,
+
+ .DataOUTEndpointNumber = CDC_RX_EPNUM,
+ .DataOUTEndpointSize = CDC_TXRX_EPSIZE,
+
+ .NotificationEndpointNumber = CDC_NOTIFICATION_EPNUM,
+ .NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE,
+
+ .AdapterVendorDescription = "LUFA RNDIS Demo Adapter",
+ .AdapterMACAddress = {ADAPTER_MAC_ADDRESS},
+ };
+
int main(void)
{
+ SetupHardware();
+
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+
+ printf_P(PSTR("\r\n\r\n****** RNDIS Demo running. ******\r\n"));
+
+ for (;;)
+ {
+ if (Ethernet_RNDIS_Interface.FrameIN.FrameInBuffer)
+ {
+ LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
+ Ethernet_ProcessPacket(&Ethernet_RNDIS_Interface.FrameIN, &Ethernet_RNDIS_Interface.FrameOUT);
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);
+ }
+
+ TCP_TCPTask(&Ethernet_RNDIS_Interface);
+
+ USB_RNDIS_USBTask(&Ethernet_RNDIS_Interface);
+ USB_USBTask();
+ }
+}
+
+void SetupHardware(void)
+{
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
@@ -60,279 +83,32 @@ int main(void)
/* Hardware Initialization */
LEDs_Init();
SerialStream_Init(9600, false);
-
- /* Webserver Initialization */
- TCP_Init();
- Webserver_Init();
-
- printf_P(PSTR("\r\n\r\n****** RNDIS Demo running. ******\r\n"));
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
-
- /* Initialize Scheduler so that it can be used */
- Scheduler_Init();
-
- /* Initialize USB Subsystem */
USB_Init();
- /* Scheduling - routine never returns, so put this last in the main function */
- Scheduler_Start();
+ /* Initialize TCP and Webserver modules */
+ TCP_Init();
+ Webserver_Init();
}
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and
- * starts the library USB task to begin the enumeration and USB management process.
- */
void EVENT_USB_Connect(void)
{
- /* Start USB management task */
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);
-
- /* Indicate USB enumerating */
- UpdateStatus(Status_USBEnumerating);
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
}
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
- * the status LEDs and stops all the relevant tasks.
- */
void EVENT_USB_Disconnect(void)
{
- /* Stop running TCP/IP and USB management tasks */
- Scheduler_SetTaskMode(RNDIS_Task, TASK_STOP);
- Scheduler_SetTaskMode(Ethernet_Task, TASK_STOP);
- Scheduler_SetTaskMode(TCP_Task, TASK_STOP);
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
}
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host sets the current configuration
- * of the USB device after enumeration, and configures the RNDIS device endpoints and starts the relevant tasks.
- */
void EVENT_USB_ConfigurationChanged(void)
{
- /* Setup CDC Notification, Rx and Tx Endpoints */
- Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,
- ENDPOINT_BANK_SINGLE);
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);
- Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,
- ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- /* Indicate USB connected and ready */
- UpdateStatus(Status_USBReady);
-
- /* Start TCP/IP tasks */
- Scheduler_SetTaskMode(RNDIS_Task, TASK_RUN);
- Scheduler_SetTaskMode(Ethernet_Task, TASK_RUN);
- Scheduler_SetTaskMode(TCP_Task, TASK_RUN);
+ if (!(USB_RNDIS_ConfigureEndpoints(&Ethernet_RNDIS_Interface)))
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
- * control requests that are not handled internally by the USB library (including the RNDIS control commands,
- * which set up the USB RNDIS network adapter), so that they can be handled appropriately for the application.
- */
void EVENT_USB_UnhandledControlPacket(void)
{
- /* Process RNDIS class commands */
- switch (USB_ControlRequest.bRequest)
- {
- case REQ_SendEncapsulatedCommand:
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- /* Clear the SETUP packet, ready for data transfer */
- Endpoint_ClearSETUP();
-
- /* Read in the RNDIS message into the message buffer */
- Endpoint_Read_Control_Stream_LE(RNDISMessageBuffer, USB_ControlRequest.wLength);
-
- /* Finalize the stream transfer to clear the last packet from the host */
- Endpoint_ClearIN();
-
- /* Process the RNDIS message */
- ProcessRNDISControlMessage();
- }
-
- break;
- case REQ_GetEncapsulatedResponse:
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- /* Clear the SETUP packet, ready for data transfer */
- Endpoint_ClearSETUP();
-
- /* Check if a response to the last message is ready */
- if (!(MessageHeader->MessageLength))
- {
- /* Set the response to a single 0x00 byte to indicate that no response is ready */
- RNDISMessageBuffer[0] = 0;
- MessageHeader->MessageLength = 1;
- }
-
- /* Write the message response data to the endpoint */
- Endpoint_Write_Control_Stream_LE(RNDISMessageBuffer, MessageHeader->MessageLength);
-
- /* Finalize the stream transfer to send the last packet or clear the host abort */
- Endpoint_ClearOUT();
-
- /* Reset the message header once again after transmission */
- MessageHeader->MessageLength = 0;
- }
-
- break;
- }
-}
-
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to
- * log to a serial port, or anything else that is suitable for status updates.
- *
- * \param CurrentStatus Current status of the system, from the RNDISEthernet_StatusCodes_t enum
- */
-void UpdateStatus(uint8_t CurrentStatus)
-{
- uint8_t LEDMask = LEDS_NO_LEDS;
-
- /* Set the LED mask to the appropriate LED mask based on the given status code */
- switch (CurrentStatus)
- {
- case Status_USBNotReady:
- LEDMask = (LEDS_LED1);
- break;
- case Status_USBEnumerating:
- LEDMask = (LEDS_LED1 | LEDS_LED2);
- break;
- case Status_USBReady:
- LEDMask = (LEDS_LED2 | LEDS_LED4);
- break;
- case Status_ProcessingEthernetFrame:
- LEDMask = (LEDS_LED2 | LEDS_LED3);
- break;
- }
-
- /* Set the board LEDs to the new LED mask */
- LEDs_SetAllLEDs(LEDMask);
-}
-
-/** Task to manage the sending and receiving of encapsulated RNDIS data and notifications. This removes the RNDIS
- * wrapper from received Ethernet frames and places them in the FrameIN global buffer, or adds the RNDIS wrapper
- * to a frame in the FrameOUT global before sending the buffer contents to the host.
- */
-TASK(RNDIS_Task)
-{
- /* Select the notification endpoint */
- Endpoint_SelectEndpoint(CDC_NOTIFICATION_EPNUM);
-
- /* Check if a message response is ready for the host */
- if (Endpoint_IsINReady() && ResponseReady)
- {
- USB_Notification_t Notification = (USB_Notification_t)
- {
- .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
- .bNotification = NOTIF_RESPONSE_AVAILABLE,
- .wValue = 0,
- .wIndex = 0,
- .wLength = 0,
- };
-
- /* Indicate that a message response is ready for the host */
- Endpoint_Write_Stream_LE(&Notification, sizeof(Notification));
-
- /* Finalize the stream transfer to send the last packet */
- Endpoint_ClearIN();
-
- /* Indicate a response is no longer ready */
- ResponseReady = false;
- }
-
- /* Don't process the data endpoints until the system is in the data initialized state, and the buffer is free */
- if ((CurrRNDISState == RNDIS_Data_Initialized) && !(MessageHeader->MessageLength))
- {
- /* Create a new packet header for reading/writing */
- RNDIS_PACKET_MSG_t RNDISPacketHeader;
-
- /* Select the data OUT endpoint */
- Endpoint_SelectEndpoint(CDC_RX_EPNUM);
-
- /* Check if the data OUT endpoint contains data, and that the IN buffer is empty */
- if (Endpoint_IsOUTReceived() && !(FrameIN.FrameInBuffer))
- {
- /* Read in the packet message header */
- Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_PACKET_MSG_t));
-
- /* Stall the request if the data is too large */
- if (RNDISPacketHeader.DataLength > ETHERNET_FRAME_SIZE_MAX)
- {
- Endpoint_StallTransaction();
- return;
- }
-
- /* Read in the Ethernet frame into the buffer */
- Endpoint_Read_Stream_LE(FrameIN.FrameData, RNDISPacketHeader.DataLength);
-
- /* Finalize the stream transfer to send the last packet */
- Endpoint_ClearOUT();
-
- /* Store the size of the Ethernet frame */
- FrameIN.FrameLength = RNDISPacketHeader.DataLength;
-
- /* Indicate Ethernet IN buffer full */
- FrameIN.FrameInBuffer = true;
- }
-
- /* Select the data IN endpoint */
- Endpoint_SelectEndpoint(CDC_TX_EPNUM);
-
- /* Check if the data IN endpoint is ready for more data, and that the IN buffer is full */
- if (Endpoint_IsINReady() && FrameOUT.FrameInBuffer)
- {
- /* Clear the packet header with all 0s so that the relevant fields can be filled */
- memset(&RNDISPacketHeader, 0, sizeof(RNDIS_PACKET_MSG_t));
-
- /* Construct the required packet header fields in the buffer */
- RNDISPacketHeader.MessageType = REMOTE_NDIS_PACKET_MSG;
- RNDISPacketHeader.MessageLength = (sizeof(RNDIS_PACKET_MSG_t) + FrameOUT.FrameLength);
- RNDISPacketHeader.DataOffset = (sizeof(RNDIS_PACKET_MSG_t) - sizeof(RNDIS_Message_Header_t));
- RNDISPacketHeader.DataLength = FrameOUT.FrameLength;
-
- /* Send the packet header to the host */
- Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_PACKET_MSG_t));
-
- /* Send the Ethernet frame data to the host */
- Endpoint_Write_Stream_LE(FrameOUT.FrameData, RNDISPacketHeader.DataLength);
-
- /* Finalize the stream transfer to send the last packet */
- Endpoint_ClearIN();
-
- /* Indicate Ethernet OUT buffer no longer full */
- FrameOUT.FrameInBuffer = false;
- }
- }
-}
-
-/** Ethernet frame processing task. This task checks to see if a frame has been received, and if so hands off the processing
- * of the frame to the Ethernet processing routines.
- */
-TASK(Ethernet_Task)
-{
- /* Task for Ethernet processing. Incoming ethernet frames are loaded into the FrameIN structure, and
- outgoing frames should be loaded into the FrameOUT structure. Both structures can only hold a single
- Ethernet frame at a time, so the FrameInBuffer bool is used to indicate when the buffers contain data. */
-
- /* Check if a frame has been written to the IN frame buffer */
- if (FrameIN.FrameInBuffer)
- {
- /* Indicate packet processing started */
- UpdateStatus(Status_ProcessingEthernetFrame);
-
- /* Process the ethernet frame - replace this with your own Ethernet handler code as desired */
- Ethernet_ProcessPacket();
-
- /* Indicate packet processing complete */
- UpdateStatus(Status_USBReady);
- }
+ USB_RNDIS_ProcessControlPacket(&Ethernet_RNDIS_Interface);
}
diff --git a/Demos/Device/RNDISEthernet/RNDISEthernet.h b/Demos/Device/RNDISEthernet/RNDISEthernet.h
index 703af4003..bc5004205 100644
--- a/Demos/Device/RNDISEthernet/RNDISEthernet.h
+++ b/Demos/Device/RNDISEthernet/RNDISEthernet.h
@@ -45,56 +45,34 @@
#include <stdio.h>
#include "Descriptors.h"
-
- #include "Lib/RNDIS.h"
+
#include "Lib/Ethernet.h"
#include "Lib/TCP.h"
#include "Lib/ARP.h"
#include "Lib/Webserver.h"
- #include <LUFA/Version.h> // Library Version Information
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management
- #include <LUFA/Drivers/Peripheral/SerialStream.h> // Serial stream driver
-
- /* Macros: */
- /** Notification value to indicate that a frame is ready to be read by the host. */
- #define NOTIF_RESPONSE_AVAILABLE 0x01
+ #include <LUFA/Version.h>
+ #include <LUFA/Drivers/Board/LEDs.h>
+ #include <LUFA/Drivers/Board/Joystick.h>
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/RNDIS.h>
- /* Type Defines: */
- /** Type define for a RNDIS notification message, for transmission to the RNDIS host via the notification
- * Endpoint.
- */
- typedef struct
- {
- uint8_t bmRequestType; /**< Notification type, a mask of values from SrdRequestType.h */
- uint8_t bNotification; /**< Notification index, indicating what the RNDIS notification relates to */
- uint16_t wValue; /**< Two byte notification value parameter */
- uint16_t wIndex; /**< Two byte notification index parameter */
- uint16_t wLength; /**< Size of data payload following the notification header */
- } USB_Notification_t;
-
- /* Enums: */
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */
- enum RNDISEthernet_StatusCodes_t
- {
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */
- Status_USBEnumerating = 1, /**< USB interface is enumerating */
- Status_USBReady = 2, /**< USB interface is connected and ready */
- Status_ProcessingEthernetFrame = 3, /**< Currently processing an ethernet frame from the host */
- };
+ /* Macros: */
+ #define LEDMASK_USB_NOTREADY LEDS_LED1
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
+ #define LEDMASK_USB_BUSY LEDS_LED2
- /* Tasks: */
- TASK(RNDIS_Task);
- TASK(Ethernet_Task);
-
/* Function Prototypes: */
+ void SetupHardware(void);
+
void EVENT_USB_Connect(void);
void EVENT_USB_Disconnect(void);
void EVENT_USB_ConfigurationChanged(void);
void EVENT_USB_UnhandledControlPacket(void);
-
- void UpdateStatus(uint8_t CurrentStatus);
+ void EVENT_USB_StartOfFrame(void);
+
+ void CALLBACK_USB_RNDIS_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo);
#endif
diff --git a/Demos/Device/RNDISEthernet/makefile b/Demos/Device/RNDISEthernet/makefile
index f40c37b05..3bcc37c8e 100644
--- a/Demos/Device/RNDISEthernet/makefile
+++ b/Demos/Device/RNDISEthernet/makefile
@@ -125,7 +125,6 @@ LUFA_PATH = ../../..
# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c \
Descriptors.c \
- Lib/RNDIS.c \
Lib/Ethernet.c \
Lib/ProtocolDecoders.c \
Lib/ICMP.c \
@@ -135,7 +134,6 @@ SRC = $(TARGET).c \
Lib/ARP.c \
Lib/IP.c \
Lib/Webserver.c \
- $(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \
$(LUFA_PATH)/LUFA/Drivers/Peripheral/SerialStream.c \
$(LUFA_PATH)/LUFA/Drivers/Peripheral/Serial.c \
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \
@@ -148,7 +146,7 @@ SRC = $(TARGET).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/RNDIS.c \
# List C++ source files here. (C dependencies are automatically generated.)
@@ -195,7 +193,7 @@ CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
CDEFS += -DNO_DECODE_ETHERNET -DNO_DECODE_ARP -DNO_DECODE_ICMP -DNO_DECODE_IP -DNO_DECODE_TCP -DNO_DECODE_UDP -DNO_DECODE_DHCP
diff --git a/Demos/Device/USBtoSerial/Descriptors.h b/Demos/Device/USBtoSerial/Descriptors.h
index 41b44300a..9e372e35b 100644
--- a/Demos/Device/USBtoSerial/Descriptors.h
+++ b/Demos/Device/USBtoSerial/Descriptors.h
@@ -37,26 +37,12 @@
#define _DESCRIPTORS_H_
/* Includes: */
- #include <LUFA/Drivers/USB/USB.h>
-
#include <avr/pgmspace.h>
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/CDC.h>
+
/* Macros: */
- /** Macro to define a CDC class-specific functional descriptor. CDC functional descriptors have a
- * uniform structure but variable sized data payloads, thus cannot be represented accurately by
- * a single typedef struct. A macro is used instead so that functional descriptors can be created
- * easily by specifying the size of the payload. This allows sizeof() to work correctly.
- *
- * \param DataSize Size in bytes of the CDC functional descriptor's data payload
- */
- #define CDC_FUNCTIONAL_DESCRIPTOR(DataSize) \
- struct \
- { \
- USB_Descriptor_Header_t Header; \
- uint8_t SubType; \
- uint8_t Data[DataSize]; \
- }
-
/** Endpoint number of the CDC device-to-host notification IN endpoint. */
#define CDC_NOTIFICATION_EPNUM 2
diff --git a/Demos/Device/USBtoSerial/USBtoSerial.c b/Demos/Device/USBtoSerial/USBtoSerial.c
index 7cef56560..7c89278ef 100644
--- a/Demos/Device/USBtoSerial/USBtoSerial.c
+++ b/Demos/Device/USBtoSerial/USBtoSerial.c
@@ -30,38 +30,55 @@
#include "USBtoSerial.h"
-/* Scheduler Task List */
-TASK_LIST
-{
- { .Task = USB_USBTask , .TaskStatus = TASK_STOP },
- { .Task = CDC_Task , .TaskStatus = TASK_STOP },
-};
+RingBuff_t Rx_Buffer;
+RingBuff_t Tx_Buffer;
-/* Globals: */
-/** Contains the current baud rate and other settings of the virtual serial port.
- *
- * These values are set by the host via a class-specific request, and the physical USART should be reconfigured to match the
- * new settings each time they are changed by the host.
- */
-CDC_Line_Coding_t LineCoding = { .BaudRateBPS = 9600,
- .CharFormat = OneStopBit,
- .ParityType = Parity_None,
- .DataBits = 8 };
+USB_ClassInfo_CDC_t VirtualSerial_CDC_Interface =
+ {
+ .ControlInterfaceNumber = 0,
-/** Ring (circular) buffer to hold the RX data - data from the host to the attached device on the serial port. */
-RingBuff_t Rx_Buffer;
+ .DataINEndpointNumber = CDC_TX_EPNUM,
+ .DataINEndpointSize = CDC_TXRX_EPSIZE,
-/** Ring (circular) buffer to hold the TX data - data from the attached device on the serial port to the host. */
-RingBuff_t Tx_Buffer;
+ .DataOUTEndpointNumber = CDC_RX_EPNUM,
+ .DataOUTEndpointSize = CDC_TXRX_EPSIZE,
-/** Flag to indicate if the USART is currently transmitting data from the Rx_Buffer circular buffer. */
-volatile bool Transmitting = false;
+ .NotificationEndpointNumber = CDC_NOTIFICATION_EPNUM,
+ .NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE,
+ };
-/** Main program entry point. This routine configures the hardware required by the application, then
- * starts the scheduler to run the application tasks.
- */
int main(void)
{
+ SetupHardware();
+
+ Buffer_Initialize(&Rx_Buffer);
+ Buffer_Initialize(&Tx_Buffer);
+
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+
+ for (;;)
+ {
+ for (uint8_t DataBytesRem = USB_CDC_BytesReceived(&VirtualSerial_CDC_Interface); DataBytesRem != 0; DataBytesRem--)
+ {
+ if (!(BUFF_STATICSIZE - Rx_Buffer.Elements))
+ break;
+
+ Buffer_StoreElement(&Rx_Buffer, USB_CDC_ReceiveByte(&VirtualSerial_CDC_Interface));
+ }
+
+ if (Tx_Buffer.Elements)
+ USB_CDC_SendByte(&VirtualSerial_CDC_Interface, Buffer_GetElement(&Rx_Buffer));
+
+ if (Rx_Buffer.Elements)
+ Serial_TxByte(Buffer_GetElement(&Rx_Buffer));
+
+ USB_CDC_USBTask(&VirtualSerial_CDC_Interface);
+ USB_USBTask();
+ }
+}
+
+void SetupHardware(void)
+{
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
@@ -70,304 +87,61 @@ int main(void)
clock_prescale_set(clock_div_1);
/* Hardware Initialization */
+ Joystick_Init();
LEDs_Init();
- ReconfigureUSART();
-
- /* Ring buffer Initialization */
- Buffer_Initialize(&Rx_Buffer);
- Buffer_Initialize(&Tx_Buffer);
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
-
- /* Initialize Scheduler so that it can be used */
- Scheduler_Init();
-
- /* Initialize USB Subsystem */
USB_Init();
-
- /* Scheduling - routine never returns, so put this last in the main function */
- Scheduler_Start();
}
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and
- * starts the library USB task to begin the enumeration and USB management process.
- */
void EVENT_USB_Connect(void)
{
- /* Start USB management task */
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);
-
- /* Indicate USB enumerating */
- UpdateStatus(Status_USBEnumerating);
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
}
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
- * the status LEDs and stops the USB management and CDC management tasks.
- */
void EVENT_USB_Disconnect(void)
{
- /* Stop running CDC and USB management tasks */
- Scheduler_SetTaskMode(CDC_Task, TASK_STOP);
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);
-
- /* Reset Tx and Rx buffers, device disconnected */
- Buffer_Initialize(&Rx_Buffer);
- Buffer_Initialize(&Tx_Buffer);
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
}
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
- * of the USB device after enumeration - the device endpoints are configured and the CDC management task started.
- */
void EVENT_USB_ConfigurationChanged(void)
{
- /* Setup CDC Notification, Rx and Tx Endpoints */
- Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,
- ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,
- ENDPOINT_BANK_SINGLE);
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);
- Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- /* Indicate USB connected and ready */
- UpdateStatus(Status_USBReady);
-
- /* Start CDC task */
- Scheduler_SetTaskMode(CDC_Task, TASK_RUN);
+ if (!(USB_CDC_ConfigureEndpoints(&VirtualSerial_CDC_Interface)))
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
- * control requests that are not handled internally by the USB library (including the CDC control commands,
- * which are all issued via the control endpoint), so that they can be handled appropriately for the application.
- */
void EVENT_USB_UnhandledControlPacket(void)
{
- uint8_t* LineCodingData = (uint8_t*)&LineCoding;
-
- /* Process CDC specific control requests */
- switch (USB_ControlRequest.bRequest)
- {
- case REQ_GetLineEncoding:
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- /* Acknowledge the SETUP packet, ready for data transfer */
- Endpoint_ClearSETUP();
-
- /* Write the line coding data to the control endpoint */
- Endpoint_Write_Control_Stream_LE(LineCodingData, sizeof(LineCoding));
-
- /* Finalize the stream transfer to send the last packet or clear the host abort */
- Endpoint_ClearOUT();
- }
-
- break;
- case REQ_SetLineEncoding:
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- /* Acknowledge the SETUP packet, ready for data transfer */
- Endpoint_ClearSETUP();
-
- /* Read the line coding data in from the host into the global struct */
- Endpoint_Read_Control_Stream_LE(LineCodingData, sizeof(LineCoding));
-
- /* Finalize the stream transfer to clear the last packet from the host */
- Endpoint_ClearIN();
-
- /* Reconfigure the USART with the new settings */
- ReconfigureUSART();
- }
-
- break;
- case REQ_SetControlLineState:
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- /* Acknowledge the SETUP packet, ready for data transfer */
- Endpoint_ClearSETUP();
-
- /* NOTE: Here you can read in the line state mask from the host, to get the current state of the output handshake
- lines. The mask is read in from the wValue parameter in USB_ControlRequest, and can be masked against the
- CONTROL_LINE_OUT_* masks to determine the RTS and DTR line states using the following code:
- */
-
- /* Acknowledge status stage */
- while (!(Endpoint_IsINReady()));
- Endpoint_ClearIN();
- }
-
- break;
- }
-}
-
-/** Task to manage CDC data transmission and reception to and from the host, from and to the physical USART. */
-TASK(CDC_Task)
-{
- if (USB_IsConnected)
- {
-#if 0
- /* NOTE: Here you can use the notification endpoint to send back line state changes to the host, for the special RS-232
- handshake signal lines (and some error states), via the CONTROL_LINE_IN_* masks and the following code:
- */
-
- USB_Notification_Header_t Notification = (USB_Notification_Header_t)
- {
- .NotificationType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
- .Notification = NOTIF_SerialState,
- .wValue = 0,
- .wIndex = 0,
- .wLength = sizeof(uint16_t),
- };
-
- uint16_t LineStateMask;
-
- // Set LineStateMask here to a mask of CONTROL_LINE_IN_* masks to set the input handshake line states to send to the host
-
- Endpoint_SelectEndpoint(CDC_NOTIFICATION_EPNUM);
- Endpoint_Write_Stream_LE(&Notification, sizeof(Notification));
- Endpoint_Write_Stream_LE(&LineStateMask, sizeof(LineStateMask));
- Endpoint_ClearIN();
-#endif
-
- /* Select the Serial Rx Endpoint */
- Endpoint_SelectEndpoint(CDC_RX_EPNUM);
-
- /* Check to see if a packet has been received from the host */
- if (Endpoint_IsOUTReceived())
- {
- /* Read the bytes in from the endpoint into the buffer while space is available */
- while (Endpoint_BytesInEndpoint() && (BUFF_STATICSIZE - Rx_Buffer.Elements))
- {
- /* Store each character from the endpoint */
- Buffer_StoreElement(&Rx_Buffer, Endpoint_Read_Byte());
- }
-
- /* Check to see if all bytes in the current packet have been read */
- if (!(Endpoint_BytesInEndpoint()))
- {
- /* Clear the endpoint buffer */
- Endpoint_ClearOUT();
- }
- }
-
- /* Check if Rx buffer contains data - if so, send it */
- if (Rx_Buffer.Elements)
- Serial_TxByte(Buffer_GetElement(&Rx_Buffer));
-
- /* Select the Serial Tx Endpoint */
- Endpoint_SelectEndpoint(CDC_TX_EPNUM);
-
- /* Check if the Tx buffer contains anything to be sent to the host */
- if (Tx_Buffer.Elements)
- {
- /* Wait until Serial Tx Endpoint Ready for Read/Write */
- while (!(Endpoint_IsReadWriteAllowed()));
-
- /* Write the bytes from the buffer to the endpoint while space is available */
- while (Tx_Buffer.Elements && (Endpoint_BytesInEndpoint() < CDC_TXRX_EPSIZE))
- {
- /* Write each byte retreived from the buffer to the endpoint */
- Endpoint_Write_Byte(Buffer_GetElement(&Tx_Buffer));
- }
-
- /* Remember if the packet to send completely fills the endpoint */
- bool IsFull = (Endpoint_BytesInEndpoint() == CDC_TXRX_EPSIZE);
-
- /* Send the data */
- Endpoint_ClearIN();
-
- /* If no more data to send and the last packet filled the endpoint, send an empty packet to release
- * the buffer on the receiver (otherwise all data will be cached until a non-full packet is received) */
- if (IsFull && !(Tx_Buffer.Elements))
- {
- /* Wait until Serial Tx Endpoint Ready for Read/Write */
- while (!(Endpoint_IsReadWriteAllowed()));
-
- /* Send an empty packet to terminate the transfer */
- Endpoint_ClearIN();
- }
- }
- }
+ USB_CDC_ProcessControlPacket(&VirtualSerial_CDC_Interface);
}
-/** ISR to handle the USART receive complete interrupt, fired each time the USART has received a character. This stores the received
- * character into the Tx_Buffer circular buffer for later transmission to the host.
- */
ISR(USART1_RX_vect, ISR_BLOCK)
{
- /* Only store received characters if the USB interface is connected */
if (USB_IsConnected)
- {
- /* Character received, store it into the buffer */
- Buffer_StoreElement(&Tx_Buffer, UDR1);
- }
+ Buffer_StoreElement(&Tx_Buffer, UDR1);
}
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to
- * log to a serial port, or anything else that is suitable for status updates.
- *
- * \param CurrentStatus Current status of the system, from the USBtoSerial_StatusCodes_t enum
- */
-void UpdateStatus(uint8_t CurrentStatus)
-{
- uint8_t LEDMask = LEDS_NO_LEDS;
-
- /* Set the LED mask to the appropriate LED mask based on the given status code */
- switch (CurrentStatus)
- {
- case Status_USBNotReady:
- LEDMask = (LEDS_LED1);
- break;
- case Status_USBEnumerating:
- LEDMask = (LEDS_LED1 | LEDS_LED2);
- break;
- case Status_USBReady:
- LEDMask = (LEDS_LED2 | LEDS_LED4);
- break;
- }
-
- /* Set the board LEDs to the new LED mask */
- LEDs_SetAllLEDs(LEDMask);
-}
-
-/** Reconfigures the USART to match the current serial port settings issued by the host as closely as possible. */
-void ReconfigureUSART(void)
+void EVENT_USB_CDC_LineEncodingChanged(USB_ClassInfo_CDC_t* CDCInterfaceInfo)
{
uint8_t ConfigMask = 0;
- /* Determine parity - non odd/even parity mode defaults to no parity */
- if (LineCoding.ParityType == Parity_Odd)
+ if (CDCInterfaceInfo->LineEncoding.ParityType == Parity_Odd)
ConfigMask = ((1 << UPM11) | (1 << UPM10));
- else if (LineCoding.ParityType == Parity_Even)
+ else if (CDCInterfaceInfo->LineEncoding.ParityType == Parity_Even)
ConfigMask = (1 << UPM11);
- /* Determine stop bits - 1.5 stop bits is set as 1 stop bit due to hardware limitations */
- if (LineCoding.CharFormat == TwoStopBits)
+ if (CDCInterfaceInfo->LineEncoding.CharFormat == TwoStopBits)
ConfigMask |= (1 << USBS1);
- /* Determine data size - 5, 6, 7, or 8 bits are supported */
- if (LineCoding.DataBits == 6)
+ if (CDCInterfaceInfo->LineEncoding.DataBits == 6)
ConfigMask |= (1 << UCSZ10);
- else if (LineCoding.DataBits == 7)
+ else if (CDCInterfaceInfo->LineEncoding.DataBits == 7)
ConfigMask |= (1 << UCSZ11);
- else if (LineCoding.DataBits == 8)
+ else if (CDCInterfaceInfo->LineEncoding.DataBits == 8)
ConfigMask |= ((1 << UCSZ11) | (1 << UCSZ10));
- /* Enable double speed, gives better error percentages at 8MHz */
- UCSR1A = (1 << U2X1);
-
- /* Enable transmit and receive modules and interrupts */
+ UCSR1A = (1 << U2X1);
UCSR1B = ((1 << RXCIE1) | (1 << TXEN1) | (1 << RXEN1));
-
- /* Set the USART mode to the mask generated by the Line Coding options */
- UCSR1C = ConfigMask;
-
- /* Set the USART baud rate register to the desired baud rate value */
- UBRR1 = SERIAL_2X_UBBRVAL((uint16_t)LineCoding.BaudRateBPS);
+ UCSR1C = ConfigMask;
+ UBRR1 = SERIAL_2X_UBBRVAL((uint16_t)CDCInterfaceInfo->LineEncoding.BaudRateBPS);
}
diff --git a/Demos/Device/USBtoSerial/USBtoSerial.h b/Demos/Device/USBtoSerial/USBtoSerial.h
index 8e7e8aed8..7ff796e70 100644
--- a/Demos/Device/USBtoSerial/USBtoSerial.h
+++ b/Demos/Device/USBtoSerial/USBtoSerial.h
@@ -46,140 +46,28 @@
#include "Lib/RingBuff.h"
- #include <LUFA/Version.h> // Library Version Information
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality
- #include <LUFA/Drivers/Peripheral/Serial.h> // USART driver
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver
- #include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management
+ #include <LUFA/Version.h>
+ #include <LUFA/Drivers/Board/LEDs.h>
+ #include <LUFA/Drivers/Board/Joystick.h>
+ #include <LUFA/Drivers/Peripheral/Serial.h>
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/Device/CDC.h>
/* Macros: */
- /** CDC Class specific request to get the current virtual serial port configuration settings. */
- #define REQ_GetLineEncoding 0x21
-
- /** CDC Class specific request to set the current virtual serial port configuration settings. */
- #define REQ_SetLineEncoding 0x20
-
- /** CDC Class specific request to set the current virtual serial port handshake line states. */
- #define REQ_SetControlLineState 0x22
-
- /** Notification type constant for a change in the virtual serial port handshake line states, for
- * use with a USB_Notification_Header_t notification structure when sent to the host via the CDC
- * notification endpoint.
- */
- #define NOTIF_SerialState 0x20
-
- /** Mask for the DTR handshake line for use with the REQ_SetControlLineState class specific request
- * from the host, to indicate that the DTR line state should be high.
- */
- #define CONTROL_LINE_OUT_DTR (1 << 0)
-
- /** Mask for the RTS handshake line for use with the REQ_SetControlLineState class specific request
- * from the host, to indicate that theRTS line state should be high.
- */
- #define CONTROL_LINE_OUT_RTS (1 << 1)
+ #define LEDMASK_USB_NOTREADY LEDS_LED1
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
- /** Mask for the DCD handshake line for use with the a NOTIF_SerialState class specific notification
- * from the device to the host, to indicate that the DCD line state is currently high.
- */
- #define CONTROL_LINE_IN_DCD (1 << 0)
-
- /** Mask for the DSR handshake line for use with the a NOTIF_SerialState class specific notification
- * from the device to the host, to indicate that the DSR line state is currently high.
- */
- #define CONTROL_LINE_IN_DSR (1 << 1)
-
- /** Mask for the BREAK handshake line for use with the a NOTIF_SerialState class specific notification
- * from the device to the host, to indicate that the BREAK line state is currently high.
- */
- #define CONTROL_LINE_IN_BREAK (1 << 2)
-
- /** Mask for the RING handshake line for use with the a NOTIF_SerialState class specific notification
- * from the device to the host, to indicate that the RING line state is currently high.
- */
- #define CONTROL_LINE_IN_RING (1 << 3)
-
- /** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,
- * to indicate that a framing error has occurred on the virtual serial port.
- */
- #define CONTROL_LINE_IN_FRAMEERROR (1 << 4)
-
- /** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,
- * to indicate that a parity error has occurred on the virtual serial port.
- */
- #define CONTROL_LINE_IN_PARITYERROR (1 << 5)
-
- /** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,
- * to indicate that a data overrun error has occurred on the virtual serial port.
- */
- #define CONTROL_LINE_IN_OVERRUNERROR (1 << 6)
-
- /* Type Defines: */
- /** Type define for the virtual serial port line encoding settings, for storing the current USART configuration
- * as set by the host via a class specific request.
- */
- typedef struct
- {
- uint32_t BaudRateBPS; /**< Baud rate of the virtual serial port, in bits per second */
- uint8_t CharFormat; /**< Character format of the virtual serial port, a value from the
- * CDCDevice_CDC_LineCodingFormats_t enum
- */
- uint8_t ParityType; /**< Parity setting of the virtual serial port, a value from the
- * CDCDevice_LineCodingParity_t enum
- */
- uint8_t DataBits; /**< Bits of data per character of the virtual serial port */
- } CDC_Line_Coding_t;
-
- /** Type define for a CDC notification, sent to the host via the CDC notification endpoint to indicate a
- * change in the device state asynchronously.
- */
- typedef struct
- {
- uint8_t NotificationType; /**< Notification type, a mask of REQDIR_*, REQTYPE_* and REQREC_* constants
- * from the library StdRequestType.h header
- */
- uint8_t Notification; /**< Notification value, a NOTIF_* constant */
- uint16_t wValue; /**< Notification wValue, notification-specific */
- uint16_t wIndex; /**< Notification wIndex, notification-specific */
- uint16_t wLength; /**< Notification wLength, notification-specific */
- } USB_Notification_Header_t;
-
- /* Enums: */
- /** Enum for the possible line encoding formats of a virtual serial port. */
- enum CDCDevice_CDC_LineCodingFormats_t
- {
- OneStopBit = 0, /**< Each frame contains one stop bit */
- OneAndAHalfStopBits = 1, /**< Each frame contains one and a half stop bits */
- TwoStopBits = 2, /**< Each frame contains two stop bits */
- };
-
- /** Enum for the possible line encoding parity settings of a virtual serial port. */
- enum CDCDevice_LineCodingParity_t
- {
- Parity_None = 0, /**< No parity bit mode on each frame */
- Parity_Odd = 1, /**< Odd parity bit mode on each frame */
- Parity_Even = 2, /**< Even parity bit mode on each frame */
- Parity_Mark = 3, /**< Mark parity bit mode on each frame */
- Parity_Space = 4, /**< Space parity bit mode on each frame */
- };
-
- /** Enum for the possible status codes for passing to the UpdateStatus() function. */
- enum USBtoSerial_StatusCodes_t
- {
- Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */
- Status_USBEnumerating = 1, /**< USB interface is enumerating */
- Status_USBReady = 2, /**< USB interface is connected and ready */
- };
-
- /* Tasks: */
- TASK(CDC_Task);
-
/* Function Prototypes: */
+ void SetupHardware(void);
+
void EVENT_USB_Connect(void);
void EVENT_USB_Disconnect(void);
void EVENT_USB_ConfigurationChanged(void);
void EVENT_USB_UnhandledControlPacket(void);
-
- void ReconfigureUSART(void);
- void UpdateStatus(uint8_t CurrentStatus);
+ void EVENT_USB_StartOfFrame(void);
+
+ void EVENT_USB_CDC_LineEncodingChanged(USB_ClassInfo_CDC_t* CDCInterfaceInfo);
#endif
diff --git a/Demos/Device/USBtoSerial/makefile b/Demos/Device/USBtoSerial/makefile
index 708e87246..5cf9c617e 100644
--- a/Demos/Device/USBtoSerial/makefile
+++ b/Demos/Device/USBtoSerial/makefile
@@ -126,7 +126,6 @@ LUFA_PATH = ../../..
SRC = $(TARGET).c \
Descriptors.c \
Lib/RingBuff.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 \
@@ -137,7 +136,7 @@ SRC = $(TARGET).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/CDC.c \
# List C++ source files here. (C dependencies are automatically generated.)
@@ -184,7 +183,7 @@ CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)
-CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY
+CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DUSB_DEVICE_ONLY
CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"