/** Writes a report to the attached device. * * \param[in] ReportOUTData Buffer containing the report to send to the device * \param[in] ReportIndex Index of the report in the device (zero if the device does not use multiple reports) * \param[in] ReportType Type of report to send, either REPORT_TYPE_OUT or REPORT_TYPE_FEATURE * \param[in] ReportLength Length of the report to send */ void WriteNextReport(uint8_t* ReportOUTData, const uint8_t ReportIndex, const uint8_t ReportType, uint16_t ReportLength) { /* Select the HID data OUT pipe */ Pipe_SelectPipe(HID_DATA_OUT_PIPE); /* Not all HID devices have an OUT endpoint (some require OUT reports to be sent over the * control endpoint instead) - check to see if the OUT endpoint has been initialized */ if (Pipe_IsConfigured() && (ReportType == REPORT_TYPE_OUT)) { Pipe_Unfreeze(); /* Ensure pipe is ready to be written to before continuing */ if (!(Pipe_IsOUTReady())) { /* Refreeze the data OUT pipe */ Pipe_Freeze(); return; } /* If the report index is used, send it before the report data */ if (ReportIndex) Pipe_Write_Byte(ReportIndex); /* Write out HID report data */ Pipe_Write_Stream_LE(ReportOUTData, ReportLength); /* Clear the OUT endpoint, send last data packet */ Pipe_ClearOUT(); /* Refreeze the data OUT pipe */ Pipe_Freeze(); } else { /* Class specific request to send a HID report to the device */ USB_ControlRequest = (USB_Request_Header_t) { .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE), .bRequest = HID_REQ_SetReport, .wValue = ((ReportType << 8) | ReportIndex), .wIndex = 0, .wLength = ReportLength, }; /* Select the control pipe for the request transfer */ Pipe_SelectPipe(PIPE_CONTROLPIPE); /* Send the request to the device */ USB_Host_SendControlRequest(ReportOUTData); } } /** Task to set the configuration of the attached device after it has been enumerated, and to read and process * HID reports from the device and to send reports if desired. */ void HID_Host_Task(void) { uint8_t ErrorCode; /* Switch to determine what user-application handled host state the host state machine is in */ switch (USB_HostState) { case HOST_STATE_Addressed: puts_P(PSTR("Getting Config Data.\r\n")); /* Get and process the configuration descriptor data */ if ((ErrorCode = ProcessConfigurationDescriptor()) != SuccessfulConfigRead) { if (ErrorCode == ControlError) puts_P(PSTR(ESC_FG_RED "Control Error (Get Configuration).\r\n")); else puts_P(PSTR(ESC_FG_RED "Invalid Device.\r\n")); printf_P(PSTR(" -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); /* Indicate error status */ LEDs_SetAllLEDs(LEDMASK_USB_ERROR); /* Wait until USB device disconnected */ USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } /* Set the device configuration to the first configuration (rarely do devices use multiple configurations) */ if ((ErrorCode = USB_Host_SetDeviceConfiguration(1)) != HOST_SENDCONTROL_Successful) { printf_P(PSTR(ESC_FG_RED "Control Error (Set Configuration).\r\n" " -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); /* Indicate error status */ LEDs_SetAllLEDs(LEDMASK_USB_ERROR); /* Wait until USB device disconnected */ USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } puts_P(PSTR("HID Device Enumerated.\r\n")); USB_HostState = HOST_STATE_Configured; break; case HOST_STATE_Configured: ReadNextReport(); break; } }
/** Task to set the configuration of the attached device after it has been enumerated, and to read and process * HID reports from the device and display the results onto the board LEDs. */ void Keyboard_HID_Task(void) { uint8_t ErrorCode; switch (USB_HostState) { case HOST_STATE_Addressed: puts_P(PSTR("Getting Config Data.\r\n")); /* Get and process the configuration descriptor data */ if ((ErrorCode = ProcessConfigurationDescriptor()) != SuccessfulConfigRead) { if (ErrorCode == ControlError) puts_P(PSTR(ESC_FG_RED "Control Error (Get Configuration).\r\n")); else puts_P(PSTR(ESC_FG_RED "Invalid Device.\r\n")); printf_P(PSTR(" -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); /* Indicate error status */ LEDs_SetAllLEDs(LEDMASK_USB_ERROR); /* Wait until USB device disconnected */ USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } /* Set the device configuration to the first configuration (rarely do devices use multiple configurations) */ if ((ErrorCode = USB_Host_SetDeviceConfiguration(1)) != HOST_SENDCONTROL_Successful) { printf_P(PSTR(ESC_FG_RED "Control Error (Set Configuration).\r\n" " -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); /* Indicate error status */ LEDs_SetAllLEDs(LEDMASK_USB_ERROR); /* Wait until USB device disconnected */ USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } /* HID class request to set the keyboard protocol to the Boot Protocol */ USB_ControlRequest = (USB_Request_Header_t) { .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE), .bRequest = REQ_SetProtocol, .wValue = 0, .wIndex = 0, .wLength = 0, }; /* Select the control pipe for the request transfer */ Pipe_SelectPipe(PIPE_CONTROLPIPE); /* Send the request, display error and wait for device detach if request fails */ if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful) { printf_P(PSTR(ESC_FG_RED "Control Error (Set Protocol).\r\n" " -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); /* Indicate error status */ LEDs_SetAllLEDs(LEDMASK_USB_ERROR); /* Wait until USB device disconnected */ USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } puts_P(PSTR("Keyboard Enumerated.\r\n")); USB_HostState = HOST_STATE_Configured; break; case HOST_STATE_Configured: /* If a report has been received, read and process it */ ReadNextReport(); break; } }