Support disconnect/reconnect of attached HID device

pull/7/head
Robert Fisk 8 years ago
parent 056932d6bc
commit 655b0e56a8

@ -45,7 +45,7 @@
InterfaceCommandClassTypeDef Downstream_HID_ApproveConnectedDevice(void); InterfaceCommandClassTypeDef Downstream_HID_ApproveConnectedDevice(void);
void Downstream_HID_PacketProcessor(DownstreamPacketTypeDef* receivedPacket); void Downstream_HID_PacketProcessor(DownstreamPacketTypeDef* receivedPacket);
void Downstream_HID_InterruptReportCallback(uint8_t* reportBuffer); void Downstream_HID_InterruptReportCallback(DownstreamPacketTypeDef* packetToSend);

@ -45,6 +45,8 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id);
void Downstream_PacketProcessor(DownstreamPacketTypeDef* receivedPacket); void Downstream_PacketProcessor(DownstreamPacketTypeDef* receivedPacket);
void Downstream_PacketProcessor_GenericErrorReply(DownstreamPacketTypeDef* replyPacket); void Downstream_PacketProcessor_GenericErrorReply(DownstreamPacketTypeDef* replyPacket);
void Downstream_PacketProcessor_ClassReply(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_SetErrorState(void);
void Downstream_PacketProcessor_FreakOut(void); void Downstream_PacketProcessor_FreakOut(void);

@ -211,9 +211,6 @@ typedef struct
typedef void (*HID_InterruptReportCallback)(uint8_t* reportBuffer);
/* Structure for HID process */ /* Structure for HID process */
typedef struct _HID_Process typedef struct _HID_Process
{ {
@ -229,7 +226,7 @@ typedef struct _HID_Process
uint8_t ep_addr; uint8_t ep_addr;
uint8_t Protocol; uint8_t Protocol;
HID_DescTypeDef HID_Desc; HID_DescTypeDef HID_Desc;
HID_InterruptReportCallback ReportCallback; FreePacketCallbackTypeDef ReportCallback;
uint8_t Data[HID_MAX_REPORT_SIZE]; uint8_t Data[HID_MAX_REPORT_SIZE];
} }
HID_HandleTypeDef; 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); uint16_t fifo_write(FIFO_TypeDef * f, const void * buf, uint16_t nbytes);
HAL_StatusTypeDef USBH_HID_GetInterruptReport(USBH_HandleTypeDef *phost, HAL_StatusTypeDef USBH_HID_GetInterruptReport(USBH_HandleTypeDef *phost,
HID_InterruptReportCallback callback); FreePacketCallbackTypeDef callback);
/** /**

@ -382,7 +382,7 @@ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost)
if (urbStatus == USBH_URB_DONE) if (urbStatus == USBH_URB_DONE)
{ {
HID_Handle->ReportCallback(HID_Handle->Data); Downstream_GetFreePacket(HID_Handle->ReportCallback);
HID_Handle->state = HID_IDLE; HID_Handle->state = HID_IDLE;
break; break;
} }
@ -431,7 +431,7 @@ static USBH_StatusTypeDef USBH_HID_SOFProcess(USBH_HandleTypeDef *phost)
//Downstream_HID calls into here at main() priority, //Downstream_HID calls into here at main() priority,
//to request a new report for Upstream. //to request a new report for Upstream.
HAL_StatusTypeDef USBH_HID_GetInterruptReport(USBH_HandleTypeDef *phost, HAL_StatusTypeDef USBH_HID_GetInterruptReport(USBH_HandleTypeDef *phost,
HID_InterruptReportCallback callback) FreePacketCallbackTypeDef callback)
{ {
HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData; HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData;

@ -25,7 +25,6 @@
#define HID_MOUSE_MAX_BUTTONS 4 #define HID_MOUSE_MAX_BUTTONS 4
DownstreamPacketTypeDef* SavedPacket;
extern USBH_HandleTypeDef hUsbHostFS; //Hard-link ourselves to usb_host.c 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 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_Mouse_ParseReportDescriptor(void);
static HAL_StatusTypeDef Downstream_HID_GetNextReportItem(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; return;
} }
SavedPacket = receivedPacket; Downstream_ReleasePacket(receivedPacket);
if (USBH_HID_GetInterruptReport(&hUsbHostFS, if (USBH_HID_GetInterruptReport(&hUsbHostFS,
Downstream_HID_InterruptReportCallback) != HAL_OK) Downstream_HID_InterruptReportCallback) != HAL_OK)
{ {
Downstream_PacketProcessor_FreakOut(); 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) if (ConfiguredDeviceClass == COMMAND_CLASS_HID_MOUSE)
{ {
Downstream_HID_Mouse_ExtractDataFromReport(reportBuffer); Downstream_HID_Mouse_ExtractDataFromReport(packetToSend);
SavedPacket->Length16 = ((HID_MOUSE_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16; packetToSend->Length16 = ((HID_MOUSE_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16;
} }
//else if... //else if...
else else
@ -284,35 +282,37 @@ void Downstream_HID_InterruptReportCallback(uint8_t* reportBuffer)
return; return;
} }
Downstream_PacketProcessor_ClassReply(SavedPacket); packetToSend->CommandClass = ConfiguredDeviceClass;
packetToSend->Command = COMMAND_HID_REPORT;
Downstream_PacketProcessor_ClassReply(packetToSend);
} }
void Downstream_HID_Mouse_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend)
void Downstream_HID_Mouse_ExtractDataFromReport(uint8_t* reportBuffer)
{ {
HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData;
uint16_t readData; uint16_t readData;
//Grab the buttons //Grab the buttons
readData = *(uint16_t*)&(reportBuffer[(ReportButtonBitOffset / 8)]); readData = *(uint16_t*)&(HID_Handle->Data[(ReportButtonBitOffset / 8)]);
readData >>= (ReportButtonBitOffset % 8); readData >>= (ReportButtonBitOffset % 8);
readData &= ((1 << ReportButtonBitLength) - 1); readData &= ((1 << ReportButtonBitLength) - 1);
SavedPacket->Data[0] = readData; packetToSend->Data[0] = readData;
//Grab X //Grab X
readData = *(uint16_t*)&(reportBuffer[(ReportXBitOffset / 8)]); readData = *(uint16_t*)&(HID_Handle->Data[(ReportXBitOffset / 8)]);
readData >>= (ReportXBitOffset % 8); readData >>= (ReportXBitOffset % 8);
SavedPacket->Data[1] = (uint8_t)readData; packetToSend->Data[1] = (uint8_t)readData;
//Grab Y //Grab Y
readData = *(uint16_t*)&(reportBuffer[(ReportYBitOffset / 8)]); readData = *(uint16_t*)&(HID_Handle->Data[(ReportYBitOffset / 8)]);
readData >>= (ReportYBitOffset % 8); readData >>= (ReportYBitOffset % 8);
SavedPacket->Data[2] = (uint8_t)readData; packetToSend->Data[2] = (uint8_t)readData;
//Grab wheel //Grab wheel
readData = *(uint16_t*)&(reportBuffer[(ReportWheelBitOffset / 8)]); readData = *(uint16_t*)&(HID_Handle->Data[(ReportWheelBitOffset / 8)]);
readData >>= (ReportWheelBitOffset % 8); readData >>= (ReportWheelBitOffset % 8);
SavedPacket->Data[3] = (uint8_t)readData; packetToSend->Data[3] = (uint8_t)readData;
} }

@ -25,10 +25,12 @@
DownstreamStateTypeDef DownstreamState = STATE_DEVICE_NOT_READY; DownstreamStateTypeDef DownstreamState = STATE_DEVICE_NOT_READY;
InterfaceCommandClassTypeDef ConfiguredDeviceClass = COMMAND_CLASS_INTERFACE; InterfaceCommandClassTypeDef ConfiguredDeviceClass = COMMAND_CLASS_INTERFACE;
uint8_t NotifyDisconnectReply = 0;
void Downstream_PacketProcessor_Interface(DownstreamPacketTypeDef* receivedPacket); static void Downstream_PacketProcessor_Interface(DownstreamPacketTypeDef* receivedPacket);
void Downstream_PacketProcessor_Interface_ReplyNotifyDevice(DownstreamPacketTypeDef* replyPacket); 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). //we need to tell Upstream of the fact (and not freak out).
if (DownstreamState == STATE_DEVICE_NOT_READY) if (DownstreamState == STATE_DEVICE_NOT_READY)
{ {
receivedPacket->Length16 = DOWNSTREAM_PACKET_HEADER_LEN_16; Downstream_PacketProcessor_NotifyDisconnectReply(receivedPacket);
receivedPacket->CommandClass = COMMAND_CLASS_ERROR;
receivedPacket->Command = COMMAND_ERROR_DEVICE_DISCONNECTED;
Downstream_PacketProcessor_ClassReply(receivedPacket);
return; return;
} }
@ -172,6 +171,7 @@ void Downstream_PacketProcessor_GenericErrorReply(DownstreamPacketTypeDef* reply
Downstream_TransmitPacket(replyPacket); Downstream_TransmitPacket(replyPacket);
Downstream_ReceivePacket(Downstream_PacketProcessor); Downstream_ReceivePacket(Downstream_PacketProcessor);
NotifyDisconnectReply = 0;
} }
@ -179,6 +179,31 @@ void Downstream_PacketProcessor_ClassReply(DownstreamPacketTypeDef* replyPacket)
{ {
Downstream_TransmitPacket(replyPacket); Downstream_TransmitPacket(replyPacket);
Downstream_ReceivePacket(Downstream_PacketProcessor); 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) if (id == HOST_USER_DISCONNECTION)
{ {
DownstreamState = STATE_DEVICE_NOT_READY; DownstreamState = STATE_DEVICE_NOT_READY;
if (NotifyDisconnectReply == 1)
{
NotifyDisconnectReply = 2; //Request a 'device disconnected' reply when we get back to main()
}
return; return;
} }

@ -73,23 +73,19 @@ void SysTick_Handler(void)
void DMA2_Stream2_IRQHandler(void) void DMA2_Stream2_IRQHandler(void)
{ {
//SPI_INT_ACTIVE_ON;
HAL_DMA_IRQHandler(&hdma_spi1_rx); HAL_DMA_IRQHandler(&hdma_spi1_rx);
//SPI_INT_ACTIVE_OFF;
} }
void DMA2_Stream3_IRQHandler(void) void DMA2_Stream3_IRQHandler(void)
{ {
//SPI_INT_ACTIVE_ON;
HAL_DMA_IRQHandler(&hdma_spi1_tx); HAL_DMA_IRQHandler(&hdma_spi1_tx);
//SPI_INT_ACTIVE_OFF;
} }
void OTG_FS_IRQHandler(void) void OTG_FS_IRQHandler(void)
{ {
INT_ACTIVE_ON; //INT_ACTIVE_ON;
HAL_HCD_IRQHandler(&hhcd_USB_OTG_FS); HAL_HCD_IRQHandler(&hhcd_USB_OTG_FS);
INT_ACTIVE_OFF; //INT_ACTIVE_OFF;
} }

@ -73,6 +73,7 @@ int main(void)
{ {
USB_Host_Process(); USB_Host_Process();
Downstream_SPIProcess(); Downstream_SPIProcess();
Downstream_PacketProcessor_CheckNotifyDisconnectReply();
} }
} }

@ -20,6 +20,8 @@
#define HID_MOUSE_DATA_LEN 4 #define HID_MOUSE_DATA_LEN 4
#define HID_KEYBOARD_DATA_LEN 0 #define HID_KEYBOARD_DATA_LEN 0
#define HID_MOUSE_MAX_BUTTONS 4
UpstreamPacketTypeDef* UpstreamHidPacket = NULL; UpstreamPacketTypeDef* UpstreamHidPacket = NULL;
UpstreamHidSendReportCallback ReportCallback = NULL; UpstreamHidSendReportCallback ReportCallback = NULL;
@ -60,11 +62,6 @@ HAL_StatusTypeDef Upstream_HID_GetNextReport(UpstreamHidSendReportCallback callb
UpstreamHidPacket = NULL; UpstreamHidPacket = NULL;
} }
if (ReportCallback != NULL)
{
UPSTREAM_STATEMACHINE_FREAKOUT;
return HAL_ERROR;
}
ReportCallback = callback; ReportCallback = callback;
freePacket = Upstream_GetFreePacketImmediately(); freePacket = Upstream_GetFreePacketImmediately();
@ -124,6 +121,8 @@ void Upstream_HID_GetNextReportReceiveCallback(UpstreamPacketTypeDef* receivedPa
return; return;
} }
receivedPacket->Data[0] &= ((1 << HID_MOUSE_MAX_BUTTONS) - 1); //Limit number of buttons received
//Mouse sanity checks & stuff go here... //Mouse sanity checks & stuff go here...
dataLength = HID_MOUSE_DATA_LEN; dataLength = HID_MOUSE_DATA_LEN;

@ -150,6 +150,7 @@ void Upstream_MSC_GetCapacityReplyCallback(UpstreamPacketTypeDef* replyPacket)
if (replyPacket->Length16 != (UPSTREAM_PACKET_HEADER_LEN_16 + (8 / 2))) if (replyPacket->Length16 != (UPSTREAM_PACKET_HEADER_LEN_16 + (8 / 2)))
{ {
Upstream_ReleasePacket(replyPacket);
GetCapacityCallback(NULL, 0, 0); GetCapacityCallback(NULL, 0, 0);
return; return;
} }

Loading…
Cancel
Save