📄 keyboard.c
字号:
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;
}
}
/** 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)
{
/* 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. */
static inline 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 if the idle period is set */
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);
}
}
/* Save the current report data for later comparison to check for changes */
PrevKeyboardReportData = KeyboardReportData;
/* Select the Keyboard Report Endpoint */
Endpoint_SelectEndpoint(KEYBOARD_EPNUM);
/* Check if Keyboard Endpoint Ready for Read/Write, and if we should send a 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. */
static inline 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();
}
}
/** 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)
{
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);
}
#if !defined(INTERRUPT_DATA_ENDPOINT)
/** Function to manage HID report generation and transmission to the host, when in report mode. */
TASK(USB_Keyboard_Report)
{
/* 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();
}
}
#endif
/** 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
* HID packets to the host each time the HID interrupt endpoints polling period elapses, as managed by the USB
* controller. It is also used to respond to standard and class specific requests send to the device on the control
* endpoint, by handing them off to the LUFA library when they are received.
*/
ISR(ENDPOINT_PIPE_vect, ISR_BLOCK)
{
#if defined(INTERRUPT_CONTROL_ENDPOINT)
/* Check if the control endpoint has received a request */
if (Endpoint_HasEndpointInterrupted(ENDPOINT_CONTROLEP))
{
/* Clear the endpoint interrupt */
Endpoint_ClearEndpointInterrupt(ENDPOINT_CONTROLEP);
/* Process the control request */
USB_USBTask();
/* Handshake the endpoint setup interrupt - must be after the call to USB_USBTask() */
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 */
Endpoint_ClearEndpointInterrupt(KEYBOARD_LEDS_EPNUM);
/* Process the LED report sent from the host */
ReceiveNextReport();
}
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -