diff --git a/Downstream/Inc/downstream_interface_def.h b/Downstream/Inc/downstream_interface_def.h index 57ebfcf..bf815ab 100644 --- a/Downstream/Inc/downstream_interface_def.h +++ b/Downstream/Inc/downstream_interface_def.h @@ -57,7 +57,8 @@ InterfaceCommandMscTypeDef; typedef enum { - COMMAND_HID_REPORT, //Returns HID report + COMMAND_HID_GET_REPORT, //Returns HID report from device + COMMAND_HID_SET_REPORT //Sends HID report to device. No reply or ack expected. } InterfaceCommandHidTypeDef; 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 03767d3..96e123f 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 @@ -112,9 +112,10 @@ typedef enum { HID_INIT= 0, HID_IDLE, - HID_GET_DATA, - HID_SYNC, - HID_POLL, + HID_GET_DATA, + HID_GET_POLL, + HID_SET_DATA, + HID_SET_POLL, HID_ERROR, } HID_StateTypeDef; 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 848e89b..c0416b9 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 @@ -327,8 +327,10 @@ static USBH_StatusTypeDef USBH_HID_ClassRequest(USBH_HandleTypeDef *phost) break; case HID_REQ_SET_PROTOCOL: - /* set protocol */ - if (USBH_HID_SetProtocol (phost, 1) == USBH_OK) + //Mouse in 'report' mode, + //Keyboard in 'boot' mode + if (USBH_HID_SetProtocol(phost, + (HID_Handle->Protocol == HID_MOUSE_BOOT_CODE ? 1 : 0)) == USBH_OK) { HID_Handle->ctl_state = HID_REQ_IDLE; @@ -372,12 +374,11 @@ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost) HID_Handle->length, HID_Handle->InPipe); - HID_Handle->state = HID_POLL; + HID_Handle->state = HID_GET_POLL; HID_Handle->timer = phost->Timer; } break; - - case HID_POLL: + case HID_GET_POLL: urbStatus = USBH_LL_GetURBState(phost, HID_Handle->InPipe); if (urbStatus == USBH_URB_DONE) @@ -404,6 +405,15 @@ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost) } break; + case HID_SET_DATA: + + break; + + case HID_SET_POLL: + + break; + + case HID_IDLE: break; diff --git a/Downstream/Src/downstream_hid.c b/Downstream/Src/downstream_hid.c index cc20ec0..7d25095 100644 --- a/Downstream/Src/downstream_hid.c +++ b/Downstream/Src/downstream_hid.c @@ -18,11 +18,17 @@ -#define HID_MAX_REPORT_LEN 8 -#define HID_MOUSE_DATA_LEN 4 -#define HID_KEYBOARD_DATA_LEN 0 +#define HID_MAX_REPORT_LEN 8 -#define HID_MOUSE_MAX_BUTTONS 4 +//These defines are duplicated in downstream_hid.c. Keep them in sync! +#define HID_MOUSE_INPUT_DATA_LEN 4 +#define HID_MOUSE_OUTPUT_DATA_LEN 0 +#define HID_MOUSE_MAX_BUTTONS 3 + +#define HID_KEYBOARD_INPUT_DATA_LEN 8 +#define HID_KEYBOARD_OUTPUT_DATA_LEN 1 +#define HID_KEYBOARD_MAX_KEY 101 //Also set in Upstream's HID report descriptor +#define HID_KEYBOARD_MAX_LED 3 @@ -59,17 +65,21 @@ InterfaceCommandClassTypeDef Downstream_HID_ApproveConnectedDevice(void) { HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; - if (HID_Handle->Protocol != HID_MOUSE_BOOT_CODE) + if (HID_Handle->Protocol == HID_MOUSE_BOOT_CODE) { - return COMMAND_CLASS_INTERFACE; //fail + if (Downstream_HID_Mouse_ParseReportDescriptor() == HAL_OK) + { + return COMMAND_CLASS_HID_MOUSE; //success! + } } - if (Downstream_HID_Mouse_ParseReportDescriptor() != HAL_OK) + if (HID_Handle->Protocol == HID_KEYBRD_BOOT_CODE) { - return COMMAND_CLASS_INTERFACE; //fail + return COMMAND_CLASS_HID_KEYBOARD; //success! } - return COMMAND_CLASS_HID_MOUSE; //success! + //else: + return COMMAND_CLASS_INTERFACE; //fail } @@ -266,19 +276,24 @@ HAL_StatusTypeDef Downstream_HID_GetNextReportItem(void) void Downstream_HID_PacketProcessor(DownstreamPacketTypeDef* receivedPacket) { - if (receivedPacket->Command != COMMAND_HID_REPORT) + if (receivedPacket->Command == COMMAND_HID_GET_REPORT) { - Downstream_PacketProcessor_FreakOut(); - return; + Downstream_ReleasePacket(receivedPacket); + if (USBH_HID_GetInterruptReport(&hUsbHostFS, + Downstream_HID_InterruptReportCallback) != HAL_OK) + { + Downstream_PacketProcessor_FreakOut(); + } + Downstream_PacketProcessor_NotifyDisconnectReplyRequired(); } - Downstream_ReleasePacket(receivedPacket); - if (USBH_HID_GetInterruptReport(&hUsbHostFS, - Downstream_HID_InterruptReportCallback) != HAL_OK) + if (receivedPacket->Command == COMMAND_HID_SET_REPORT) { - Downstream_PacketProcessor_FreakOut(); + } - Downstream_PacketProcessor_NotifyDisconnectReplyRequired(); + + //else: + Downstream_PacketProcessor_FreakOut(); } @@ -287,9 +302,15 @@ void Downstream_HID_InterruptReportCallback(DownstreamPacketTypeDef* packetToSen if (ConfiguredDeviceClass == COMMAND_CLASS_HID_MOUSE) { Downstream_HID_Mouse_ExtractDataFromReport(packetToSend); - packetToSend->Length16 = ((HID_MOUSE_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16; + packetToSend->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; } //else if... + else { Downstream_PacketProcessor_FreakOut(); @@ -297,7 +318,7 @@ void Downstream_HID_InterruptReportCallback(DownstreamPacketTypeDef* packetToSen } packetToSend->CommandClass = ConfiguredDeviceClass; - packetToSend->Command = COMMAND_HID_REPORT; + packetToSend->Command = COMMAND_HID_GET_REPORT; Downstream_PacketProcessor_ClassReply(packetToSend); } @@ -348,3 +369,26 @@ uint8_t Downstream_HID_Mouse_Extract8BitValue(HID_HandleTypeDef* hidHandle, return (int8_t)readData; } + + +void Downstream_HID_Keyboard_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend) +{ + HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; + uint32_t i; + uint8_t readData; + + packetToSend->Data[0] = HID_Handle->Data[0]; //Modifier keys - pass straight through + packetToSend->Data[1] = 0; //Constant byte + + for (i = 2; i < HID_KEYBOARD_INPUT_DATA_LEN; i++) //Key array + { + readData = HID_Handle->Data[i]; + if (readData > HID_KEYBOARD_MAX_KEY) + { + readData = HID_KEYBOARD_MAX_KEY; + } + packetToSend->Data[i] = readData; + } +} + + diff --git a/Upstream/Inc/upstream_hid.h b/Upstream/Inc/upstream_hid.h index 9bc5de7..78ef333 100644 --- a/Upstream/Inc/upstream_hid.h +++ b/Upstream/Inc/upstream_hid.h @@ -14,18 +14,30 @@ #define UPSTREAM_HID_H_ - #include "stm32f4xx_hal.h" +#include "upstream_spi.h" + + +//These defines are duplicated in downstream_hid.h. Keep them in sync! +#define HID_MOUSE_INPUT_DATA_LEN 4 +#define HID_MOUSE_OUTPUT_DATA_LEN 0 +#define HID_MOUSE_MAX_BUTTONS 3 +#define HID_KEYBOARD_INPUT_DATA_LEN 8 +#define HID_KEYBOARD_OUTPUT_DATA_LEN 1 +#define HID_KEYBOARD_MAX_KEY 101 +#define HID_KEYBOARD_MAX_LED 3 -typedef uint8_t (*UpstreamHidSendReportCallback)(uint8_t *report, + +typedef uint8_t (*UpstreamHidGetReportCallback)(uint8_t *report, uint16_t len); void Upstream_HID_DeInit(void); -HAL_StatusTypeDef Upstream_HID_GetNextReport(UpstreamHidSendReportCallback callback); - +void Upstream_HID_GetNextInterruptReport(UpstreamHidGetReportCallback callback); +void Upstream_HID_SendControlReport(UpstreamPacketTypeDef* packetToSend, uint8_t dataLength); +void Upstream_HID_ReallySendControlReport(void); diff --git a/Upstream/Inc/upstream_interface_def.h b/Upstream/Inc/upstream_interface_def.h index f122887..3bb78b7 100644 --- a/Upstream/Inc/upstream_interface_def.h +++ b/Upstream/Inc/upstream_interface_def.h @@ -59,7 +59,8 @@ InterfaceCommandMscTypeDef; typedef enum { - COMMAND_HID_REPORT, //Returns HID report + COMMAND_HID_GET_REPORT, //Returns HID report from device + COMMAND_HID_SET_REPORT //Sends HID report to device. No reply or ack expected. } InterfaceCommandHidTypeDef; diff --git a/Upstream/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Inc/usbd_hid.h b/Upstream/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Inc/usbd_hid.h index 2aef166..46bbb06 100644 --- a/Upstream/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Inc/usbd_hid.h +++ b/Upstream/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Inc/usbd_hid.h @@ -23,6 +23,9 @@ * limitations under the License. * ****************************************************************************** + * + * Modifications by Robert Fisk + * */ /* Define to prevent recursive inclusion -------------------------------------*/ @@ -50,11 +53,11 @@ * @{ */ #define HID_EPIN_ADDR 0x81 -#define HID_EPIN_SIZE 0x04 #define USB_HID_CONFIG_DESC_SIZ 34 #define USB_HID_DESC_SIZ 9 #define HID_MOUSE_REPORT_DESC_SIZE 74 +#define HID_KEYBOARD_REPORT_DESC_SIZE 63 #define HID_DESCRIPTOR_TYPE 0x21 #define HID_REPORT_DESC 0x22 @@ -71,6 +74,10 @@ #define HID_REQ_SET_REPORT 0x09 #define HID_REQ_GET_REPORT 0x01 + +#define HID_KEYBRD_BOOT_CODE 0x01 +#define HID_MOUSE_BOOT_CODE 0x02 + /** * @} */ diff --git a/Upstream/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Src/usbd_hid.c b/Upstream/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Src/usbd_hid.c index 5a35812..22be3ec 100644 --- a/Upstream/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Src/usbd_hid.c +++ b/Upstream/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Src/usbd_hid.c @@ -73,6 +73,8 @@ static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum); static uint8_t USBD_HID_SendReport (uint8_t *report, uint16_t len); +static uint8_t USBD_HID_EP0RxReady(USBD_HandleTypeDef *pdev); + #define USBD_PID_HID 0x0002 @@ -84,7 +86,7 @@ USBD_ClassTypeDef USBD_HID = USBD_HID_DeInit, USBD_HID_Setup, NULL, /*EP0_TxSent*/ - NULL, /*EP0_RxReady*/ + USBD_HID_EP0RxReady, /*EP0_RxReady*/ USBD_HID_DataIn, /*DataIn*/ NULL, /*DataOut*/ NULL, /*SOF */ @@ -99,9 +101,11 @@ USBD_ClassTypeDef USBD_HID = }; +#define USB_HID_CFGDESC__INTERFACE_PROTOCOL_OFFSET 16 +#define USB_HID_CFGDESC__HID_REPORT_DESC_SIZE_OFFSET 25 +#define USB_HID_CFGDESC__EPIN_SIZE_OFFSET 31 +#define USB_HID_DESC__HID_REPORT_DESC_SIZE_OFFSET 7 -#define USB_HID_CFGDESC__HID_REPORT_DESC_SIZE_OFFSET 25 -#define USB_HID_DESC__HID_REPORT_DESC_SIZE_OFFSET 7 /* USB HID device Configuration Descriptor */ @@ -128,7 +132,7 @@ __ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_ 0x01, /*bNumEndpoints*/ 0x03, /*bInterfaceClass: HID*/ 0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/ - 0x02, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/ + 0x00, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/ 0, /*iInterface: Index of string descriptor*/ /******************** Descriptor of Joystick Mouse HID ********************/ /* 18 */ @@ -148,7 +152,7 @@ __ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_ HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/ 0x03, /*bmAttributes: Interrupt endpoint*/ - HID_EPIN_SIZE, /*wMaxPacketSize: 4 Byte max */ + 0x00, //HID_EPIN_SIZE, /*wMaxPacketSize: 4 Byte max */ 0x00, HID_FS_BINTERVAL, /*bInterval: Polling Interval (10 ms)*/ /* 34 */ @@ -192,14 +196,14 @@ __ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] _ 0xA1, 0x00, // Collection (Physical) 0x05, 0x09, // Usage Page (Button) 0x19, 0x01, // Usage Minimum (0x01) - 0x29, 0x03, // Usage Maximum (0x03) + 0x29, HID_MOUSE_MAX_BUTTONS, // Usage Maximum (0x03) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) - 0x95, 0x03, // Report Count (3) + 0x95, HID_MOUSE_MAX_BUTTONS, // Report Count (3) 0x75, 0x01, // Report Size (1) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x95, 0x01, // Report Count (1) - 0x75, 0x05, // Report Size (5) + 0x75, (8 - HID_MOUSE_MAX_BUTTONS), // Report Size (5) 0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x30, // Usage (X) @@ -223,14 +227,54 @@ __ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] _ 0x95, 0x01, // Report Count (1) 0xB1, 0x01, // Feature (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0xC0, // End Collection - // 74 bytes }; -USBD_HandleTypeDef *USBD_HID_pdev; -uint8_t* ActiveReportDescriptor = NULL; -uint8_t ActiveReportDescriptorLength; +__ALIGN_BEGIN static uint8_t HID_KEYBOARD_ReportDesc[HID_KEYBOARD_REPORT_DESC_SIZE] __ALIGN_END = { + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x06, // USAGE (Keyboard) + 0xa1, 0x01, // COLLECTION (Application) + 0x05, 0x07, // USAGE_PAGE (Keyboard) + 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) + 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x08, // REPORT_COUNT (8) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x08, // REPORT_SIZE (8) + 0x81, 0x03, // INPUT (Cnst,Var,Abs) + 0x95, HID_KEYBOARD_MAX_LED, // REPORT_COUNT (5) + 0x75, 0x01, // REPORT_SIZE (1) + 0x05, 0x08, // USAGE_PAGE (LEDs) + 0x19, 0x01, // USAGE_MINIMUM (Num Lock) + 0x29, 0x03, // USAGE_MAXIMUM (Scroll Lock) + 0x91, 0x02, // OUTPUT (Data,Var,Abs) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, (8 - HID_KEYBOARD_MAX_LED), // REPORT_SIZE (3) + 0x91, 0x03, // OUTPUT (Cnst,Var,Abs) + 0x95, 0x06, // REPORT_COUNT (6) + 0x75, 0x08, // REPORT_SIZE (8) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, HID_KEYBOARD_MAX_KEY, // LOGICAL_MAXIMUM (101) + 0x05, 0x07, // USAGE_PAGE (Keyboard) + 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) + 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) + 0x81, 0x00, // INPUT (Data,Ary,Abs) + 0xc0 // END_COLLECTION +}; + + + + +USBD_HandleTypeDef *USBD_HID_pdev; +UpstreamPacketTypeDef* OutReportPacket = NULL; +uint8_t* ActiveReportDescriptor = NULL; +uint8_t ActiveReportDescriptorLength; +uint8_t InReportSize; +uint8_t OutReportSize; /** @@ -252,12 +296,29 @@ void USBD_HID_PreinitMouse(void) { ActiveReportDescriptor = HID_MOUSE_ReportDesc; ActiveReportDescriptorLength = HID_MOUSE_REPORT_DESC_SIZE; + InReportSize = HID_MOUSE_INPUT_DATA_LEN; + OutReportSize = HID_MOUSE_OUTPUT_DATA_LEN; + USBD_HID_CfgDesc[USB_HID_CFGDESC__INTERFACE_PROTOCOL_OFFSET] = HID_MOUSE_BOOT_CODE; USBD_HID_CfgDesc[USB_HID_CFGDESC__HID_REPORT_DESC_SIZE_OFFSET] = HID_MOUSE_REPORT_DESC_SIZE; + USBD_HID_CfgDesc[USB_HID_CFGDESC__EPIN_SIZE_OFFSET] = HID_MOUSE_INPUT_DATA_LEN; USBD_HID_Desc[USB_HID_DESC__HID_REPORT_DESC_SIZE_OFFSET] = HID_MOUSE_REPORT_DESC_SIZE; } +void USBD_HID_PreinitKeyboard(void) +{ + ActiveReportDescriptor = HID_KEYBOARD_ReportDesc; + ActiveReportDescriptorLength = HID_KEYBOARD_REPORT_DESC_SIZE; + InReportSize = HID_KEYBOARD_INPUT_DATA_LEN; + OutReportSize = HID_KEYBOARD_OUTPUT_DATA_LEN; + + USBD_HID_CfgDesc[USB_HID_CFGDESC__INTERFACE_PROTOCOL_OFFSET] = HID_KEYBRD_BOOT_CODE; + USBD_HID_CfgDesc[USB_HID_CFGDESC__HID_REPORT_DESC_SIZE_OFFSET] = HID_KEYBOARD_REPORT_DESC_SIZE; + USBD_HID_CfgDesc[USB_HID_CFGDESC__EPIN_SIZE_OFFSET] = HID_KEYBOARD_INPUT_DATA_LEN; + USBD_HID_Desc[USB_HID_DESC__HID_REPORT_DESC_SIZE_OFFSET] = HID_KEYBOARD_REPORT_DESC_SIZE; +} + static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev, @@ -269,7 +330,7 @@ static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev, USBD_LL_OpenEP(pdev, HID_EPIN_ADDR, USBD_EP_TYPE_INTR, - HID_EPIN_SIZE); + InReportSize); pdev->pClassData = USBD_malloc(sizeof (USBD_HID_HandleTypeDef)); @@ -282,7 +343,7 @@ static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev, ((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE; USBD_HID_pdev = pdev; - Upstream_HID_GetNextReport(USBD_HID_SendReport); + Upstream_HID_GetNextInterruptReport(USBD_HID_SendReport); } return ret; @@ -326,7 +387,7 @@ static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev, { uint16_t len = 0; uint8_t *pbuf = NULL; - USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*) pdev->pClassData; + USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*) pdev->pClassData; if (ActiveReportDescriptor == NULL) { @@ -339,8 +400,7 @@ static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev, case USB_REQ_TYPE_CLASS : switch (req->bRequest) { - - + case HID_REQ_SET_PROTOCOL: hhid->Protocol = (uint8_t)(req->wValue); break; @@ -358,7 +418,24 @@ static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev, case HID_REQ_GET_IDLE: USBD_CtlSendData (pdev, (uint8_t *)&hhid->IdleState, - 1); + 1); + break; + + case HID_REQ_SET_REPORT: + if ((OutReportSize > 0) && + (req->wLength == OutReportSize)) + { + if (OutReportPacket != NULL) while(1); + OutReportPacket = Upstream_GetFreePacketImmediately(); + if (OutReportPacket == NULL) while(1); + USBD_CtlPrepareRx(pdev, OutReportPacket->Data, OutReportSize); + } + else + { + USBD_CtlError (pdev, req); + return USBD_FAIL; + } + break; default: @@ -489,7 +566,7 @@ static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev, ((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE; USBD_HID_pdev = pdev; - Upstream_HID_GetNextReport(USBD_HID_SendReport); + Upstream_HID_GetNextInterruptReport(USBD_HID_SendReport); return USBD_OK; } @@ -507,6 +584,23 @@ static uint8_t *USBD_HID_GetDeviceQualifierDesc (uint16_t *length) return USBD_HID_DeviceQualifierDesc; } + +//Called when data is received from host on control endpoint. +//Upstream_HID may send this immediately, but will probably have to save it and send after the next interrupt transfer +static uint8_t USBD_HID_EP0RxReady(USBD_HandleTypeDef *pdev) +{ + if ((OutReportPacket == NULL) || + (OutReportSize == 0)) + { + while(1); + } + + Upstream_HID_SendControlReport(OutReportPacket, OutReportSize); + Upstream_ReleasePacket(OutReportPacket); + OutReportPacket = NULL; + return USBD_OK; +} + /** * @} */ diff --git a/Upstream/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c b/Upstream/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c index 2b3791c..fa946cb 100755 --- a/Upstream/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c +++ b/Upstream/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c @@ -314,7 +314,7 @@ USBD_StatusTypeDef USBD_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, u USBD_CtlContinueRx (pdev, pdata, - MIN(pep->rem_length ,pep->maxpacket)); + pep->rem_length); } else { @@ -354,35 +354,24 @@ USBD_StatusTypeDef USBD_DataInStage(USBD_HandleTypeDef *pdev ,uint8_t epnum, uin { if(pep->rem_length > pep->maxpacket) { - pep->rem_length -= pep->maxpacket; + pep->rem_length -= pep->maxpacket; USBD_CtlContinueSendData (pdev, pdata, pep->rem_length); } else - - /* Prepare endpoint for premature end of transfer */ - USBD_LL_PrepareReceive (pdev, - 0, - NULL, - 0); - { /* last packet is MPS multiple, so send ZLP packet */ + { + //We sent less data than host was expecting? + /* last packet is MPS multiple, so send ZLP packet */ if((pep->total_length % pep->maxpacket == 0) && (pep->total_length >= pep->maxpacket) && (pep->total_length < pdev->ep0_data_len )) { - USBD_CtlContinueSendData(pdev , NULL, 0); pdev->ep0_data_len = 0; } else - - /* Prepare endpoint for premature end of transfer */ - USBD_LL_PrepareReceive (pdev, - 0, - NULL, - 0); { if((pdev->pClass->EP0_TxSent != NULL)&& (pdev->dev_state == USBD_STATE_CONFIGURED)) diff --git a/Upstream/Src/upstream_hid.c b/Upstream/Src/upstream_hid.c index f1f637c..a029524 100644 --- a/Upstream/Src/upstream_hid.c +++ b/Upstream/Src/upstream_hid.c @@ -12,23 +12,19 @@ #include "upstream_hid.h" -#include "upstream_spi.h" #include "upstream_interface_def.h" -#include "usbd_hid.h" -#define HID_MOUSE_DATA_LEN 4 -#define HID_KEYBOARD_DATA_LEN 0 - -#define HID_MOUSE_MAX_BUTTONS 4 - UpstreamPacketTypeDef* UpstreamHidPacket = NULL; -UpstreamHidSendReportCallback ReportCallback = NULL; +UpstreamHidGetReportCallback GetReportCallback = NULL; +uint8_t KeyboardOutDataAvailable = 0; +uint8_t KeyboardOutData[HID_KEYBOARD_OUTPUT_DATA_LEN]; -void Upstream_HID_GetNextReportReceiveCallback(UpstreamPacketTypeDef* receivedPacket); + +void Upstream_HID_GetNextInterruptReportReceiveCallback(UpstreamPacketTypeDef* receivedPacket); @@ -39,29 +35,31 @@ void Upstream_HID_DeInit(void) Upstream_ReleasePacket(UpstreamHidPacket); UpstreamHidPacket = NULL; } - ReportCallback = NULL; + GetReportCallback = NULL; + KeyboardOutDataAvailable = 0; } -HAL_StatusTypeDef Upstream_HID_GetNextReport(UpstreamHidSendReportCallback callback) +void Upstream_HID_GetNextInterruptReport(UpstreamHidGetReportCallback callback) { UpstreamPacketTypeDef* freePacket; InterfaceCommandClassTypeDef activeClass; activeClass = Upstream_StateMachine_CheckActiveClass(); - if ((activeClass != COMMAND_CLASS_HID_MOUSE)) //add classes here + if ((activeClass != COMMAND_CLASS_HID_MOUSE) && + (activeClass != COMMAND_CLASS_HID_KEYBOARD)) //add classes here { UPSTREAM_STATEMACHINE_FREAKOUT; - return HAL_ERROR; + return; } //Just return if we already have an outstanding request - if (ReportCallback != NULL) + if (GetReportCallback != NULL) { - return HAL_OK; + return; } - ReportCallback = callback; + GetReportCallback = callback; //Release packet used for last transaction (if any) if (UpstreamHidPacket != NULL) @@ -73,41 +71,43 @@ HAL_StatusTypeDef Upstream_HID_GetNextReport(UpstreamHidSendReportCallback callb freePacket = Upstream_GetFreePacketImmediately(); if (freePacket == NULL) { - return HAL_ERROR; + return; } freePacket->Length16 = UPSTREAM_PACKET_HEADER_LEN_16; freePacket->CommandClass = activeClass; - freePacket->Command = COMMAND_HID_REPORT; + freePacket->Command = COMMAND_HID_GET_REPORT; if (Upstream_TransmitPacket(freePacket) == HAL_OK) { - return Upstream_ReceivePacket(Upstream_HID_GetNextReportReceiveCallback); + Upstream_ReceivePacket(Upstream_HID_GetNextInterruptReportReceiveCallback); + } + else + { + Upstream_ReleasePacket(freePacket); } - - //else: - Upstream_ReleasePacket(freePacket); - return HAL_ERROR; } -void Upstream_HID_GetNextReportReceiveCallback(UpstreamPacketTypeDef* receivedPacket) +void Upstream_HID_GetNextInterruptReportReceiveCallback(UpstreamPacketTypeDef* receivedPacket) { - UpstreamHidSendReportCallback tempReportCallback; + UpstreamHidGetReportCallback tempReportCallback; InterfaceCommandClassTypeDef activeClass; - uint8_t dataLength = 0; - uint8_t i; + uint32_t i; + uint8_t dataLength; + activeClass = Upstream_StateMachine_CheckActiveClass(); - if ((activeClass != COMMAND_CLASS_HID_MOUSE)) //add classes here + if ((activeClass != COMMAND_CLASS_HID_MOUSE) && + (activeClass != COMMAND_CLASS_HID_KEYBOARD)) //add classes here { UPSTREAM_STATEMACHINE_FREAKOUT; return; } if ((UpstreamHidPacket != NULL) || - (ReportCallback == NULL)) + (GetReportCallback == NULL)) { UPSTREAM_SPI_FREAKOUT; return; @@ -121,37 +121,121 @@ void Upstream_HID_GetNextReportReceiveCallback(UpstreamPacketTypeDef* receivedPa if (activeClass == COMMAND_CLASS_HID_MOUSE) { - if (receivedPacket->Length16 != (UPSTREAM_PACKET_HEADER_LEN_16 + ((HID_MOUSE_DATA_LEN + 1) / 2))) + if (receivedPacket->Length16 != (UPSTREAM_PACKET_HEADER_LEN_16 + ((HID_MOUSE_INPUT_DATA_LEN + 1) / 2))) { UPSTREAM_SPI_FREAKOUT; return; } + dataLength = HID_MOUSE_INPUT_DATA_LEN; + if ((receivedPacket->Data[0] & ~((1 << HID_MOUSE_MAX_BUTTONS) - 1)) != 0) //Check number of buttons received + { + UPSTREAM_SPI_FREAKOUT; + return; + } + //Other mouse sanity checks & stuff go here... + } - receivedPacket->Data[0] &= ((1 << HID_MOUSE_MAX_BUTTONS) - 1); //Limit number of buttons received - - //Mouse sanity checks & stuff go here... + else if (activeClass == COMMAND_CLASS_HID_KEYBOARD) + { + if (receivedPacket->Length16 != (UPSTREAM_PACKET_HEADER_LEN_16 + ((HID_KEYBOARD_INPUT_DATA_LEN + 1) / 2))) + { + UPSTREAM_SPI_FREAKOUT; + return; + } + dataLength = HID_KEYBOARD_INPUT_DATA_LEN; - dataLength = HID_MOUSE_DATA_LEN; + if (receivedPacket->Data[1] != 0) + { + UPSTREAM_SPI_FREAKOUT; + return; + } + for (i = 2; i < HID_KEYBOARD_INPUT_DATA_LEN; i++) + { + if (receivedPacket->Data[i] > HID_KEYBOARD_MAX_KEY) + { + UPSTREAM_SPI_FREAKOUT; + return; + } + } + //Other keyboard sanity checks here... } //Other HID classes go here... + else + { + UPSTREAM_SPI_FREAKOUT; + return; + } + + UpstreamHidPacket = receivedPacket; //Save packet so we can free it when upstream USB transaction is done + tempReportCallback = GetReportCallback; + GetReportCallback = NULL; + tempReportCallback(receivedPacket->Data, dataLength); + - if (dataLength == 0) + //Check if we need to send OUT data to the keyboard before requesting next Interrupt IN data + if (KeyboardOutDataAvailable) + { + Upstream_HID_ReallySendControlReport(); + } +} + + + +void Upstream_HID_SendControlReport(UpstreamPacketTypeDef* packetToSend, uint8_t dataLength) +{ + InterfaceCommandClassTypeDef activeClass; + uint32_t i; + + activeClass = Upstream_StateMachine_CheckActiveClass(); + if ((packetToSend == NULL) || + (activeClass != COMMAND_CLASS_HID_KEYBOARD) || + (dataLength != HID_KEYBOARD_OUTPUT_DATA_LEN)) { UPSTREAM_SPI_FREAKOUT; return; } - for (i = dataLength; i < HID_EPIN_SIZE; i++) + if (GetReportCallback == NULL) { - receivedPacket->Data[i] = 0; //Zero out unused bytes before we send report upstream + while(1); //checkme! } - UpstreamHidPacket = receivedPacket; //Save packet so we can free it when upstream USB transaction is done - tempReportCallback = ReportCallback; - ReportCallback = NULL; - tempReportCallback(receivedPacket->Data, HID_EPIN_SIZE); + //Save data until after the next interrupt data is received from Downstream + KeyboardOutDataAvailable = 1; + for (i = 0; i < HID_KEYBOARD_OUTPUT_DATA_LEN; i++) + { + KeyboardOutData[i] = packetToSend->Data[i]; + } +} + + + +void Upstream_HID_ReallySendControlReport(void) +{ + UpstreamPacketTypeDef* freePacket; + uint32_t i; + + KeyboardOutDataAvailable = 0; + + freePacket = Upstream_GetFreePacketImmediately(); + if (freePacket == NULL) return; + + freePacket->Length16 = UPSTREAM_PACKET_HEADER_LEN_16 + ((HID_KEYBOARD_OUTPUT_DATA_LEN + 1) / 2); + freePacket->CommandClass = COMMAND_CLASS_HID_KEYBOARD; + freePacket->Command = COMMAND_HID_SET_REPORT; + + for (i = 0; i < HID_KEYBOARD_OUTPUT_DATA_LEN; i++) + { + freePacket->Data[i] = KeyboardOutData[i]; + } + freePacket->Data[0] &= ((1 << HID_KEYBOARD_MAX_LED) - 1); + + if (Upstream_TransmitPacket(freePacket) != HAL_OK) + { + Upstream_ReleasePacket(freePacket); + } } diff --git a/Upstream/Src/upstream_statemachine.c b/Upstream/Src/upstream_statemachine.c index 1002b53..2ae9cc1 100644 --- a/Upstream/Src/upstream_statemachine.c +++ b/Upstream/Src/upstream_statemachine.c @@ -180,6 +180,12 @@ void Upstream_StateMachine_NotifyDeviceReplyCallback(UpstreamPacketTypeDef* repl USBD_HID_PreinitMouse(); break; + case COMMAND_CLASS_HID_KEYBOARD: + newActiveClass = COMMAND_CLASS_HID_KEYBOARD; + newClassPointer = &USBD_HID; + USBD_HID_PreinitKeyboard(); + break; + //Add other supported classes here... } diff --git a/Upstream/Upstream Debug.launch b/Upstream/Upstream Debug.launch index e612e23..bb74e62 100644 --- a/Upstream/Upstream Debug.launch +++ b/Upstream/Upstream Debug.launch @@ -1,6 +1,6 @@ - +