From 655b0e56a81cdc400a63dc9dbe5c167c23398965 Mon Sep 17 00:00:00 2001 From: Robert Fisk Date: Sat, 30 Apr 2016 14:13:57 +1200 Subject: [PATCH] Support disconnect/reconnect of attached HID device --- Downstream/Inc/downstream_hid.h | 2 +- Downstream/Inc/downstream_statemachine.h | 2 + .../Class/HID/Inc/usbh_hid.h | 7 +--- .../Class/HID/Src/usbh_hid.c | 4 +- Downstream/Src/downstream_hid.c | 38 ++++++++--------- Downstream/Src/downstream_statemachine.c | 41 ++++++++++++++++--- Downstream/Src/interrupts.c | 8 +--- Downstream/Src/main.c | 1 + Upstream/Src/upstream_hid.c | 9 ++-- Upstream/Src/upstream_msc.c | 1 + 10 files changed, 69 insertions(+), 44 deletions(-) diff --git a/Downstream/Inc/downstream_hid.h b/Downstream/Inc/downstream_hid.h index a9f2fd2..640f9b6 100644 --- a/Downstream/Inc/downstream_hid.h +++ b/Downstream/Inc/downstream_hid.h @@ -45,7 +45,7 @@ InterfaceCommandClassTypeDef Downstream_HID_ApproveConnectedDevice(void); void Downstream_HID_PacketProcessor(DownstreamPacketTypeDef* receivedPacket); -void Downstream_HID_InterruptReportCallback(uint8_t* reportBuffer); +void Downstream_HID_InterruptReportCallback(DownstreamPacketTypeDef* packetToSend); diff --git a/Downstream/Inc/downstream_statemachine.h b/Downstream/Inc/downstream_statemachine.h index 6e86311..cffd57e 100644 --- a/Downstream/Inc/downstream_statemachine.h +++ b/Downstream/Inc/downstream_statemachine.h @@ -45,6 +45,8 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id); void Downstream_PacketProcessor(DownstreamPacketTypeDef* receivedPacket); void Downstream_PacketProcessor_GenericErrorReply(DownstreamPacketTypeDef* replyPacket); void Downstream_PacketProcessor_ClassReply(DownstreamPacketTypeDef* replyPacket); +void Downstream_PacketProcessor_NotifyDisconnectReplyRequired(void); +void Downstream_PacketProcessor_CheckNotifyDisconnectReply(void); void Downstream_PacketProcessor_SetErrorState(void); void Downstream_PacketProcessor_FreakOut(void); 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 3c630a3..03767d3 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 @@ -211,9 +211,6 @@ typedef struct -typedef void (*HID_InterruptReportCallback)(uint8_t* reportBuffer); - - /* Structure for HID process */ typedef struct _HID_Process { @@ -229,7 +226,7 @@ typedef struct _HID_Process uint8_t ep_addr; uint8_t Protocol; HID_DescTypeDef HID_Desc; - HID_InterruptReportCallback ReportCallback; + FreePacketCallbackTypeDef ReportCallback; uint8_t Data[HID_MAX_REPORT_SIZE]; } HID_HandleTypeDef; @@ -324,7 +321,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, - HID_InterruptReportCallback callback); + FreePacketCallbackTypeDef 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 87fd1df..848e89b 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 @@ -382,7 +382,7 @@ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost) if (urbStatus == USBH_URB_DONE) { - HID_Handle->ReportCallback(HID_Handle->Data); + Downstream_GetFreePacket(HID_Handle->ReportCallback); HID_Handle->state = HID_IDLE; break; } @@ -431,7 +431,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, - HID_InterruptReportCallback callback) + FreePacketCallbackTypeDef callback) { HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData; diff --git a/Downstream/Src/downstream_hid.c b/Downstream/Src/downstream_hid.c index c383344..e9cff89 100644 --- a/Downstream/Src/downstream_hid.c +++ b/Downstream/Src/downstream_hid.c @@ -25,7 +25,6 @@ #define HID_MOUSE_MAX_BUTTONS 4 -DownstreamPacketTypeDef* SavedPacket; extern USBH_HandleTypeDef hUsbHostFS; //Hard-link ourselves to usb_host.c extern InterfaceCommandClassTypeDef ConfiguredDeviceClass; //Do a cheap hard-link to downstream_statemachine.c, rather than keep a duplicate here @@ -50,7 +49,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(uint8_t* reportBuffer); +static void Downstream_HID_Mouse_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend); @@ -259,23 +258,22 @@ void Downstream_HID_PacketProcessor(DownstreamPacketTypeDef* receivedPacket) return; } - SavedPacket = receivedPacket; - + Downstream_ReleasePacket(receivedPacket); if (USBH_HID_GetInterruptReport(&hUsbHostFS, Downstream_HID_InterruptReportCallback) != HAL_OK) { Downstream_PacketProcessor_FreakOut(); } - + Downstream_PacketProcessor_NotifyDisconnectReplyRequired(); } -void Downstream_HID_InterruptReportCallback(uint8_t* reportBuffer) +void Downstream_HID_InterruptReportCallback(DownstreamPacketTypeDef* packetToSend) { if (ConfiguredDeviceClass == COMMAND_CLASS_HID_MOUSE) { - Downstream_HID_Mouse_ExtractDataFromReport(reportBuffer); - SavedPacket->Length16 = ((HID_MOUSE_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16; + Downstream_HID_Mouse_ExtractDataFromReport(packetToSend); + packetToSend->Length16 = ((HID_MOUSE_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16; } //else if... else @@ -284,35 +282,37 @@ void Downstream_HID_InterruptReportCallback(uint8_t* reportBuffer) return; } - Downstream_PacketProcessor_ClassReply(SavedPacket); + packetToSend->CommandClass = ConfiguredDeviceClass; + packetToSend->Command = COMMAND_HID_REPORT; + Downstream_PacketProcessor_ClassReply(packetToSend); } - -void Downstream_HID_Mouse_ExtractDataFromReport(uint8_t* reportBuffer) +void Downstream_HID_Mouse_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend) { + HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; uint16_t readData; //Grab the buttons - readData = *(uint16_t*)&(reportBuffer[(ReportButtonBitOffset / 8)]); + readData = *(uint16_t*)&(HID_Handle->Data[(ReportButtonBitOffset / 8)]); readData >>= (ReportButtonBitOffset % 8); readData &= ((1 << ReportButtonBitLength) - 1); - SavedPacket->Data[0] = readData; + packetToSend->Data[0] = readData; //Grab X - readData = *(uint16_t*)&(reportBuffer[(ReportXBitOffset / 8)]); + readData = *(uint16_t*)&(HID_Handle->Data[(ReportXBitOffset / 8)]); readData >>= (ReportXBitOffset % 8); - SavedPacket->Data[1] = (uint8_t)readData; + packetToSend->Data[1] = (uint8_t)readData; //Grab Y - readData = *(uint16_t*)&(reportBuffer[(ReportYBitOffset / 8)]); + readData = *(uint16_t*)&(HID_Handle->Data[(ReportYBitOffset / 8)]); readData >>= (ReportYBitOffset % 8); - SavedPacket->Data[2] = (uint8_t)readData; + packetToSend->Data[2] = (uint8_t)readData; //Grab wheel - readData = *(uint16_t*)&(reportBuffer[(ReportWheelBitOffset / 8)]); + readData = *(uint16_t*)&(HID_Handle->Data[(ReportWheelBitOffset / 8)]); readData >>= (ReportWheelBitOffset % 8); - SavedPacket->Data[3] = (uint8_t)readData; + packetToSend->Data[3] = (uint8_t)readData; } diff --git a/Downstream/Src/downstream_statemachine.c b/Downstream/Src/downstream_statemachine.c index 0a65f83..ae09dee 100644 --- a/Downstream/Src/downstream_statemachine.c +++ b/Downstream/Src/downstream_statemachine.c @@ -25,10 +25,12 @@ DownstreamStateTypeDef DownstreamState = STATE_DEVICE_NOT_READY; InterfaceCommandClassTypeDef ConfiguredDeviceClass = COMMAND_CLASS_INTERFACE; +uint8_t NotifyDisconnectReply = 0; -void Downstream_PacketProcessor_Interface(DownstreamPacketTypeDef* receivedPacket); -void Downstream_PacketProcessor_Interface_ReplyNotifyDevice(DownstreamPacketTypeDef* replyPacket); +static void Downstream_PacketProcessor_Interface(DownstreamPacketTypeDef* receivedPacket); +static void Downstream_PacketProcessor_Interface_ReplyNotifyDevice(DownstreamPacketTypeDef* replyPacket); +static void Downstream_PacketProcessor_NotifyDisconnectReply(DownstreamPacketTypeDef* packetToSend); @@ -71,10 +73,7 @@ void Downstream_PacketProcessor(DownstreamPacketTypeDef* receivedPacket) //we need to tell Upstream of the fact (and not freak out). if (DownstreamState == STATE_DEVICE_NOT_READY) { - receivedPacket->Length16 = DOWNSTREAM_PACKET_HEADER_LEN_16; - receivedPacket->CommandClass = COMMAND_CLASS_ERROR; - receivedPacket->Command = COMMAND_ERROR_DEVICE_DISCONNECTED; - Downstream_PacketProcessor_ClassReply(receivedPacket); + Downstream_PacketProcessor_NotifyDisconnectReply(receivedPacket); return; } @@ -172,6 +171,7 @@ void Downstream_PacketProcessor_GenericErrorReply(DownstreamPacketTypeDef* reply Downstream_TransmitPacket(replyPacket); Downstream_ReceivePacket(Downstream_PacketProcessor); + NotifyDisconnectReply = 0; } @@ -179,6 +179,31 @@ void Downstream_PacketProcessor_ClassReply(DownstreamPacketTypeDef* replyPacket) { Downstream_TransmitPacket(replyPacket); Downstream_ReceivePacket(Downstream_PacketProcessor); + NotifyDisconnectReply = 0; +} + + +void Downstream_PacketProcessor_NotifyDisconnectReplyRequired(void) +{ + NotifyDisconnectReply = 1; +} + + +void Downstream_PacketProcessor_CheckNotifyDisconnectReply(void) +{ + if (NotifyDisconnectReply == 2) + { + Downstream_GetFreePacket(Downstream_PacketProcessor_NotifyDisconnectReply); + } +} + + +void Downstream_PacketProcessor_NotifyDisconnectReply(DownstreamPacketTypeDef* packetToSend) +{ + packetToSend->Length16 = DOWNSTREAM_PACKET_HEADER_LEN_16; + packetToSend->CommandClass = COMMAND_CLASS_ERROR; + packetToSend->Command = COMMAND_ERROR_DEVICE_DISCONNECTED; + Downstream_PacketProcessor_ClassReply(packetToSend); } @@ -198,6 +223,10 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id) if (id == HOST_USER_DISCONNECTION) { DownstreamState = STATE_DEVICE_NOT_READY; + if (NotifyDisconnectReply == 1) + { + NotifyDisconnectReply = 2; //Request a 'device disconnected' reply when we get back to main() + } return; } diff --git a/Downstream/Src/interrupts.c b/Downstream/Src/interrupts.c index 720cee4..3d88c18 100644 --- a/Downstream/Src/interrupts.c +++ b/Downstream/Src/interrupts.c @@ -73,23 +73,19 @@ void SysTick_Handler(void) void DMA2_Stream2_IRQHandler(void) { - //SPI_INT_ACTIVE_ON; HAL_DMA_IRQHandler(&hdma_spi1_rx); - //SPI_INT_ACTIVE_OFF; } void DMA2_Stream3_IRQHandler(void) { - //SPI_INT_ACTIVE_ON; HAL_DMA_IRQHandler(&hdma_spi1_tx); - //SPI_INT_ACTIVE_OFF; } void OTG_FS_IRQHandler(void) { - INT_ACTIVE_ON; + //INT_ACTIVE_ON; HAL_HCD_IRQHandler(&hhcd_USB_OTG_FS); - INT_ACTIVE_OFF; + //INT_ACTIVE_OFF; } diff --git a/Downstream/Src/main.c b/Downstream/Src/main.c index a2e1ec2..5d29f71 100644 --- a/Downstream/Src/main.c +++ b/Downstream/Src/main.c @@ -73,6 +73,7 @@ int main(void) { USB_Host_Process(); Downstream_SPIProcess(); + Downstream_PacketProcessor_CheckNotifyDisconnectReply(); } } diff --git a/Upstream/Src/upstream_hid.c b/Upstream/Src/upstream_hid.c index 5ff95c4..0535233 100644 --- a/Upstream/Src/upstream_hid.c +++ b/Upstream/Src/upstream_hid.c @@ -20,6 +20,8 @@ #define HID_MOUSE_DATA_LEN 4 #define HID_KEYBOARD_DATA_LEN 0 +#define HID_MOUSE_MAX_BUTTONS 4 + UpstreamPacketTypeDef* UpstreamHidPacket = NULL; UpstreamHidSendReportCallback ReportCallback = NULL; @@ -60,11 +62,6 @@ HAL_StatusTypeDef Upstream_HID_GetNextReport(UpstreamHidSendReportCallback callb UpstreamHidPacket = NULL; } - if (ReportCallback != NULL) - { - UPSTREAM_STATEMACHINE_FREAKOUT; - return HAL_ERROR; - } ReportCallback = callback; freePacket = Upstream_GetFreePacketImmediately(); @@ -124,6 +121,8 @@ void Upstream_HID_GetNextReportReceiveCallback(UpstreamPacketTypeDef* receivedPa return; } + receivedPacket->Data[0] &= ((1 << HID_MOUSE_MAX_BUTTONS) - 1); //Limit number of buttons received + //Mouse sanity checks & stuff go here... dataLength = HID_MOUSE_DATA_LEN; diff --git a/Upstream/Src/upstream_msc.c b/Upstream/Src/upstream_msc.c index bf71253..55a4d8c 100644 --- a/Upstream/Src/upstream_msc.c +++ b/Upstream/Src/upstream_msc.c @@ -150,6 +150,7 @@ void Upstream_MSC_GetCapacityReplyCallback(UpstreamPacketTypeDef* replyPacket) if (replyPacket->Length16 != (UPSTREAM_PACKET_HEADER_LEN_16 + (8 / 2))) { + Upstream_ReleasePacket(replyPacket); GetCapacityCallback(NULL, 0, 0); return; }