diff --git a/Downstream/Inc/downstream_hid.h b/Downstream/Inc/downstream_hid.h index 640f9b6..2a7bc6e 100644 --- a/Downstream/Inc/downstream_hid.h +++ b/Downstream/Inc/downstream_hid.h @@ -42,10 +42,12 @@ #define HID_ITEM_INPUT_REL 0x06 +typedef void (*TransactionCompleteCallbackTypeDef)(void); InterfaceCommandClassTypeDef Downstream_HID_ApproveConnectedDevice(void); void Downstream_HID_PacketProcessor(DownstreamPacketTypeDef* receivedPacket); -void Downstream_HID_InterruptReportCallback(DownstreamPacketTypeDef* packetToSend); +void Downstream_HID_InterruptReportCallback(void); +void Downstream_HID_SendReportCallback(void); diff --git a/Downstream/Inc/downstream_interface_def.h b/Downstream/Inc/downstream_interface_def.h index bf815ab..dd6b538 100644 --- a/Downstream/Inc/downstream_interface_def.h +++ b/Downstream/Inc/downstream_interface_def.h @@ -58,7 +58,7 @@ InterfaceCommandMscTypeDef; typedef enum { COMMAND_HID_GET_REPORT, //Returns HID report from device - COMMAND_HID_SET_REPORT //Sends HID report to device. No reply or ack expected. + COMMAND_HID_SET_REPORT //Sends HID report to device. Simple ack packet contains no data. } InterfaceCommandHidTypeDef; diff --git a/Downstream/Inc/downstream_spi.h b/Downstream/Inc/downstream_spi.h index f8941a1..6f59a6f 100644 --- a/Downstream/Inc/downstream_spi.h +++ b/Downstream/Inc/downstream_spi.h @@ -71,6 +71,7 @@ typedef void (*SpiPacketReceivedCallbackTypeDef)(DownstreamPacketTypeDef* receiv void Downstream_InitSPI(void); HAL_StatusTypeDef Downstream_GetFreePacket(FreePacketCallbackTypeDef callback); +DownstreamPacketTypeDef* Downstream_GetFreePacketImmediately(void); void Downstream_ReleasePacket(DownstreamPacketTypeDef* packetToRelease); HAL_StatusTypeDef Downstream_ReceivePacket(SpiPacketReceivedCallbackTypeDef callback); HAL_StatusTypeDef Downstream_TransmitPacket(DownstreamPacketTypeDef* packetToWrite); diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid.h b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid.h index 96e123f..e8acdd4 100644 --- a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid.h +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid.h @@ -23,6 +23,9 @@ * limitations under the License. * ****************************************************************************** + * + * Modifications by Robert Fisk + * */ /* Define to prevent recursive ----------------------------------------------*/ @@ -35,7 +38,7 @@ /* Includes ------------------------------------------------------------------*/ #include "usbh_core.h" -#include "downstream_spi.h" +#include "downstream_hid.h" /** @addtogroup USBH_LIB @@ -105,6 +108,10 @@ #define HID_LOCAL_ITEM_TAG_STRING_MIN 0x08 #define HID_LOCAL_ITEM_TAG_STRING_MAX 0x09 #define HID_LOCAL_ITEM_TAG_DELIMITER 0x0A + + +#define HID_REPORT_DIRECTION_IN 0x01 +#define HID_REPORT_DIRECTION_OUT 0x02 /* States for HID State Machine */ @@ -114,8 +121,7 @@ typedef enum HID_IDLE, HID_GET_DATA, HID_GET_POLL, - HID_SET_DATA, - HID_SET_POLL, + HID_SET_DATA_POLL, HID_ERROR, } HID_StateTypeDef; @@ -227,7 +233,7 @@ typedef struct _HID_Process uint8_t ep_addr; uint8_t Protocol; HID_DescTypeDef HID_Desc; - FreePacketCallbackTypeDef ReportCallback; + TransactionCompleteCallbackTypeDef ReportCallback; uint8_t Data[HID_MAX_REPORT_SIZE]; } HID_HandleTypeDef; @@ -288,7 +294,8 @@ USBH_StatusTypeDef USBH_HID_SetReport (USBH_HandleTypeDef *phost, uint8_t reportType, uint8_t reportId, uint8_t* reportBuff, - uint8_t reportLen); + uint8_t reportLen, + TransactionCompleteCallbackTypeDef callback); USBH_StatusTypeDef USBH_HID_GetReport (USBH_HandleTypeDef *phost, uint8_t reportType, @@ -322,7 +329,7 @@ uint16_t fifo_read(FIFO_TypeDef * f, void * buf, uint16_t nbytes); uint16_t fifo_write(FIFO_TypeDef * f, const void * buf, uint16_t nbytes); HAL_StatusTypeDef USBH_HID_GetInterruptReport(USBH_HandleTypeDef *phost, - FreePacketCallbackTypeDef callback); + TransactionCompleteCallbackTypeDef callback); /** diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid.c b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid.c index c0416b9..49d9188 100644 --- a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid.c +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid.c @@ -373,17 +373,17 @@ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost) HID_Handle->Data, HID_Handle->length, HID_Handle->InPipe); - HID_Handle->state = HID_GET_POLL; HID_Handle->timer = phost->Timer; } break; + case HID_GET_POLL: urbStatus = USBH_LL_GetURBState(phost, HID_Handle->InPipe); if (urbStatus == USBH_URB_DONE) { - Downstream_GetFreePacket(HID_Handle->ReportCallback); + HID_Handle->ReportCallback(); HID_Handle->state = HID_IDLE; break; } @@ -405,15 +405,14 @@ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost) } break; - case HID_SET_DATA: - - break; - - case HID_SET_POLL: - + case HID_SET_DATA_POLL: + if (USBH_CtlReq(phost, HID_Handle->Data, phost->Control.setup.b.wLength.w) == USBH_OK) + { + HID_Handle->ReportCallback(); + HID_Handle->state = HID_IDLE; + } break; - case HID_IDLE: break; @@ -441,7 +440,7 @@ static USBH_StatusTypeDef USBH_HID_SOFProcess(USBH_HandleTypeDef *phost) //Downstream_HID calls into here at main() priority, //to request a new report for Upstream. HAL_StatusTypeDef USBH_HID_GetInterruptReport(USBH_HandleTypeDef *phost, - FreePacketCallbackTypeDef callback) + TransactionCompleteCallbackTypeDef callback) { HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData; @@ -452,7 +451,8 @@ HAL_StatusTypeDef USBH_HID_GetInterruptReport(USBH_HandleTypeDef *phost, return HAL_OK; } - return HAL_ERROR; + //return HAL_ERROR; + while (1); } @@ -533,16 +533,18 @@ USBH_StatusTypeDef USBH_HID_SetIdle (USBH_HandleTypeDef *phost, uint8_t duration, uint8_t reportId) { - - phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\ - USB_REQ_TYPE_CLASS; - - - phost->Control.setup.b.bRequest = USB_HID_SET_IDLE; - phost->Control.setup.b.wValue.w = (duration << 8 ) | reportId; - - phost->Control.setup.b.wIndex.w = 0; - phost->Control.setup.b.wLength.w = 0; + if (phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_H2D | + USB_REQ_RECIPIENT_INTERFACE | + USB_REQ_TYPE_CLASS; + + phost->Control.setup.b.bRequest = USB_HID_SET_IDLE; + phost->Control.setup.b.wValue.w = (duration << 8 ) | reportId; + + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = 0; + } return USBH_CtlReq(phost, 0 , 0 ); } @@ -562,20 +564,41 @@ USBH_StatusTypeDef USBH_HID_SetReport (USBH_HandleTypeDef *phost, uint8_t reportType, uint8_t reportId, uint8_t* reportBuff, - uint8_t reportLen) + uint8_t reportLen, + TransactionCompleteCallbackTypeDef callback) { + HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData; + uint32_t i; + + if (phost->RequestState == CMD_SEND) + { + if ((HID_Handle->state != HID_IDLE) || + (reportLen > HID_MAX_REPORT_SIZE)) + { + while (1); + } + + HID_Handle->ReportCallback = callback; + HID_Handle->state = HID_SET_DATA_POLL; + for (i = 0; i < reportLen; i++) + { + HID_Handle->Data[i] = *reportBuff; + reportBuff++; + } + + phost->Control.setup.b.bmRequestType = USB_H2D | + USB_REQ_RECIPIENT_INTERFACE | + USB_REQ_TYPE_CLASS; + + phost->Control.setup.b.bRequest = USB_HID_SET_REPORT; + phost->Control.setup.b.wValue.w = (reportType << 8 ) | reportId; + + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = reportLen; + } - phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\ - USB_REQ_TYPE_CLASS; - - - phost->Control.setup.b.bRequest = USB_HID_SET_REPORT; - phost->Control.setup.b.wValue.w = (reportType << 8 ) | reportId; - - phost->Control.setup.b.wIndex.w = 0; - phost->Control.setup.b.wLength.w = reportLen; - - return USBH_CtlReq(phost, reportBuff , reportLen ); + //return USBH_CtlReq(phost, reportBuff, reportLen); + return USBH_OK; } @@ -595,17 +618,19 @@ USBH_StatusTypeDef USBH_HID_GetReport (USBH_HandleTypeDef *phost, uint8_t* reportBuff, uint8_t reportLen) { - - phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_RECIPIENT_INTERFACE |\ - USB_REQ_TYPE_CLASS; - - - phost->Control.setup.b.bRequest = USB_HID_GET_REPORT; - phost->Control.setup.b.wValue.w = (reportType << 8 ) | reportId; - - phost->Control.setup.b.wIndex.w = 0; - phost->Control.setup.b.wLength.w = reportLen; - + if (phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_D2H | + USB_REQ_RECIPIENT_INTERFACE | + USB_REQ_TYPE_CLASS; + + phost->Control.setup.b.bRequest = USB_HID_GET_REPORT; + phost->Control.setup.b.wValue.w = (reportType << 8 ) | reportId; + + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = reportLen; + } + return USBH_CtlReq(phost, reportBuff , reportLen ); } @@ -619,16 +644,17 @@ USBH_StatusTypeDef USBH_HID_GetReport (USBH_HandleTypeDef *phost, USBH_StatusTypeDef USBH_HID_SetProtocol(USBH_HandleTypeDef *phost, uint8_t protocol) { - - - phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\ - USB_REQ_TYPE_CLASS; - - - phost->Control.setup.b.bRequest = USB_HID_SET_PROTOCOL; - phost->Control.setup.b.wValue.w = protocol == 0 ? 0 : 1; - phost->Control.setup.b.wIndex.w = 0; - phost->Control.setup.b.wLength.w = 0; + if (phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_H2D | + USB_REQ_RECIPIENT_INTERFACE |\ + USB_REQ_TYPE_CLASS; + + phost->Control.setup.b.bRequest = USB_HID_SET_PROTOCOL; + phost->Control.setup.b.wValue.w = protocol == 0 ? 0 : 1; + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = 0; + } return USBH_CtlReq(phost, 0 , 0 ); diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_bot.c b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_bot.c index b96563f..32b68af 100644 --- a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_bot.c +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_bot.c @@ -58,14 +58,17 @@ USBH_HandleTypeDef *Callback_MSC_phost; */ USBH_StatusTypeDef USBH_MSC_BOT_REQ_Reset(USBH_HandleTypeDef *phost) { - - phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_TYPE_CLASS | \ - USB_REQ_RECIPIENT_INTERFACE; - - phost->Control.setup.b.bRequest = USB_REQ_BOT_RESET; - phost->Control.setup.b.wValue.w = 0; - phost->Control.setup.b.wIndex.w = 0; - phost->Control.setup.b.wLength.w = 0; + if (phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_H2D | + USB_REQ_TYPE_CLASS | + USB_REQ_RECIPIENT_INTERFACE; + + phost->Control.setup.b.bRequest = USB_REQ_BOT_RESET; + phost->Control.setup.b.wValue.w = 0; + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = 0; + } return USBH_CtlReq(phost, 0 , 0 ); } @@ -79,13 +82,17 @@ USBH_StatusTypeDef USBH_MSC_BOT_REQ_Reset(USBH_HandleTypeDef *phost) */ USBH_StatusTypeDef USBH_MSC_BOT_REQ_GetMaxLUN(USBH_HandleTypeDef *phost, uint8_t *Maxlun) { - phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_TYPE_CLASS | \ - USB_REQ_RECIPIENT_INTERFACE; - - phost->Control.setup.b.bRequest = USB_REQ_GET_MAX_LUN; - phost->Control.setup.b.wValue.w = 0; - phost->Control.setup.b.wIndex.w = 0; - phost->Control.setup.b.wLength.w = 1; + if (phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_D2H | + USB_REQ_TYPE_CLASS | + USB_REQ_RECIPIENT_INTERFACE; + + phost->Control.setup.b.bRequest = USB_REQ_GET_MAX_LUN; + phost->Control.setup.b.wValue.w = 0; + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = 1; + } return USBH_CtlReq(phost, Maxlun , 1 ); } diff --git a/Downstream/Src/downstream_hid.c b/Downstream/Src/downstream_hid.c index 7d25095..0484ed2 100644 --- a/Downstream/Src/downstream_hid.c +++ b/Downstream/Src/downstream_hid.c @@ -56,6 +56,7 @@ uint8_t ItemData; static HAL_StatusTypeDef Downstream_HID_Mouse_ParseReportDescriptor(void); static HAL_StatusTypeDef Downstream_HID_GetNextReportItem(void); static void Downstream_HID_Mouse_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend); +static void Downstream_HID_Keyboard_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend); static uint8_t Downstream_HID_Mouse_Extract8BitValue(HID_HandleTypeDef* hidHandle, uint8_t valueBitOffset, uint8_t valueBitLength); @@ -84,7 +85,7 @@ InterfaceCommandClassTypeDef Downstream_HID_ApproveConnectedDevice(void) -HAL_StatusTypeDef Downstream_HID_Mouse_ParseReportDescriptor(void) +static HAL_StatusTypeDef Downstream_HID_Mouse_ParseReportDescriptor(void) { uint32_t currentReportBitIndex = 0; uint8_t currentUsagePage = 0; @@ -242,7 +243,7 @@ HAL_StatusTypeDef Downstream_HID_Mouse_ParseReportDescriptor(void) //Retrieves the next item in the HID report, and at most one of its associated data bytes. //Then it updates ReportDataPointer based on the actual length of the retrieved item. -HAL_StatusTypeDef Downstream_HID_GetNextReportItem(void) +static HAL_StatusTypeDef Downstream_HID_GetNextReportItem(void) { HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; uint32_t itemLength; @@ -287,9 +288,22 @@ void Downstream_HID_PacketProcessor(DownstreamPacketTypeDef* receivedPacket) Downstream_PacketProcessor_NotifyDisconnectReplyRequired(); } - if (receivedPacket->Command == COMMAND_HID_SET_REPORT) + else if (receivedPacket->Command == COMMAND_HID_SET_REPORT) { - + if ((ConfiguredDeviceClass != COMMAND_CLASS_HID_KEYBOARD) || + (receivedPacket->Length16 != ((HID_KEYBOARD_OUTPUT_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16) || + ((receivedPacket->Data[0] & ~((1 << HID_KEYBOARD_MAX_LED) - 1)) != 0)) + { + Downstream_PacketProcessor_FreakOut(); + } + USBH_HID_SetReport(&hUsbHostFS, + HID_REPORT_DIRECTION_OUT, + 0, + receivedPacket->Data, + HID_KEYBOARD_OUTPUT_DATA_LEN, + Downstream_HID_SendReportCallback); + Downstream_ReleasePacket(receivedPacket); + Downstream_PacketProcessor_NotifyDisconnectReplyRequired(); } //else: @@ -297,17 +311,20 @@ void Downstream_HID_PacketProcessor(DownstreamPacketTypeDef* receivedPacket) } -void Downstream_HID_InterruptReportCallback(DownstreamPacketTypeDef* packetToSend) +void Downstream_HID_InterruptReportCallback(void) { + DownstreamPacketTypeDef* freePacket; + + freePacket = Downstream_GetFreePacketImmediately(); if (ConfiguredDeviceClass == COMMAND_CLASS_HID_MOUSE) { - Downstream_HID_Mouse_ExtractDataFromReport(packetToSend); - packetToSend->Length16 = ((HID_MOUSE_INPUT_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16; + Downstream_HID_Mouse_ExtractDataFromReport(freePacket); + freePacket->Length16 = ((HID_MOUSE_INPUT_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16; } else if (ConfiguredDeviceClass == COMMAND_CLASS_HID_KEYBOARD) { - Downstream_HID_Keyboard_ExtractDataFromReport(packetToSend); - packetToSend->Length16 = ((HID_KEYBOARD_INPUT_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16; + Downstream_HID_Keyboard_ExtractDataFromReport(freePacket); + freePacket->Length16 = ((HID_KEYBOARD_INPUT_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16; } //else if... @@ -317,13 +334,13 @@ void Downstream_HID_InterruptReportCallback(DownstreamPacketTypeDef* packetToSen return; } - packetToSend->CommandClass = ConfiguredDeviceClass; - packetToSend->Command = COMMAND_HID_GET_REPORT; - Downstream_PacketProcessor_ClassReply(packetToSend); + freePacket->CommandClass = ConfiguredDeviceClass; + freePacket->Command = COMMAND_HID_GET_REPORT; + Downstream_PacketProcessor_ClassReply(freePacket); } -void Downstream_HID_Mouse_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend) +static void Downstream_HID_Mouse_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend) { HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; uint32_t readData; @@ -348,9 +365,9 @@ void Downstream_HID_Mouse_ExtractDataFromReport(DownstreamPacketTypeDef* packetT -uint8_t Downstream_HID_Mouse_Extract8BitValue(HID_HandleTypeDef* hidHandle, - uint8_t valueBitOffset, - uint8_t valueBitLength) +static uint8_t Downstream_HID_Mouse_Extract8BitValue(HID_HandleTypeDef* hidHandle, + uint8_t valueBitOffset, + uint8_t valueBitLength) { int32_t readData; @@ -371,7 +388,7 @@ uint8_t Downstream_HID_Mouse_Extract8BitValue(HID_HandleTypeDef* hidHandle, -void Downstream_HID_Keyboard_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend) +static void Downstream_HID_Keyboard_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend) { HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; uint32_t i; @@ -392,3 +409,14 @@ void Downstream_HID_Keyboard_ExtractDataFromReport(DownstreamPacketTypeDef* pack } + +void Downstream_HID_SendReportCallback(void) +{ + DownstreamPacketTypeDef* freePacket; + + freePacket = Downstream_GetFreePacketImmediately(); + freePacket->CommandClass = ConfiguredDeviceClass; + freePacket->Command = COMMAND_HID_SET_REPORT; + Downstream_PacketProcessor_ClassReply(freePacket); +} + diff --git a/Downstream/Src/downstream_spi.c b/Downstream/Src/downstream_spi.c index 2c08354..575ecd7 100644 --- a/Downstream/Src/downstream_spi.c +++ b/Downstream/Src/downstream_spi.c @@ -92,6 +92,33 @@ HAL_StatusTypeDef Downstream_GetFreePacket(FreePacketCallbackTypeDef callback) } + +DownstreamPacketTypeDef* Downstream_GetFreePacketImmediately(void) +{ + if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR) + { + return NULL; + } + + //We are expecting a free buffer now + if (DownstreamPacket0.Busy == NOT_BUSY) + { + DownstreamPacket0.Busy = BUSY; + return &DownstreamPacket0; + } + if (DownstreamPacket1.Busy == NOT_BUSY) + { + DownstreamPacket1.Busy = BUSY; + return &DownstreamPacket1; + } + + //Should not happen: + DOWNSTREAM_SPI_FREAKOUT; + return NULL; +} + + + //Used by Downstream state machine and USB host classes. void Downstream_ReleasePacket(DownstreamPacketTypeDef* packetToRelease) { diff --git a/Downstream/Src/downstream_statemachine.c b/Downstream/Src/downstream_statemachine.c index ae09dee..6ede375 100644 --- a/Downstream/Src/downstream_statemachine.c +++ b/Downstream/Src/downstream_statemachine.c @@ -10,7 +10,6 @@ */ -#include #include "downstream_statemachine.h" #include "downstream_interface_def.h" #include "downstream_spi.h" diff --git a/Upstream/Inc/upstream_hid.h b/Upstream/Inc/upstream_hid.h index 78ef333..7d7f3f3 100644 --- a/Upstream/Inc/upstream_hid.h +++ b/Upstream/Inc/upstream_hid.h @@ -29,10 +29,16 @@ #define HID_KEYBOARD_MAX_LED 3 -typedef uint8_t (*UpstreamHidGetReportCallback)(uint8_t *report, - uint16_t len); +typedef enum +{ + KEYBOARD_OUT_STATE_IDLE, + KEYBOARD_OUT_STATE_DATA_READY, + KEYBOARD_OUT_STATE_BUSY +} KeyboardOutStateTypeDef; +typedef uint8_t (*UpstreamHidGetReportCallback)(uint8_t *report, + uint16_t len); void Upstream_HID_DeInit(void); void Upstream_HID_GetNextInterruptReport(UpstreamHidGetReportCallback callback); diff --git a/Upstream/Inc/upstream_interface_def.h b/Upstream/Inc/upstream_interface_def.h index 3bb78b7..f4d0a23 100644 --- a/Upstream/Inc/upstream_interface_def.h +++ b/Upstream/Inc/upstream_interface_def.h @@ -60,7 +60,7 @@ InterfaceCommandMscTypeDef; typedef enum { COMMAND_HID_GET_REPORT, //Returns HID report from device - COMMAND_HID_SET_REPORT //Sends HID report to device. No reply or ack expected. + COMMAND_HID_SET_REPORT //Sends HID report to device. Simple ack packet contains no data. } InterfaceCommandHidTypeDef; diff --git a/Upstream/Src/upstream_hid.c b/Upstream/Src/upstream_hid.c index a029524..ac89ff5 100644 --- a/Upstream/Src/upstream_hid.c +++ b/Upstream/Src/upstream_hid.c @@ -19,8 +19,8 @@ UpstreamPacketTypeDef* UpstreamHidPacket = NULL; UpstreamHidGetReportCallback GetReportCallback = NULL; -uint8_t KeyboardOutDataAvailable = 0; -uint8_t KeyboardOutData[HID_KEYBOARD_OUTPUT_DATA_LEN]; +KeyboardOutStateTypeDef KeyboardOutDataState = KEYBOARD_OUT_STATE_IDLE; +uint8_t KeyboardOutData[HID_KEYBOARD_OUTPUT_DATA_LEN]; @@ -36,7 +36,7 @@ void Upstream_HID_DeInit(void) UpstreamHidPacket = NULL; } GetReportCallback = NULL; - KeyboardOutDataAvailable = 0; + KeyboardOutDataState = KEYBOARD_OUT_STATE_IDLE; } @@ -54,11 +54,31 @@ void Upstream_HID_GetNextInterruptReport(UpstreamHidGetReportCallback callback) return; } - //Just return if we already have an outstanding request - if (GetReportCallback != NULL) + if (callback != NULL) { - return; + //This means we were called by the host (normal operation) + if (KeyboardOutDataState == KEYBOARD_OUT_STATE_BUSY) + { + //Just save the callback, because we are still waiting for the OUT report to complete + GetReportCallback = callback; + return; + } + if (GetReportCallback != NULL) + { + //Just return if we already have an outstanding request + return; + } + } + else + { + //This means were called on OUT report completion + if (GetReportCallback == NULL) + { + //The host has not given us the callback yet, so we give up + return; + } } + GetReportCallback = callback; //Release packet used for last transaction (if any) @@ -175,7 +195,7 @@ void Upstream_HID_GetNextInterruptReportReceiveCallback(UpstreamPacketTypeDef* r //Check if we need to send OUT data to the keyboard before requesting next Interrupt IN data - if (KeyboardOutDataAvailable) + if (KeyboardOutDataState == KEYBOARD_OUT_STATE_DATA_READY) { Upstream_HID_ReallySendControlReport(); } @@ -203,7 +223,7 @@ void Upstream_HID_SendControlReport(UpstreamPacketTypeDef* packetToSend, uint8_t } //Save data until after the next interrupt data is received from Downstream - KeyboardOutDataAvailable = 1; + KeyboardOutDataState = KEYBOARD_OUT_STATE_DATA_READY; for (i = 0; i < HID_KEYBOARD_OUTPUT_DATA_LEN; i++) { KeyboardOutData[i] = packetToSend->Data[i]; @@ -217,7 +237,7 @@ void Upstream_HID_ReallySendControlReport(void) UpstreamPacketTypeDef* freePacket; uint32_t i; - KeyboardOutDataAvailable = 0; + KeyboardOutDataState = KEYBOARD_OUT_STATE_BUSY; freePacket = Upstream_GetFreePacketImmediately(); if (freePacket == NULL) return; @@ -232,10 +252,39 @@ void Upstream_HID_ReallySendControlReport(void) } freePacket->Data[0] &= ((1 << HID_KEYBOARD_MAX_LED) - 1); - if (Upstream_TransmitPacket(freePacket) != HAL_OK) + if (Upstream_TransmitPacket(freePacket) == HAL_OK) + { + Upstream_ReceivePacket(Upstream_HID_GetNextInterruptReportReceiveCallback); + } + else { Upstream_ReleasePacket(freePacket); } } + +void Upstream_HID_ReallySendControlReportReceiveCallback(UpstreamPacketTypeDef* receivedPacket) +{ + InterfaceCommandClassTypeDef activeClass; + + activeClass = Upstream_StateMachine_CheckActiveClass(); + if (activeClass != COMMAND_CLASS_HID_KEYBOARD) //add classes here + { + UPSTREAM_STATEMACHINE_FREAKOUT; + return; + } + + if (receivedPacket == NULL) + { + return; //Just give up... + } + + Upstream_ReleasePacket(receivedPacket); + KeyboardOutDataState = KEYBOARD_OUT_STATE_IDLE; + + //If upstream host has already requested the next IN report data, + //this will send the request downstream. + Upstream_HID_GetNextInterruptReport(NULL); +} +