Bugfixes for keyboard support: works!!!

USG_1.0
Robert Fisk 8 years ago
parent bc2bf01cbe
commit c68151698b

@ -15,9 +15,23 @@
#include "downstream_interface_def.h"
#include "downstream_spi.h"
#include "usbh_def.h"
#define HID_MAX_REPORT_LEN 8
//These defines are duplicated in upstream_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 //Also set in Upstream's HID report descriptor
#define HID_KEYBOARD_MAX_LED 3
//Stuff for parsing HID descriptors:
#define HID_ITEM_LONG 0xFE
#define HID_ITEM_LENGTH_MASK 0x03
@ -42,12 +56,12 @@
#define HID_ITEM_INPUT_REL 0x06
typedef void (*TransactionCompleteCallbackTypeDef)(void);
typedef void (*TransactionCompleteCallbackTypeDef)(USBH_StatusTypeDef result);
InterfaceCommandClassTypeDef Downstream_HID_ApproveConnectedDevice(void);
void Downstream_HID_PacketProcessor(DownstreamPacketTypeDef* receivedPacket);
void Downstream_HID_InterruptReportCallback(void);
void Downstream_HID_SendReportCallback(void);
void Downstream_HID_InterruptReportCallback(USBH_StatusTypeDef result);
void Downstream_HID_SendReportCallback(USBH_StatusTypeDef result);

@ -365,6 +365,9 @@ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost)
HID_Handle->timer = phost->Timer;
HID_Handle->state = HID_IDLE;
break;
case HID_IDLE:
break;
case HID_GET_DATA:
if ((int32_t)(phost->Timer - HID_Handle->timer) >= HID_Handle->poll)
@ -383,14 +386,15 @@ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost)
if (urbStatus == USBH_URB_DONE)
{
HID_Handle->ReportCallback();
HID_Handle->ReportCallback(USBH_OK);
HID_Handle->state = HID_IDLE;
break;
}
if (urbStatus == USBH_URB_NOTREADY)
{
HID_Handle->state = HID_GET_DATA;
HID_Handle->ReportCallback(USBH_BUSY);
HID_Handle->state = HID_IDLE;
break;
}
@ -400,7 +404,8 @@ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost)
if(USBH_ClrFeature(phost,
HID_Handle->ep_addr) == USBH_OK)
{
HID_Handle->state = HID_GET_DATA;
HID_Handle->ReportCallback(USBH_BUSY);
HID_Handle->state = HID_IDLE;
}
}
break;
@ -408,14 +413,10 @@ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost)
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->ReportCallback(USBH_OK);
HID_Handle->state = HID_IDLE;
}
break;
case HID_IDLE:
break;
default:
break;

@ -17,21 +17,6 @@
#include "stm32f4xx_hal.h"
#define HID_MAX_REPORT_LEN 8
//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
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
@ -286,9 +271,10 @@ void Downstream_HID_PacketProcessor(DownstreamPacketTypeDef* receivedPacket)
Downstream_PacketProcessor_FreakOut();
}
Downstream_PacketProcessor_NotifyDisconnectReplyRequired();
return;
}
else if (receivedPacket->Command == COMMAND_HID_SET_REPORT)
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) ||
@ -304,6 +290,7 @@ void Downstream_HID_PacketProcessor(DownstreamPacketTypeDef* receivedPacket)
Downstream_HID_SendReportCallback);
Downstream_ReleasePacket(receivedPacket);
Downstream_PacketProcessor_NotifyDisconnectReplyRequired();
return;
}
//else:
@ -311,27 +298,37 @@ void Downstream_HID_PacketProcessor(DownstreamPacketTypeDef* receivedPacket)
}
void Downstream_HID_InterruptReportCallback(void)
void Downstream_HID_InterruptReportCallback(USBH_StatusTypeDef result)
{
DownstreamPacketTypeDef* freePacket;
freePacket = Downstream_GetFreePacketImmediately();
if (ConfiguredDeviceClass == COMMAND_CLASS_HID_MOUSE)
{
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)
if (result == USBH_OK)
{
Downstream_HID_Keyboard_ExtractDataFromReport(freePacket);
freePacket->Length16 = ((HID_KEYBOARD_INPUT_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16;
}
//else if...
//Data received from device
if (ConfiguredDeviceClass == COMMAND_CLASS_HID_MOUSE)
{
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(freePacket);
freePacket->Length16 = ((HID_KEYBOARD_INPUT_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16;
}
//else if...
else
{
Downstream_PacketProcessor_FreakOut();
return;
}
}
else
{
Downstream_PacketProcessor_FreakOut();
return;
//NAK received from device, return zero-length packet
freePacket->Length16 = DOWNSTREAM_PACKET_HEADER_LEN_16;
}
freePacket->CommandClass = ConfiguredDeviceClass;
@ -410,11 +407,12 @@ static void Downstream_HID_Keyboard_ExtractDataFromReport(DownstreamPacketTypeDe
void Downstream_HID_SendReportCallback(void)
void Downstream_HID_SendReportCallback(USBH_StatusTypeDef result)
{
DownstreamPacketTypeDef* freePacket;
freePacket = Downstream_GetFreePacketImmediately();
freePacket->Length16 = DOWNSTREAM_PACKET_HEADER_LEN_16;
freePacket->CommandClass = ConfiguredDeviceClass;
freePacket->Command = COMMAND_HID_SET_REPORT;
Downstream_PacketProcessor_ClassReply(freePacket);

@ -25,6 +25,7 @@ uint8_t KeyboardOutData[HID_KEYBOARD_OUTPUT_DATA_LEN];
void Upstream_HID_GetNextInterruptReportReceiveCallback(UpstreamPacketTypeDef* receivedPacket);
void Upstream_HID_ReallySendControlReportReceiveCallback(UpstreamPacketTypeDef* receivedPacket);
@ -56,7 +57,14 @@ void Upstream_HID_GetNextInterruptReport(UpstreamHidGetReportCallback callback)
if (callback != NULL)
{
//This means we were called by the host (normal operation)
//This means we were called by the host
//Release packet used for last transaction (if any)
if (UpstreamHidPacket != NULL)
{
Upstream_ReleasePacket(UpstreamHidPacket);
UpstreamHidPacket = NULL;
}
if (KeyboardOutDataState == KEYBOARD_OUT_STATE_BUSY)
{
//Just save the callback, because we are still waiting for the OUT report to complete
@ -68,10 +76,11 @@ void Upstream_HID_GetNextInterruptReport(UpstreamHidGetReportCallback callback)
//Just return if we already have an outstanding request
return;
}
GetReportCallback = callback;
}
else
{
//This means were called on OUT report completion
//This means were called on OUT report completion, or retrying after a downstream NAK
if (GetReportCallback == NULL)
{
//The host has not given us the callback yet, so we give up
@ -79,15 +88,6 @@ void Upstream_HID_GetNextInterruptReport(UpstreamHidGetReportCallback callback)
}
}
GetReportCallback = callback;
//Release packet used for last transaction (if any)
if (UpstreamHidPacket != NULL)
{
Upstream_ReleasePacket(UpstreamHidPacket);
UpstreamHidPacket = NULL;
}
freePacket = Upstream_GetFreePacketImmediately();
if (freePacket == NULL)
{
@ -138,6 +138,24 @@ void Upstream_HID_GetNextInterruptReportReceiveCallback(UpstreamPacketTypeDef* r
return; //Just give up...
}
if (receivedPacket->Length16 == UPSTREAM_PACKET_HEADER_LEN_16)
{
//Zero-length reply indicates no data from downstream device
Upstream_ReleasePacket(receivedPacket);
//Check if we need to send OUT data to the keyboard before requesting next Interrupt IN data
if (KeyboardOutDataState == KEYBOARD_OUT_STATE_DATA_READY)
{
Upstream_HID_ReallySendControlReport();
}
else
{
//Otherwise poll downstream again
Upstream_HID_GetNextInterruptReport(NULL);
}
return;
}
if (activeClass == COMMAND_CLASS_HID_MOUSE)
{
@ -193,7 +211,6 @@ void Upstream_HID_GetNextInterruptReportReceiveCallback(UpstreamPacketTypeDef* r
GetReportCallback = NULL;
tempReportCallback(receivedPacket->Data, dataLength);
//Check if we need to send OUT data to the keyboard before requesting next Interrupt IN data
if (KeyboardOutDataState == KEYBOARD_OUT_STATE_DATA_READY)
{
@ -254,7 +271,7 @@ void Upstream_HID_ReallySendControlReport(void)
if (Upstream_TransmitPacket(freePacket) == HAL_OK)
{
Upstream_ReceivePacket(Upstream_HID_GetNextInterruptReportReceiveCallback);
Upstream_ReceivePacket(Upstream_HID_ReallySendControlReportReceiveCallback);
}
else
{

Loading…
Cancel
Save