From 4c40373a322d34b37266efa8f0641e97ca4537c1 Mon Sep 17 00:00:00 2001 From: Robert Fisk Date: Sun, 17 Jan 2016 12:10:12 +1300 Subject: [PATCH] Upstream HID mouse support probably done, not tested yet. --- Upstream/Inc/upstream_hid.h | 35 +++++ Upstream/Inc/upstream_interface_def.h | 7 + Upstream/Inc/upstream_spi.h | 5 + .../Class/HID/Inc/usbd_hid.h | 5 +- .../Class/HID/Src/usbd_hid.c | 131 +++++++++--------- Upstream/Src/upstream_hid.c | 117 ++++++++++++++++ Upstream/Src/upstream_spi.c | 26 +++- 7 files changed, 254 insertions(+), 72 deletions(-) create mode 100644 Upstream/Inc/upstream_hid.h create mode 100644 Upstream/Src/upstream_hid.c diff --git a/Upstream/Inc/upstream_hid.h b/Upstream/Inc/upstream_hid.h new file mode 100644 index 0000000..fa5d5fd --- /dev/null +++ b/Upstream/Inc/upstream_hid.h @@ -0,0 +1,35 @@ +/* + * upstream_hid.h + * + * Created on: Jan 16, 2016 + * Author: Robert Fisk + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + + +#ifndef UPSTREAM_HID_H_ +#define UPSTREAM_HID_H_ + + + +//#include "usbd_def.h" +#include "stm32f4xx_hal.h" +#include "upstream_interface_def.h" + + +typedef uint8_t UpstreamHidSendReportCallback(uint8_t *report, + uint16_t len); + + +void Upstream_HID_Init(InterfaceCommandClassTypeDef newClass); +void Upstream_HID_DeInit(void); +void Upstream_HID_GetNextReport(UpstreamHidSendReportCallback callback); + + + + + +#endif /* UPSTREAM_HID_H_ */ diff --git a/Upstream/Inc/upstream_interface_def.h b/Upstream/Inc/upstream_interface_def.h index 825c6da..d2366a6 100644 --- a/Upstream/Inc/upstream_interface_def.h +++ b/Upstream/Inc/upstream_interface_def.h @@ -56,6 +56,13 @@ typedef enum InterfaceCommandMscTypeDef; +typedef enum +{ + COMMAND_HID_REPORT, //Downstream initiates HID report transfer to Upstream. Upstream just needs to Upstream_ReceivePacket each time. +} +InterfaceCommandHidTypeDef; + + typedef enum { COMMAND_ERROR_GENERIC, diff --git a/Upstream/Inc/upstream_spi.h b/Upstream/Inc/upstream_spi.h index f41c8c6..b96e00c 100644 --- a/Upstream/Inc/upstream_spi.h +++ b/Upstream/Inc/upstream_spi.h @@ -13,7 +13,10 @@ #define INC_UPSTREAM_SPI_H_ +#include "upstream_statemachine.h" #include "usbd_config.h" +#include "led.h" + #define UPSTREAM_PACKET_HEADER_LEN (2) //Min length = CommandClass & Command bytes @@ -84,6 +87,8 @@ HAL_StatusTypeDef Upstream_ReceivePacket(SpiPacketReceivedCallbackTypeDef callba void Upstream_TxOkInterrupt(void); void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi); void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi); +void Upstream_SetExpectedReceivedCommand(uint8_t expectedCommandClass, + uint8_t expectedCommand); #endif /* INC_UPSTREAM_SPI_H_ */ 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 2c5b69f..e0a1e25 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 @@ -124,9 +124,8 @@ extern USBD_ClassTypeDef USBD_HID_Keyboard; /** @defgroup USB_CORE_Exported_Functions * @{ */ -uint8_t USBD_HID_SendReport (USBD_HandleTypeDef *pdev, - uint8_t *report, - uint16_t len); +uint8_t USBD_HID_SendReport (uint8_t *report, + uint16_t len); uint32_t USBD_HID_GetPollingInterval (USBD_HandleTypeDef *pdev); 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 91875e3..3925e7e 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 @@ -44,11 +44,14 @@ * limitations under the License. * ****************************************************************************** - */ + * + * Modifications by Robert Fisk + */ /* Includes ------------------------------------------------------------------*/ #include "usbd_hid.h" #include "usbd_ctlreq.h" +#include "upstream_hid.h" @@ -113,8 +116,8 @@ USBD_ClassTypeDef USBD_HID_Keyboard = -#define USB_HID_CFGDESC_HID_REPORT_DESC_SIZE_OFFSET 25 -#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 */ @@ -198,57 +201,52 @@ __ALIGN_BEGIN static uint8_t USBD_HID_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_ __ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END = { - 0x05, 0x01, - 0x09, 0x02, - 0xA1, 0x01, - 0x09, 0x01, - - 0xA1, 0x00, - 0x05, 0x09, - 0x19, 0x01, - 0x29, 0x03, - - 0x15, 0x00, - 0x25, 0x01, - 0x95, 0x03, - 0x75, 0x01, - - 0x81, 0x02, - 0x95, 0x01, - 0x75, 0x05, - 0x81, 0x01, - - 0x05, 0x01, - 0x09, 0x30, - 0x09, 0x31, - 0x09, 0x38, - - 0x15, 0x81, - 0x25, 0x7F, - 0x75, 0x08, - 0x95, 0x03, - - 0x81, 0x06, - 0xC0, 0x09, - 0x3c, 0x05, - 0xff, 0x09, + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x02, // Usage (Mouse) + 0xA1, 0x01, // Collection (Application) + 0x09, 0x01, // Usage (Pointer) + 0xA1, 0x00, // Collection (Physical) + 0x05, 0x09, // Usage Page (Button) + 0x19, 0x01, // Usage Minimum (0x01) + 0x29, 0x03, // Usage Maximum (0x03) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x95, 0x03, // 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) + 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) + 0x09, 0x31, // Usage (Y) + 0x09, 0x38, // Usage (Wheel) + 0x15, 0x81, // Logical Minimum (129) + 0x25, 0x7F, // Logical Maximum (127) + 0x75, 0x08, // Report Size (8) + 0x95, 0x03, // Report Count (3) + 0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position) + 0xC0, // End Collection + 0x09, 0x3C, // Usage (Motion Wakeup) + 0x05, 0xFF, // Usage Page (Reserved 0xFF) + 0x09, 0x01, // Usage (0x01) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x01, // Report Size (1) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x22, // Feature (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Non-volatile) + 0x75, 0x07, // Report Size (7) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x01, // Feature (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + 0xC0, // End Collection - 0x01, 0x15, - 0x00, 0x25, - 0x01, 0x75, - 0x01, 0x95, - - 0x02, 0xb1, - 0x22, 0x75, - 0x06, 0x95, - 0x01, 0xb1, - - 0x01, 0xc0 + // 74 bytes }; -uint8_t* ActiveReportDescriptor = NULL; -uint8_t ActiveReportDescriptorLength; +USBD_HandleTypeDef *USBD_HID_pdev; +uint8_t* ActiveReportDescriptor = NULL; +uint8_t ActiveReportDescriptorLength; /** @@ -266,14 +264,16 @@ uint8_t ActiveReportDescriptorLength; * @param cfgidx: Configuration index * @retval status */ -static uint8_t USBD_HID_InitMouse(USBD_HandleTypeDef *pdev, - uint8_t cfgidx) +static uint8_t USBD_HID_InitMouse(USBD_HandleTypeDef *pdev, + uint8_t cfgidx) { ActiveReportDescriptor = HID_MOUSE_ReportDesc; ActiveReportDescriptorLength = HID_MOUSE_REPORT_DESC_SIZE; - USBD_HID_CfgDesc[USB_HID_CFGDESC_HID_REPORT_DESC_SIZE_OFFSET] = HID_MOUSE_REPORT_DESC_SIZE; - USBD_HID_Desc[USB_HID_DESC_HID_REPORT_DESC_SIZE_OFFSET] = HID_MOUSE_REPORT_DESC_SIZE; + USBD_HID_CfgDesc[USB_HID_CFGDESC__HID_REPORT_DESC_SIZE_OFFSET] = HID_MOUSE_REPORT_DESC_SIZE; + USBD_HID_Desc[USB_HID_DESC__HID_REPORT_DESC_SIZE_OFFSET] = HID_MOUSE_REPORT_DESC_SIZE; + + Upstream_HID_Init(COMMAND_CLASS_HID_MOUSE); return USBD_HID_Init(pdev, cfgidx); } @@ -301,7 +301,11 @@ static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev, else { ((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE; + + USBD_HID_pdev = pdev; + Upstream_HID_GetNextReport(USBD_HID_SendReport); } + return ret; } @@ -316,6 +320,7 @@ static uint8_t USBD_HID_DeInit (USBD_HandleTypeDef *pdev, uint8_t cfgidx) { ActiveReportDescriptor = NULL; + Upstream_HID_DeInit(); /* Close HID EPs */ USBD_LL_CloseEP(pdev, @@ -426,18 +431,17 @@ static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev, * @param buff: pointer to report * @retval status */ -uint8_t USBD_HID_SendReport (USBD_HandleTypeDef *pdev, - uint8_t *report, - uint16_t len) +uint8_t USBD_HID_SendReport(uint8_t *report, + uint16_t len) { - USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*)pdev->pClassData; + USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*)USBD_HID_pdev->pClassData; - if (pdev->dev_state == USBD_STATE_CONFIGURED ) + if (USBD_HID_pdev->dev_state == USBD_STATE_CONFIGURED ) { if(hhid->state == HID_IDLE) { hhid->state = HID_BUSY; - USBD_LL_Transmit (pdev, + USBD_LL_Transmit (USBD_HID_pdev, HID_EPIN_ADDR, report, len); @@ -501,12 +505,15 @@ static uint8_t *USBD_HID_GetCfgDesc (uint16_t *length) * @retval status */ static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev, - uint8_t epnum) + uint8_t epnum) { - /* Ensure that the FIFO is empty before a new transfer, this condition could be caused by a new transfer before the end of the previous transfer */ ((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE; + + USBD_HID_pdev = pdev; + Upstream_HID_GetNextReport(USBD_HID_SendReport); + return USBD_OK; } diff --git a/Upstream/Src/upstream_hid.c b/Upstream/Src/upstream_hid.c new file mode 100644 index 0000000..cd7502f --- /dev/null +++ b/Upstream/Src/upstream_hid.c @@ -0,0 +1,117 @@ +/* + * upstream_hid.c + * + * Created on: Jan 16, 2016 + * Author: Robert Fisk + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + + + +#include "upstream_hid.h" +#include "upstream_spi.h" +#include "upstream_interface_def.h" +#include "usbd_hid.h" + + +#define HID_MOUSE_REPORT_LEN 4 + + + +InterfaceCommandClassTypeDef ActiveHidClass = COMMAND_CLASS_INTERFACE; +UpstreamPacketTypeDef* UpstreamHidPacket = NULL; + + +void Upstream_HID_GetNextReportReceiveCallback(UpstreamPacketTypeDef* receivedPacket); + + + +void Upstream_HID_Init(InterfaceCommandClassTypeDef newClass) +{ + if ((newClass != COMMAND_CLASS_HID_MOUSE)) //add classes here + { + UPSTREAM_SPI_FREAKOUT; + return; + } + + if (UpstreamHidPacket != NULL) + { + UPSTREAM_SPI_FREAKOUT; + return; + } + + ActiveHidClass = newClass; +} + + +void Upstream_HID_DeInit(void) +{ + ActiveHidClass = COMMAND_CLASS_INTERFACE; + if (UpstreamHidPacket != NULL) + { + Upstream_ReleasePacket(UpstreamHidPacket); + UpstreamHidPacket = NULL; + } +} + + +void Upstream_HID_GetNextReport(UpstreamHidSendReportCallback callback) +{ + if ((ActiveHidClass != COMMAND_CLASS_HID_MOUSE)) //add classes here + { + UPSTREAM_SPI_FREAKOUT; + return; + } + + //Release packet used for last transaction (if any) + if (UpstreamHidPacket != NULL) + { + Upstream_ReleasePacket(UpstreamHidPacket); + UpstreamHidPacket = NULL; + } + + //Get next packet + Upstream_SetExpectedReceivedCommand(ActiveHidClass, COMMAND_HID_REPORT); + Upstream_ReceivePacket(Upstream_HID_GetNextReportReceiveCallback); +} + + +void Upstream_HID_GetNextReportReceiveCallback(UpstreamPacketTypeDef* receivedPacket) +{ + uint8_t reportLength; + + if (UpstreamHidPacket != NULL) + { + UPSTREAM_SPI_FREAKOUT; + return; + } + + if (receivedPacket == NULL) + { + return; //Just give up... + } + + + if (ActiveHidClass == COMMAND_CLASS_HID_MOUSE) + { + if (receivedPacket->Length16 != (UPSTREAM_PACKET_HEADER_LEN_16 + ((HID_MOUSE_REPORT_LEN + 1) / 2))) + { + UPSTREAM_SPI_FREAKOUT; + return; + } + + //Mouse sanity checks & stuff go here... + + reportLength = HID_MOUSE_REPORT_LEN; + } + + //Other HID classes go here... + + + UpstreamHidPacket = receivedPacket; //Save packet so we can free it when upstream USB transaction is done + USBD_HID_SendReport(receivedPacket->Data, reportLength); +} + diff --git a/Upstream/Src/upstream_spi.c b/Upstream/Src/upstream_spi.c index e4787d1..25478cd 100644 --- a/Upstream/Src/upstream_spi.c +++ b/Upstream/Src/upstream_spi.c @@ -11,9 +11,7 @@ #include "upstream_interface_def.h" #include "upstream_spi.h" -#include "upstream_statemachine.h" #include "stm32f4xx_hal.h" -#include "usbd_def.h" #include "board_config.h" #include "interrupts.h" @@ -148,6 +146,12 @@ void Upstream_ReleasePacket(UpstreamPacketTypeDef* packetToRelease) return; } + if (packetToRelease->Busy != BUSY) + { + UPSTREAM_SPI_FREAKOUT; + return; + } + if (PendingFreePacketCallback != NULL) { tempCallback = PendingFreePacketCallback; //In extreme situations, running this callback can trigger another request for a free packet, @@ -445,8 +449,8 @@ void Upstream_BeginTransmitPacketSize(void) if (HAL_SPI_TransmitReceive(&Hspi1, (uint8_t*)&CurrentWorkingPacket->Length16, (uint8_t*)&TemporaryIncomingPacketLength, - 2, - SPI_TIMEOUT_VALUE) != HAL_OK) //We only need to write one word, but the peripheral library freaks out... + 2, //We only need to write one word, but the peripheral library freaks out... + SPI_TIMEOUT_VALUE) != HAL_OK) { UPSTREAM_SPI_FREAKOUT; } @@ -491,8 +495,8 @@ void Upstream_BeginReceivePacketSize(UpstreamPacketTypeDef* freePacket) if (HAL_SPI_TransmitReceive(&Hspi1, (uint8_t*)&CurrentWorkingPacket->Length16, (uint8_t*)&CurrentWorkingPacket->Length16, - 2, - SPI_TIMEOUT_VALUE) != HAL_OK) //We only need to write one word, but the peripheral library freaks out... + 2, //We only need to write one word, but the peripheral library freaks out... + SPI_TIMEOUT_VALUE) != HAL_OK) { UPSTREAM_SPI_FREAKOUT; } @@ -515,7 +519,6 @@ void Upstream_BeginReceivePacketBody(void) } - //Something bad happened! Possibly CRC error... void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) { @@ -537,3 +540,12 @@ void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) } +//Used by USB interface classes. +//This is required when Downstream sends a packet without an initiating request from us +void Upstream_SetExpectedReceivedCommand(uint8_t expectedCommandClass, + uint8_t expectedCommand) +{ + SentCommandClass = expectedCommandClass; + SentCommand = expectedCommand; +} +