Fixed Mouse and Keyboard device demos not acting in accordance with the HID specification for idle periods (thanks to Brian Dickman).

Removed support for endpoint/pipe non-control interrupts; these did not act in the way users expected, and had many subtle issues.
pull/1469/head
Dean Camera 16 years ago
parent ea74397095
commit 958a1b4e2b

@ -43,9 +43,7 @@ TASK_LIST
{ .Task = USB_USBTask , .TaskStatus = TASK_STOP }, { .Task = USB_USBTask , .TaskStatus = TASK_STOP },
#endif #endif
#if !defined(INTERRUPT_DATA_ENDPOINT)
{ .Task = USB_HID_Report , .TaskStatus = TASK_STOP }, { .Task = USB_HID_Report , .TaskStatus = TASK_STOP },
#endif
}; };
/** Static buffer to hold the last received report from the host, so that it can be echoed back in the next sent report */ /** Static buffer to hold the last received report from the host, so that it can be echoed back in the next sent report */
@ -112,9 +110,7 @@ EVENT_HANDLER(USB_Connect)
EVENT_HANDLER(USB_Disconnect) EVENT_HANDLER(USB_Disconnect)
{ {
/* Stop running HID reporting and USB management tasks */ /* Stop running HID reporting and USB management tasks */
#if !defined(INTERRUPT_DATA_ENDPOINT)
Scheduler_SetTaskMode(USB_HID_Report, TASK_STOP); Scheduler_SetTaskMode(USB_HID_Report, TASK_STOP);
#endif
#if !defined(INTERRUPT_CONTROL_ENDPOINT) #if !defined(INTERRUPT_CONTROL_ENDPOINT)
Scheduler_SetTaskMode(USB_USBTask, TASK_STOP); Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);
@ -134,21 +130,11 @@ EVENT_HANDLER(USB_ConfigurationChanged)
ENDPOINT_DIR_IN, GENERIC_EPSIZE, ENDPOINT_DIR_IN, GENERIC_EPSIZE,
ENDPOINT_BANK_SINGLE); ENDPOINT_BANK_SINGLE);
#if defined(INTERRUPT_DATA_ENDPOINT)
/* Enable the endpoint IN interrupt ISR for the report endpoint */
USB_INT_Enable(ENDPOINT_INT_IN);
#endif
/* Setup Generic OUT Report Endpoint */ /* Setup Generic OUT Report Endpoint */
Endpoint_ConfigureEndpoint(GENERIC_OUT_EPNUM, EP_TYPE_INTERRUPT, Endpoint_ConfigureEndpoint(GENERIC_OUT_EPNUM, EP_TYPE_INTERRUPT,
ENDPOINT_DIR_OUT, GENERIC_EPSIZE, ENDPOINT_DIR_OUT, GENERIC_EPSIZE,
ENDPOINT_BANK_SINGLE); ENDPOINT_BANK_SINGLE);
#if defined(INTERRUPT_DATA_ENDPOINT)
/* Enable the endpoint OUT interrupt ISR for the report endpoint */
USB_INT_Enable(ENDPOINT_INT_OUT);
#endif
/* Indicate USB connected and ready */ /* Indicate USB connected and ready */
UpdateStatus(Status_USBReady); UpdateStatus(Status_USBReady);
} }
@ -266,7 +252,6 @@ void CreateGenericHIDReport(uint8_t* DataArray)
DataArray[i] = LastReceived[i]; DataArray[i] = LastReceived[i];
} }
#if !defined(INTERRUPT_DATA_ENDPOINT)
TASK(USB_HID_Report) TASK(USB_HID_Report)
{ {
/* Check if the USB system is connected to a host */ /* Check if the USB system is connected to a host */
@ -313,8 +298,8 @@ TASK(USB_HID_Report)
} }
} }
} }
#endif
#if defined(INTERRUPT_CONTROL_ENDPOINT)
/** ISR for the general Pipe/Endpoint interrupt vector. This ISR fires when an endpoint's status changes (such as /** ISR for the general Pipe/Endpoint interrupt vector. This ISR fires when an endpoint's status changes (such as
* a packet has been received) on an endpoint with its corresponding ISR enabling bits set. This is used to send * a packet has been received) on an endpoint with its corresponding ISR enabling bits set. This is used to send
* HID packets to the host each time the HID interrupt endpoints polling period elapses, as managed by the USB * HID packets to the host each time the HID interrupt endpoints polling period elapses, as managed by the USB
@ -325,7 +310,6 @@ ISR(ENDPOINT_PIPE_vect, ISR_BLOCK)
/* Save previously selected endpoint before selecting a new endpoint */ /* Save previously selected endpoint before selecting a new endpoint */
uint8_t PrevSelectedEndpoint = Endpoint_GetCurrentEndpoint(); uint8_t PrevSelectedEndpoint = Endpoint_GetCurrentEndpoint();
#if defined(INTERRUPT_CONTROL_ENDPOINT)
/* Check if the control endpoint has received a request */ /* Check if the control endpoint has received a request */
if (Endpoint_HasEndpointInterrupted(ENDPOINT_CONTROLEP)) if (Endpoint_HasEndpointInterrupted(ENDPOINT_CONTROLEP))
{ {
@ -338,60 +322,8 @@ ISR(ENDPOINT_PIPE_vect, ISR_BLOCK)
/* Handshake the endpoint setup interrupt - must be after the call to USB_USBTask() */ /* Handshake the endpoint setup interrupt - must be after the call to USB_USBTask() */
USB_INT_Clear(ENDPOINT_INT_SETUP); USB_INT_Clear(ENDPOINT_INT_SETUP);
} }
#endif
#if defined(INTERRUPT_DATA_ENDPOINT)
/* Check if Generic IN endpoint has interrupted */
if (Endpoint_HasEndpointInterrupted(GENERIC_IN_EPNUM))
{
/* Select the Generic IN Report Endpoint */
Endpoint_SelectEndpoint(GENERIC_IN_EPNUM);
/* Clear the endpoint IN interrupt flag */
USB_INT_Clear(ENDPOINT_INT_IN);
/* Clear the Generic IN Report endpoint interrupt and select the endpoint */
Endpoint_ClearEndpointInterrupt(GENERIC_IN_EPNUM);
/* 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();
}
/* Check if Generic OUT endpoint has interrupted */
if (Endpoint_HasEndpointInterrupted(GENERIC_OUT_EPNUM))
{
/* Select the Generic OUT Report Endpoint */
Endpoint_SelectEndpoint(GENERIC_OUT_EPNUM);
/* Clear the endpoint OUT Interrupt flag */
USB_INT_Clear(ENDPOINT_INT_OUT);
/* Clear the Generic OUT Report endpoint interrupt and select the endpoint */
Endpoint_ClearEndpointInterrupt(GENERIC_OUT_EPNUM);
/* 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();
}
#endif
/* Restore previously selected endpoint */ /* Restore previously selected endpoint */
Endpoint_SelectEndpoint(PrevSelectedEndpoint); Endpoint_SelectEndpoint(PrevSelectedEndpoint);
} }
#endif

@ -67,12 +67,5 @@
* which services control requests from the host. If not defined, the control endpoint * which services control requests from the host. If not defined, the control endpoint
* is serviced via polling using the task scheduler.</td> * is serviced via polling using the task scheduler.</td>
* </tr> * </tr>
* <tr>
* <td>INTERRUPT_DATA_ENDPOINT</td>
* <td>Makefile CDEFS</td>
* <td>When defined, this causes the demo to enable interrupts for the data endpoints,
* which services incoming LED reports and outgoing key status reports to and from the host.
* If not defined, the data endpoints are serviced via polling using the task scheduler.</td>
* </tr>
* </table> * </table>
*/ */

@ -56,9 +56,9 @@ TASK_LIST
bool UsingReportProtocol = true; bool UsingReportProtocol = true;
/** Current Idle period. This is set by the host via a Set Idle HID class request to silence the device's reports /** 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). * for either the entire idle duration, or until the report status changes (e.g. the user presses a key).
*/ */
uint8_t IdleCount = 0; uint16_t IdleCount = 500;
/** Current Idle period remaining. When the IdleCount value is set, this tracks the remaining number of idle /** 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 * milliseconds. This is separate to the IdleCount timer and is incremented and compared as the host may request
@ -140,9 +140,7 @@ EVENT_HANDLER(USB_Reset)
EVENT_HANDLER(USB_Disconnect) EVENT_HANDLER(USB_Disconnect)
{ {
/* Stop running keyboard reporting and USB management tasks */ /* Stop running keyboard reporting and USB management tasks */
#if !defined(INTERRUPT_DATA_ENDPOINT)
Scheduler_SetTaskMode(USB_Keyboard_Report, TASK_STOP); Scheduler_SetTaskMode(USB_Keyboard_Report, TASK_STOP);
#endif
#if !defined(INTERRUPT_CONTROL_ENDPOINT) #if !defined(INTERRUPT_CONTROL_ENDPOINT)
Scheduler_SetTaskMode(USB_USBTask, TASK_STOP); Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);
@ -162,28 +160,16 @@ EVENT_HANDLER(USB_ConfigurationChanged)
ENDPOINT_DIR_IN, KEYBOARD_EPSIZE, ENDPOINT_DIR_IN, KEYBOARD_EPSIZE,
ENDPOINT_BANK_SINGLE); ENDPOINT_BANK_SINGLE);
#if defined(INTERRUPT_DATA_ENDPOINT)
/* Enable the endpoint IN interrupt ISR for the report endpoint */
USB_INT_Enable(ENDPOINT_INT_IN);
#endif
/* Setup Keyboard LED Report Endpoint */ /* Setup Keyboard LED Report Endpoint */
Endpoint_ConfigureEndpoint(KEYBOARD_LEDS_EPNUM, EP_TYPE_INTERRUPT, Endpoint_ConfigureEndpoint(KEYBOARD_LEDS_EPNUM, EP_TYPE_INTERRUPT,
ENDPOINT_DIR_OUT, KEYBOARD_EPSIZE, ENDPOINT_DIR_OUT, KEYBOARD_EPSIZE,
ENDPOINT_BANK_SINGLE); ENDPOINT_BANK_SINGLE);
#if defined(INTERRUPT_DATA_ENDPOINT)
/* Enable the endpoint OUT interrupt ISR for the LED report endpoint */
USB_INT_Enable(ENDPOINT_INT_OUT);
#endif
/* Indicate USB connected and ready */ /* Indicate USB connected and ready */
UpdateStatus(Status_USBReady); UpdateStatus(Status_USBReady);
#if !defined(INTERRUPT_DATA_ENDPOINT)
/* Start running keyboard reporting task */ /* Start running keyboard reporting task */
Scheduler_SetTaskMode(USB_Keyboard_Report, TASK_RUN); Scheduler_SetTaskMode(USB_Keyboard_Report, TASK_RUN);
#endif
} }
/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific /** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
@ -358,7 +344,7 @@ void ProcessLEDReport(uint8_t LEDReport)
} }
/** Sends the next HID report to the host, via the keyboard data endpoint. */ /** Sends the next HID report to the host, via the keyboard data endpoint. */
static inline void SendNextReport(void) void SendNextReport(void)
{ {
static USB_KeyboardReport_Data_t PrevKeyboardReportData; static USB_KeyboardReport_Data_t PrevKeyboardReportData;
USB_KeyboardReport_Data_t KeyboardReportData; USB_KeyboardReport_Data_t KeyboardReportData;
@ -367,29 +353,26 @@ static inline void SendNextReport(void)
/* Create the next keyboard report for transmission to the host */ /* Create the next keyboard report for transmission to the host */
CreateKeyboardReport(&KeyboardReportData); CreateKeyboardReport(&KeyboardReportData);
/* Check if the idle period is set */ /* Check to see if the report data has changed - if so a report MUST be sent */
if (IdleCount)
{
/* Check if idle period has elapsed */
if (!(IdleMSRemaining))
{
/* Reset the idle time remaining counter, must multiply by 4 to get the duration in milliseconds */
IdleMSRemaining = (IdleCount << 2);
}
else
{
/* Idle period not elapsed, indicate that a report must not be sent unless the report has changed */
SendReport = (memcmp(&PrevKeyboardReportData, &KeyboardReportData, sizeof(USB_KeyboardReport_Data_t)) != 0); SendReport = (memcmp(&PrevKeyboardReportData, &KeyboardReportData, sizeof(USB_KeyboardReport_Data_t)) != 0);
}
}
/* Save the current report data for later comparison to check for changes */ /* Save the current report data for later comparison to check for changes */
PrevKeyboardReportData = KeyboardReportData; 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 */ /* Select the Keyboard Report Endpoint */
Endpoint_SelectEndpoint(KEYBOARD_EPNUM); Endpoint_SelectEndpoint(KEYBOARD_EPNUM);
/* Check if Keyboard Endpoint Ready for Read/Write, and if we should send a report */ /* Check if Keyboard Endpoint Ready for Read/Write and if we should send a new report */
if (Endpoint_IsReadWriteAllowed() && SendReport) if (Endpoint_IsReadWriteAllowed() && SendReport)
{ {
/* Write Keyboard Report Data */ /* Write Keyboard Report Data */
@ -401,7 +384,7 @@ static inline void SendNextReport(void)
} }
/** Reads the next LED status report from the host from the LED data endpoint, if one has been sent. */ /** Reads the next LED status report from the host from the LED data endpoint, if one has been sent. */
static inline void ReceiveNextReport(void) void ReceiveNextReport(void)
{ {
/* Select the Keyboard LED Report Endpoint */ /* Select the Keyboard LED Report Endpoint */
Endpoint_SelectEndpoint(KEYBOARD_LEDS_EPNUM); Endpoint_SelectEndpoint(KEYBOARD_LEDS_EPNUM);
@ -451,7 +434,6 @@ void UpdateStatus(uint8_t CurrentStatus)
LEDs_SetAllLEDs(LEDMask); LEDs_SetAllLEDs(LEDMask);
} }
#if !defined(INTERRUPT_DATA_ENDPOINT)
/** Function to manage HID report generation and transmission to the host, when in report mode. */ /** Function to manage HID report generation and transmission to the host, when in report mode. */
TASK(USB_Keyboard_Report) TASK(USB_Keyboard_Report)
{ {
@ -465,8 +447,8 @@ TASK(USB_Keyboard_Report)
ReceiveNextReport(); ReceiveNextReport();
} }
} }
#endif
#if defined(INTERRUPT_CONTROL_ENDPOINT)
/** ISR for the general Pipe/Endpoint interrupt vector. This ISR fires when an endpoint's status changes (such as /** ISR for the general Pipe/Endpoint interrupt vector. This ISR fires when an endpoint's status changes (such as
* a packet has been received) on an endpoint with its corresponding ISR enabling bits set. This is used to send * a packet has been received) on an endpoint with its corresponding ISR enabling bits set. This is used to send
* HID packets to the host each time the HID interrupt endpoints polling period elapses, as managed by the USB * HID packets to the host each time the HID interrupt endpoints polling period elapses, as managed by the USB
@ -475,52 +457,20 @@ TASK(USB_Keyboard_Report)
*/ */
ISR(ENDPOINT_PIPE_vect, ISR_BLOCK) ISR(ENDPOINT_PIPE_vect, ISR_BLOCK)
{ {
#if defined(INTERRUPT_CONTROL_ENDPOINT) /* Save previously selected endpoint before selecting a new endpoint */
uint8_t PrevSelectedEndpoint = Endpoint_GetCurrentEndpoint();
/* Check if the control endpoint has received a request */ /* Check if the control endpoint has received a request */
if (Endpoint_HasEndpointInterrupted(ENDPOINT_CONTROLEP)) if (Endpoint_HasEndpointInterrupted(ENDPOINT_CONTROLEP))
{ {
/* Clear the endpoint interrupt */
Endpoint_ClearEndpointInterrupt(ENDPOINT_CONTROLEP);
/* Process the control request */ /* Process the control request */
USB_USBTask(); USB_USBTask();
/* Handshake the endpoint setup interrupt - must be after the call to USB_USBTask() */ /* Handshake the endpoint setup interrupt - must be after the call to USB_USBTask() */
USB_INT_Clear(ENDPOINT_INT_SETUP); USB_INT_Clear(ENDPOINT_INT_SETUP);
} }
#endif
#if defined(INTERRUPT_DATA_ENDPOINT)
/* Check if keyboard endpoint has interrupted */
if (Endpoint_HasEndpointInterrupted(KEYBOARD_EPNUM))
{
/* Select the Keyboard Report Endpoint */
Endpoint_SelectEndpoint(KEYBOARD_EPNUM);
/* Clear the endpoint IN interrupt flag */
USB_INT_Clear(ENDPOINT_INT_IN);
/* Clear the Keyboard Report endpoint interrupt */
Endpoint_ClearEndpointInterrupt(KEYBOARD_EPNUM);
/* Send the next keypress report to the host */
SendNextReport();
}
/* Check if Keyboard LED status Endpoint has interrupted */
if (Endpoint_HasEndpointInterrupted(KEYBOARD_LEDS_EPNUM))
{
/* Select the Keyboard LED Report Endpoint */
Endpoint_SelectEndpoint(KEYBOARD_LEDS_EPNUM);
/* Clear the endpoint OUT interrupt flag */
USB_INT_Clear(ENDPOINT_INT_OUT);
/* Clear the Keyboard LED Report endpoint interrupt */ /* Restore previously selected endpoint */
Endpoint_ClearEndpointInterrupt(KEYBOARD_LEDS_EPNUM); Endpoint_SelectEndpoint(PrevSelectedEndpoint);
/* Process the LED report sent from the host */
ReceiveNextReport();
}
#endif
} }
#endif

@ -54,6 +54,9 @@
#include <LUFA/Drivers/Board/LEDs.h> // LEDs driver #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver
/* Macros: */ /* 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. */ /** HID Class specific request to get the next HID report from the device. */
#define REQ_GetReport 0x01 #define REQ_GetReport 0x01
@ -114,8 +117,8 @@
/* Function Prototypes: */ /* Function Prototypes: */
void CreateKeyboardReport(USB_KeyboardReport_Data_t* ReportData); void CreateKeyboardReport(USB_KeyboardReport_Data_t* ReportData);
void ProcessLEDReport(uint8_t LEDReport); void ProcessLEDReport(uint8_t LEDReport);
static inline void SendNextReport(void); void SendNextReport(void);
static inline void ReceiveNextReport(void); void ReceiveNextReport(void);
void UpdateStatus(uint8_t CurrentStatus); void UpdateStatus(uint8_t CurrentStatus);
#endif #endif

@ -63,12 +63,5 @@
* which services control requests from the host. If not defined, the control endpoint * which services control requests from the host. If not defined, the control endpoint
* is serviced via polling using the task scheduler.</td> * is serviced via polling using the task scheduler.</td>
* </tr> * </tr>
* <tr>
* <td>INTERRUPT_DATA_ENDPOINT</td>
* <td>Makefile CDEFS</td>
* <td>When defined, this causes the demo to enable interrupts for the data endpoints,
* which services incoming LED reports and outgoing key status reports to and from the host.
* If not defined, the data endpoints are serviced via polling using the task scheduler.</td>
* </tr>
* </table> * </table>
*/ */

@ -387,9 +387,6 @@ ISR(ENDPOINT_PIPE_vect, ISR_BLOCK)
/* Check if the control endpoint has received a request */ /* Check if the control endpoint has received a request */
if (Endpoint_HasEndpointInterrupted(ENDPOINT_CONTROLEP)) if (Endpoint_HasEndpointInterrupted(ENDPOINT_CONTROLEP))
{ {
/* Clear the endpoint interrupt */
Endpoint_ClearEndpointInterrupt(ENDPOINT_CONTROLEP);
/* Process the control request */ /* Process the control request */
USB_USBTask(); USB_USBTask();

@ -43,9 +43,7 @@ TASK_LIST
{ .Task = USB_USBTask , .TaskStatus = TASK_STOP }, { .Task = USB_USBTask , .TaskStatus = TASK_STOP },
#endif #endif
#if !defined(INTERRUPT_DATA_ENDPOINT)
{ .Task = USB_Mouse_Report , .TaskStatus = TASK_STOP }, { .Task = USB_Mouse_Report , .TaskStatus = TASK_STOP },
#endif
}; };
/* Global Variables */ /* Global Variables */
@ -57,7 +55,7 @@ bool UsingReportProtocol = true;
/** Current Idle period. This is set by the host via a Set Idle HID class request to silence the device's reports /** 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). * for either the entire idle duration, or until the report status changes (e.g. the user moves the mouse).
*/ */
uint8_t IdleCount = 0; uint16_t IdleCount = HID_IDLE_CHANGESONLY;
/** Current Idle period remaining. When the IdleCount value is set, this tracks the remaining number of idle /** 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 * milliseconds. This is separate to the IdleCount timer and is incremented and compared as the host may request
@ -140,9 +138,7 @@ EVENT_HANDLER(USB_Reset)
EVENT_HANDLER(USB_Disconnect) EVENT_HANDLER(USB_Disconnect)
{ {
/* Stop running mouse reporting and USB management tasks */ /* Stop running mouse reporting and USB management tasks */
#if !defined(INTERRUPT_DATA_ENDPOINT)
Scheduler_SetTaskMode(USB_Mouse_Report, TASK_STOP); Scheduler_SetTaskMode(USB_Mouse_Report, TASK_STOP);
#endif
#if !defined(INTERRUPT_CONTROL_ENDPOINT) #if !defined(INTERRUPT_CONTROL_ENDPOINT)
Scheduler_SetTaskMode(USB_USBTask, TASK_STOP); Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);
@ -162,18 +158,11 @@ EVENT_HANDLER(USB_ConfigurationChanged)
ENDPOINT_DIR_IN, MOUSE_EPSIZE, ENDPOINT_DIR_IN, MOUSE_EPSIZE,
ENDPOINT_BANK_SINGLE); ENDPOINT_BANK_SINGLE);
#if defined(INTERRUPT_DATA_ENDPOINT)
/* Enable the endpoint IN interrupt ISR for the report endpoint */
USB_INT_Enable(ENDPOINT_INT_IN);
#endif
/* Indicate USB connected and ready */ /* Indicate USB connected and ready */
UpdateStatus(Status_USBReady); UpdateStatus(Status_USBReady);
#if !defined(INTERRUPT_DATA_ENDPOINT)
/* Start running mouse reporting task */ /* Start running mouse reporting task */
Scheduler_SetTaskMode(USB_Mouse_Report, TASK_RUN); Scheduler_SetTaskMode(USB_Mouse_Report, TASK_RUN);
#endif
} }
/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific /** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
@ -311,34 +300,36 @@ void CreateMouseReport(USB_MouseReport_Data_t* ReportData)
} }
/** Sends the next HID report to the host, via the keyboard data endpoint. */ /** Sends the next HID report to the host, via the keyboard data endpoint. */
static inline void SendNextReport(void) void SendNextReport(void)
{ {
static USB_MouseReport_Data_t PrevMouseReportData; static USB_MouseReport_Data_t PrevMouseReportData;
USB_MouseReport_Data_t MouseReportData; USB_MouseReport_Data_t MouseReportData;
bool SendReport = true; bool SendReport;
/* Create the next mouse report for transmission to the host */ /* Create the next mouse report for transmission to the host */
CreateMouseReport(&MouseReportData); CreateMouseReport(&MouseReportData);
/* Check if the idle period is set*/ /* Check to see if the report data has changed - if so a report MUST be sent */
if (IdleCount)
{
/* Determine if the idle period has elapsed */
if (!(IdleMSRemaining))
{
/* Reset the idle time remaining counter, must multiply by 4 to get the duration in milliseconds */
IdleMSRemaining = (IdleCount << 2);
}
else
{
/* Idle period not elapsed, indicate that a report must not be sent unless the report has changed */
SendReport = (memcmp(&PrevMouseReportData, &MouseReportData, sizeof(USB_MouseReport_Data_t)) != 0); 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 */ /* Save the current report data for later comparison to check for changes */
PrevMouseReportData = MouseReportData; 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;
}
/* Select the Mouse Report Endpoint */ /* Select the Mouse Report Endpoint */
Endpoint_SelectEndpoint(MOUSE_EPNUM); Endpoint_SelectEndpoint(MOUSE_EPNUM);
@ -380,7 +371,6 @@ void UpdateStatus(uint8_t CurrentStatus)
LEDs_SetAllLEDs(LEDMask); LEDs_SetAllLEDs(LEDMask);
} }
#if !defined(INTERRUPT_DATA_ENDPOINT)
/** Task to manage HID report generation and transmission to the host, when in report mode. */ /** Task to manage HID report generation and transmission to the host, when in report mode. */
TASK(USB_Mouse_Report) TASK(USB_Mouse_Report)
{ {
@ -391,8 +381,8 @@ TASK(USB_Mouse_Report)
SendNextReport(); SendNextReport();
} }
} }
#endif
#if defined(INTERRUPT_CONTROL_ENDPOINT)
/** ISR for the general Pipe/Endpoint interrupt vector. This ISR fires when an endpoint's status changes (such as /** ISR for the general Pipe/Endpoint interrupt vector. This ISR fires when an endpoint's status changes (such as
* a packet has been received) on an endpoint with its corresponding ISR enabling bits set. This is used to send * a packet has been received) on an endpoint with its corresponding ISR enabling bits set. This is used to send
* HID packets to the host each time the HID interrupt endpoints polling period elapses, as managed by the USB * HID packets to the host each time the HID interrupt endpoints polling period elapses, as managed by the USB
@ -401,36 +391,20 @@ TASK(USB_Mouse_Report)
*/ */
ISR(ENDPOINT_PIPE_vect, ISR_BLOCK) ISR(ENDPOINT_PIPE_vect, ISR_BLOCK)
{ {
#if defined(INTERRUPT_CONTROL_ENDPOINT) /* Save previously selected endpoint before selecting a new endpoint */
uint8_t PrevSelectedEndpoint = Endpoint_GetCurrentEndpoint();
/* Check if the control endpoint has received a request */ /* Check if the control endpoint has received a request */
if (Endpoint_HasEndpointInterrupted(ENDPOINT_CONTROLEP)) if (Endpoint_HasEndpointInterrupted(ENDPOINT_CONTROLEP))
{ {
/* Clear the endpoint interrupt */
Endpoint_ClearEndpointInterrupt(ENDPOINT_CONTROLEP);
/* Process the control request */ /* Process the control request */
USB_USBTask(); USB_USBTask();
/* Handshake the endpoint setup interrupt - must be after the call to USB_USBTask() */ /* Handshake the endpoint setup interrupt - must be after the call to USB_USBTask() */
USB_INT_Clear(ENDPOINT_INT_SETUP); USB_INT_Clear(ENDPOINT_INT_SETUP);
} }
#endif
#if defined(INTERRUPT_DATA_ENDPOINT)
/* Check if mouse endpoint has interrupted */
if (Endpoint_HasEndpointInterrupted(MOUSE_EPNUM))
{
/* Select the Mouse Report Endpoint */
Endpoint_SelectEndpoint(MOUSE_EPNUM);
/* Clear the endpoint IN interrupt flag */
USB_INT_Clear(ENDPOINT_INT_IN);
/* Clear the Mouse Report endpoint interrupt and select the endpoint */ /* Restore previously selected endpoint */
Endpoint_ClearEndpointInterrupt(MOUSE_EPNUM); Endpoint_SelectEndpoint(PrevSelectedEndpoint);
/* Send the next mouse report to the host */
SendNextReport();
}
#endif
} }
#endif

@ -57,6 +57,9 @@
TASK(USB_Mouse_Report); TASK(USB_Mouse_Report);
/* Macros: */ /* 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. */ /** HID Class specific request to get the next HID report from the device. */
#define REQ_GetReport 0x01 #define REQ_GetReport 0x01

@ -64,12 +64,5 @@
* which services control requests from the host. If not defined, the control endpoint * which services control requests from the host. If not defined, the control endpoint
* is serviced via polling using the task scheduler.</td> * is serviced via polling using the task scheduler.</td>
* </tr> * </tr>
* <tr>
* <td>INTERRUPT_DATA_ENDPOINT</td>
* <td>Makefile CDEFS</td>
* <td>When defined, this causes the demo to enable interrupts for the data endpoint,
* which services outgoing mouse button and movement reports to the host. If not defined,
* the data endpoint is serviced via polling using the task scheduler.</td>
* </tr>
* </table> * </table>
*/ */

@ -182,10 +182,8 @@ void ReadNextReport(void)
/* Check to see if a packet has been received */ /* Check to see if a packet has been received */
if (!(Pipe_IsINReceived())) if (!(Pipe_IsINReceived()))
{ {
#if !defined(INTERRUPT_DATA_PIPE)
/* Refreeze HID data IN pipe */ /* Refreeze HID data IN pipe */
Pipe_Freeze(); Pipe_Freeze();
#endif
return; return;
} }
@ -208,10 +206,8 @@ void ReadNextReport(void)
/* Clear the IN endpoint, ready for next data packet */ /* Clear the IN endpoint, ready for next data packet */
Pipe_ClearIN(); Pipe_ClearIN();
#if !defined(INTERRUPT_DATA_PIPE)
/* Refreeze HID data IN pipe */ /* Refreeze HID data IN pipe */
Pipe_Freeze(); Pipe_Freeze();
#endif
} }
/** Writes a report to the attached device. /** Writes a report to the attached device.
@ -345,43 +341,9 @@ TASK(USB_HID_Host)
USB_HostState = HOST_STATE_Ready; USB_HostState = HOST_STATE_Ready;
break; break;
#if !defined(INTERRUPT_DATA_PIPE)
case HOST_STATE_Ready: case HOST_STATE_Ready:
ReadNextReport(); ReadNextReport();
break; break;
#endif
} }
} }
#if defined(INTERRUPT_DATA_PIPE)
/** Interrupt handler for the Endpoint/Pipe interrupt vector. This interrupt fires each time an enabled
* pipe interrupt occurs on a pipe which has had that interrupt enabled.
*/
ISR(ENDPOINT_PIPE_vect, ISR_BLOCK)
{
/* Save previously selected pipe before selecting a new pipe */
uint8_t PrevSelectedPipe = Pipe_GetCurrentPipe();
/* Check to see if the HID data IN pipe has caused the interrupt */
if (Pipe_HasPipeInterrupted(HID_DATA_IN_PIPE))
{
/* Clear the pipe interrupt, and select the data IN pipe */
Pipe_ClearPipeInterrupt(HID_DATA_IN_PIPE);
Pipe_SelectPipe(HID_DATA_IN_PIPE);
/* Check to see if the pipe IN interrupt has fired */
if (USB_INT_HasOccurred(PIPE_INT_IN) && USB_INT_IsEnabled(PIPE_INT_IN))
{
/* Clear interrupt flag */
USB_INT_Clear(PIPE_INT_IN);
/* Read and process the next report from the device */
ReadNextReport();
}
}
/* Restore previously selected pipe */
Pipe_SelectPipe(PrevSelectedPipe);
}
#endif

@ -47,16 +47,9 @@
* *
* <table> * <table>
* <tr> * <tr>
* <td><b>Define Name:</b></td> * <td>
* <td><b>Location:</b></td> * None
* <td><b>Description:</b></td> * </td>
* </tr>
* <tr>
* <td>INTERRUPT_DATA_ENDPOINT</td>
* <td>Makefile CDEFS</td>
* <td>When defined, this causes the demo to enable interrupts for the data IN pipe,
* which services reports from the device. If not defined, the data pipe is
* serviced via polling using the task scheduler.</td>
* </tr> * </tr>
* </table> * </table>
*/ */

@ -180,18 +180,14 @@ void ReadNextReport(void)
/* Select keyboard data pipe */ /* Select keyboard data pipe */
Pipe_SelectPipe(KEYBOARD_DATAPIPE); Pipe_SelectPipe(KEYBOARD_DATAPIPE);
#if !defined(INTERRUPT_DATA_PIPE)
/* Unfreeze keyboard data pipe */ /* Unfreeze keyboard data pipe */
Pipe_Unfreeze(); Pipe_Unfreeze();
#endif
/* Check to see if a packet has been received */ /* Check to see if a packet has been received */
if (!(Pipe_IsINReceived())) if (!(Pipe_IsINReceived()))
{ {
#if !defined(INTERRUPT_DATA_PIPE)
/* Refreeze HID data IN pipe */ /* Refreeze HID data IN pipe */
Pipe_Freeze(); Pipe_Freeze();
#endif
return; return;
} }
@ -232,14 +228,11 @@ void ReadNextReport(void)
} }
} }
/* Clear the IN endpoint, ready for next data packet */ /* Clear the IN endpoint, ready for next data packet */
Pipe_ClearIN(); Pipe_ClearIN();
#if !defined(INTERRUPT_DATA_PIPE)
/* Refreeze keyboard data pipe */ /* Refreeze keyboard data pipe */
Pipe_Freeze(); Pipe_Freeze();
#endif
} }
/** Task to set the configuration of the attached device after it has been enumerated, and to read and process /** Task to set the configuration of the attached device after it has been enumerated, and to read and process
@ -329,53 +322,14 @@ TASK(USB_Keyboard_Host)
break; break;
} }
#if defined(INTERRUPT_DATA_PIPE)
/* Select and unfreeze keyboard data pipe */
Pipe_SelectPipe(KEYBOARD_DATAPIPE);
Pipe_Unfreeze();
#endif
puts_P(PSTR("Keyboard Enumerated.\r\n")); puts_P(PSTR("Keyboard Enumerated.\r\n"));
USB_HostState = HOST_STATE_Ready; USB_HostState = HOST_STATE_Ready;
break; break;
#if !defined(INTERRUPT_DATA_PIPE)
case HOST_STATE_Ready: case HOST_STATE_Ready:
/* If a report has been received, read and process it */ /* If a report has been received, read and process it */
ReadNextReport(); ReadNextReport();
break; break;
#endif
} }
} }
#if defined(INTERRUPT_DATA_PIPE)
/** Interrupt handler for the Endpoint/Pipe interrupt vector. This interrupt fires each time an enabled
* pipe interrupt occurs on a pipe which has had that interrupt enabled.
*/
ISR(ENDPOINT_PIPE_vect, ISR_BLOCK)
{
/* Save previously selected pipe before selecting a new pipe */
uint8_t PrevSelectedPipe = Pipe_GetCurrentPipe();
/* Check to see if the keyboard data pipe has caused the interrupt */
if (Pipe_HasPipeInterrupted(KEYBOARD_DATAPIPE))
{
/* Clear the pipe interrupt, and select the keyboard pipe */
Pipe_ClearPipeInterrupt(KEYBOARD_DATAPIPE);
Pipe_SelectPipe(KEYBOARD_DATAPIPE);
/* Check to see if the pipe IN interrupt has fired */
if (USB_INT_HasOccurred(PIPE_INT_IN) && USB_INT_IsEnabled(PIPE_INT_IN))
{
/* Clear interrupt flag */
USB_INT_Clear(PIPE_INT_IN);
/* Read and process the next report from the device */
ReadNextReport();
}
/* Restore previously selected pipe */
Pipe_SelectPipe(PrevSelectedPipe);
}
#endif

@ -56,16 +56,9 @@
* *
* <table> * <table>
* <tr> * <tr>
* <td><b>Define Name:</b></td> * <td>
* <td><b>Location:</b></td> * None
* <td><b>Description:</b></td> * </td>
* </tr>
* <tr>
* <td>INTERRUPT_DATA_ENDPOINT</td>
* <td>Makefile CDEFS</td>
* <td>When defined, this causes the demo to enable interrupts for the data pipe,
* which services reports from the device. If not defined, the data pipe is
* serviced via polling using the task scheduler.</td>
* </tr> * </tr>
* </table> * </table>
*/ */

@ -181,18 +181,14 @@ void ReadNextReport(void)
/* Select mouse data pipe */ /* Select mouse data pipe */
Pipe_SelectPipe(MOUSE_DATAPIPE); Pipe_SelectPipe(MOUSE_DATAPIPE);
#if !defined(INTERRUPT_DATA_PIPE)
/* Unfreeze keyboard data pipe */ /* Unfreeze keyboard data pipe */
Pipe_Unfreeze(); Pipe_Unfreeze();
#endif
/* Check to see if a packet has been received */ /* Check to see if a packet has been received */
if (!(Pipe_IsINReceived())) if (!(Pipe_IsINReceived()))
{ {
#if !defined(INTERRUPT_DATA_PIPE)
/* Refreeze HID data IN pipe */ /* Refreeze HID data IN pipe */
Pipe_Freeze(); Pipe_Freeze();
#endif
return; return;
} }
@ -230,10 +226,8 @@ void ReadNextReport(void)
/* Clear the IN endpoint, ready for next data packet */ /* Clear the IN endpoint, ready for next data packet */
Pipe_ClearIN(); Pipe_ClearIN();
#if !defined(INTERRUPT_DATA_PIPE)
/* Refreeze mouse data pipe */ /* Refreeze mouse data pipe */
Pipe_Freeze(); Pipe_Freeze();
#endif
} }
/** Task to set the configuration of the attached device after it has been enumerated, and to read and process /** Task to set the configuration of the attached device after it has been enumerated, and to read and process
@ -324,54 +318,14 @@ TASK(USB_Mouse_Host)
break; break;
} }
#if defined(INTERRUPT_DATA_PIPE)
/* Select and unfreeze mouse data pipe */
Pipe_SelectPipe(MOUSE_DATAPIPE);
Pipe_Unfreeze();
#endif
puts_P(PSTR("Mouse Enumerated.\r\n")); puts_P(PSTR("Mouse Enumerated.\r\n"));
USB_HostState = HOST_STATE_Ready; USB_HostState = HOST_STATE_Ready;
break; break;
#if !defined(INTERRUPT_DATA_PIPE)
case HOST_STATE_Ready: case HOST_STATE_Ready:
/* If a report has been received, read and process it */ /* If a report has been received, read and process it */
ReadNextReport(); ReadNextReport();
break; break;
#endif
} }
} }
#if defined(INTERRUPT_DATA_PIPE)
/** Interrupt handler for the Endpoint/Pipe interrupt vector. This interrupt fires each time an enabled
* pipe interrupt occurs on a pipe which has had that interrupt enabled.
*/
ISR(ENDPOINT_PIPE_vect, ISR_BLOCK)
{
/* Save previously selected pipe before selecting a new pipe */
uint8_t PrevSelectedPipe = Pipe_GetCurrentPipe();
/* Check to see if the mouse data pipe has caused the interrupt */
if (Pipe_HasPipeInterrupted(MOUSE_DATAPIPE))
{
/* Clear the pipe interrupt, and select the mouse pipe */
Pipe_ClearPipeInterrupt(MOUSE_DATAPIPE);
Pipe_SelectPipe(MOUSE_DATAPIPE);
/* Check to see if the pipe IN interrupt has fired */
if (USB_INT_HasOccurred(PIPE_INT_IN) && USB_INT_IsEnabled(PIPE_INT_IN))
{
/* Clear interrupt flag */
USB_INT_Clear(PIPE_INT_IN);
/* Read and process the next report from the device */
ReadNextReport();
}
}
/* Restore previously selected pipe */
Pipe_SelectPipe(PrevSelectedPipe);
}
#endif

@ -57,16 +57,9 @@
* *
* <table> * <table>
* <tr> * <tr>
* <td><b>Define Name:</b></td> * <td>
* <td><b>Location:</b></td> * None
* <td><b>Description:</b></td> * </td>
* </tr>
* <tr>
* <td>INTERRUPT_DATA_ENDPOINT</td>
* <td>Makefile CDEFS</td>
* <td>When defined, this causes the demo to enable interrupts for the data pipe,
* which services reports from the device. If not defined, the data pipe is
* serviced via polling using the task scheduler.</td>
* </tr> * </tr>
* </table> * </table>
*/ */

@ -175,6 +175,8 @@ EVENT_HANDLER(USB_DeviceEnumerationFailed)
{ {
puts_P(PSTR(ESC_BG_RED "Dev Enum Error\r\n")); puts_P(PSTR(ESC_BG_RED "Dev Enum Error\r\n"));
printf_P(PSTR(" -- Error Code %d\r\n"), ErrorCode); printf_P(PSTR(" -- Error Code %d\r\n"), ErrorCode);
printf_P(PSTR(" -- Sub Error Code %d\r\n"), SubErrorCode);
printf_P(PSTR(" -- In State %d\r\n"), USB_HostState);
} }
/** /**

File diff suppressed because one or more lines are too long

@ -11,6 +11,8 @@
* - Fixed bug in RNDISEthernet and DualCDC demos not using the correct USB_ControlRequest structure for control request data * - Fixed bug in RNDISEthernet and DualCDC demos not using the correct USB_ControlRequest structure for control request data
* - Fixed documentation showing incorrect USB mode support on the supported AVRs list * - Fixed documentation showing incorrect USB mode support on the supported AVRs list
* - Fixed RNDISEthernet not working under Linux due to Linux requiring an "optional" request which was unhandled * - Fixed RNDISEthernet not working under Linux due to Linux requiring an "optional" request which was unhandled
* - Fixed Mouse and Keyboard device demos not acting in accordance with the HID specification for idle periods (thanks to Brian Dickman)
* - Removed support for endpoint/pipe non-control interrupts; these did not act in the way users expected, and had many subtle issues
* *
* *
* \section Sec_ChangeLog090510 Version 090510 * \section Sec_ChangeLog090510 Version 090510

@ -154,34 +154,6 @@
*/ */
#define ENDPOINT_INT_SETUP UEIENX, (1 << RXSTPE), UEINTX, (1 << RXSTPI) #define ENDPOINT_INT_SETUP UEIENX, (1 << RXSTPE), UEINTX, (1 << RXSTPI)
/** Interrupt definition for the endpoint IN interrupt (for INTERRUPT type endpoints). Should be
* used with the USB_INT_* macros located in USBInterrupt.h.
*
* This interrupt will fire if enabled on an INTERRUPT type endpoint if a the endpoint interrupt
* period has elapsed and the endpoint is ready for a new packet to be written to its FIFO buffer
* (if required).
*
* \note This interrupt must be enabled and cleared on *each* endpoint which requires it (after the
* endpoint is selected), and will fire the common endpoint interrupt vector.
*
* \see \ref ENDPOINT_PIPE_vect for more information on the common pipe and endpoint interrupt vector.
*/
#define ENDPOINT_INT_IN UEIENX, (1 << TXINE) , UEINTX, (1 << TXINI)
/** Interrupt definition for the endpoint OUT interrupt (for INTERRUPT type endpoints). Should be
* used with the USB_INT_* macros located in USBInterrupt.h.
*
* This interrupt will fire if enabled on an INTERRUPT type endpoint if a the endpoint interrupt
* period has elapsed and the endpoint is ready for a packet from the host to be read from its
* FIFO buffer (if received).
*
* \note This interrupt must be enabled and cleared on *each* endpoint which requires it (after the
* endpoint is selected), and will fire the common endpoint interrupt vector.
*
* \see \ref ENDPOINT_PIPE_vect for more information on the common pipe and endpoint interrupt vector.
*/
#define ENDPOINT_INT_OUT UEIENX, (1 << RXOUTE), UEINTX, (1 << RXOUTI)
/* Pseudo-Function Macros: */ /* Pseudo-Function Macros: */
#if defined(__DOXYGEN__) #if defined(__DOXYGEN__)
/** Indicates the number of bytes currently stored in the current endpoint's selected bank. /** Indicates the number of bytes currently stored in the current endpoint's selected bank.
@ -265,13 +237,6 @@
*/ */
static inline uint8_t Endpoint_GetEndpointInterrupts(void); static inline uint8_t Endpoint_GetEndpointInterrupts(void);
/** Clears the endpoint interrupt flag. This clears the specified endpoint number's interrupt
* mask in the endpoint interrupt flag register.
*
* \param EndpointNumber Index of the endpoint whose interrupt flag should be cleared
*/
static inline void Endpoint_ClearEndpointInterrupt(uint8_t EndpointNumber);
/** Determines if the specified endpoint number has interrupted (valid only for INTERRUPT type /** Determines if the specified endpoint number has interrupted (valid only for INTERRUPT type
* endpoints). * endpoints).
* *
@ -398,8 +363,6 @@
#define Endpoint_GetEndpointInterrupts() UEINT #define Endpoint_GetEndpointInterrupts() UEINT
#define Endpoint_ClearEndpointInterrupt(n) MACROS{ UEINT &= ~(1 << n); }MACROE
#define Endpoint_HasEndpointInterrupted(n) ((UEINT & (1 << n)) ? true : false) #define Endpoint_HasEndpointInterrupted(n) ((UEINT & (1 << n)) ? true : false)
#define Endpoint_IsINReady() ((UEINTX & (1 << TXINI)) ? true : false) #define Endpoint_IsINReady() ((UEINTX & (1 << TXINI)) ? true : false)

@ -158,34 +158,6 @@
*/ */
#define PIPE_EPSIZE_MASK 0x7FF #define PIPE_EPSIZE_MASK 0x7FF
/** Interrupt definition for the pipe IN interrupt (for INTERRUPT type pipes). Should be used with
* the USB_INT_* macros located in USBInterrupt.h.
*
* This interrupt will fire if enabled on an INTERRUPT type pipe if the pipe interrupt period has
* elapsed and the pipe is ready for the next packet from the attached device to be read out from its
* FIFO buffer (if received).
*
* \note This interrupt must be enabled and cleared on *each* pipe which requires it (after the pipe
* is selected), and will fire the common pipe interrupt vector.
*
* \see \ref ENDPOINT_PIPE_vect for more information on the common pipe and endpoint interrupt vector.
*/
#define PIPE_INT_IN UPIENX, (1 << RXINE) , UPINTX, (1 << RXINI)
/** Interrupt definition for the pipe OUT interrupt (for INTERRUPT type pipes). Should be used with
* the USB_INT_* macros located in USBInterrupt.h.
*
* This interrupt will fire if enabled on an INTERRUPT type endpoint if a the pipe interrupt period
* has elapsed and the pipe is ready for a packet to be written to the pipe's FIFO buffer and sent
* to the attached device (if required).
*
* \note This interrupt must be enabled and cleared on *each* pipe which requires it (after the pipe
* is selected), and will fire the common pipe interrupt vector.
*
* \see \ref ENDPOINT_PIPE_vect for more information on the common pipe and endpoint interrupt vector.
*/
#define PIPE_INT_OUT UPIENX, (1 << TXOUTE), UPINTX, (1 << TXOUTI)
/** Interrupt definition for the pipe SETUP bank ready interrupt (for CONTROL type pipes). Should be /** Interrupt definition for the pipe SETUP bank ready interrupt (for CONTROL type pipes). Should be
* used with the USB_INT_* macros located in USBInterrupt.h. * used with the USB_INT_* macros located in USBInterrupt.h.
* *
@ -337,12 +309,6 @@
*/ */
static inline uint8_t Pipe_GetPipeInterrupts(void); static inline uint8_t Pipe_GetPipeInterrupts(void);
/** Clears the interrupt flag for the specified pipe number.
*
* \param PipeNumber Index of the pipe whose interrupt flag is to be cleared
*/
static inline void Pipe_ClearPipeInterrupt(uint8_t PipeNumber);
/** Determines if the specified pipe number has interrupted (valid only for INTERRUPT type /** Determines if the specified pipe number has interrupted (valid only for INTERRUPT type
* pipes). * pipes).
* *
@ -504,8 +470,6 @@
#define Pipe_GetPipeInterrupts() UPINT #define Pipe_GetPipeInterrupts() UPINT
#define Pipe_ClearPipeInterrupt(n) MACROS{ UPINT &= ~(1 << n); }MACROE
#define Pipe_HasPipeInterrupted(n) ((UPINT & (1 << n)) ? true : false) #define Pipe_HasPipeInterrupted(n) ((UPINT & (1 << n)) ? true : false)
#define Pipe_Unfreeze() MACROS{ UPCONX &= ~(1 << PFREEZE); }MACROE #define Pipe_Unfreeze() MACROS{ UPCONX &= ~(1 << PFREEZE); }MACROE

@ -12,6 +12,16 @@
* *
* \section Sec_MigrationXXXXXX Migrating from 090510 to XXXXXX * \section Sec_MigrationXXXXXX Migrating from 090510 to XXXXXX
* *
* <b>Device Mode</b>
* - Support for non-control data endpoint interrupts has been dropped due to many issues in the implementation. All existing
* projects using interrupts on non-control endpoints should switch to polling.
* - The Endpoint_ClearEndpointInterrupt() macro has been deleted and references to it should be removed.
*
* <b>Device Mode</b>
* - Support for non-control data pipe interrupts has been dropped due to many issues in the implementation. All existing
* projects using interrupts on non-control pipes should switch to polling.
* - The Pipe_ClearPipeInterrupt() macro has been deleted and references to it should be removed.
*
* *
* \section Sec_Migration090510 Migrating from 090401 to 090510 * \section Sec_Migration090510 Migrating from 090401 to 090510
* *

Loading…
Cancel
Save