Keyboard support implemented, but not tested

pull/7/head
Robert Fisk 8 years ago
parent 34b152cce9
commit e78c526cb8

@ -42,10 +42,12 @@
#define HID_ITEM_INPUT_REL 0x06 #define HID_ITEM_INPUT_REL 0x06
typedef void (*TransactionCompleteCallbackTypeDef)(void);
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(DownstreamPacketTypeDef* packetToSend); void Downstream_HID_InterruptReportCallback(void);
void Downstream_HID_SendReportCallback(void);

@ -58,7 +58,7 @@ InterfaceCommandMscTypeDef;
typedef enum typedef enum
{ {
COMMAND_HID_GET_REPORT, //Returns HID report from device COMMAND_HID_GET_REPORT, //Returns HID report from device
COMMAND_HID_SET_REPORT //Sends HID report to device. No reply or ack expected. COMMAND_HID_SET_REPORT //Sends HID report to device. Simple ack packet contains no data.
} }
InterfaceCommandHidTypeDef; InterfaceCommandHidTypeDef;

@ -71,6 +71,7 @@ typedef void (*SpiPacketReceivedCallbackTypeDef)(DownstreamPacketTypeDef* receiv
void Downstream_InitSPI(void); void Downstream_InitSPI(void);
HAL_StatusTypeDef Downstream_GetFreePacket(FreePacketCallbackTypeDef callback); HAL_StatusTypeDef Downstream_GetFreePacket(FreePacketCallbackTypeDef callback);
DownstreamPacketTypeDef* Downstream_GetFreePacketImmediately(void);
void Downstream_ReleasePacket(DownstreamPacketTypeDef* packetToRelease); void Downstream_ReleasePacket(DownstreamPacketTypeDef* packetToRelease);
HAL_StatusTypeDef Downstream_ReceivePacket(SpiPacketReceivedCallbackTypeDef callback); HAL_StatusTypeDef Downstream_ReceivePacket(SpiPacketReceivedCallbackTypeDef callback);
HAL_StatusTypeDef Downstream_TransmitPacket(DownstreamPacketTypeDef* packetToWrite); HAL_StatusTypeDef Downstream_TransmitPacket(DownstreamPacketTypeDef* packetToWrite);

@ -23,6 +23,9 @@
* limitations under the License. * limitations under the License.
* *
****************************************************************************** ******************************************************************************
*
* Modifications by Robert Fisk
*
*/ */
/* Define to prevent recursive ----------------------------------------------*/ /* Define to prevent recursive ----------------------------------------------*/
@ -35,7 +38,7 @@
/* Includes ------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
#include "usbh_core.h" #include "usbh_core.h"
#include "downstream_spi.h" #include "downstream_hid.h"
/** @addtogroup USBH_LIB /** @addtogroup USBH_LIB
@ -105,6 +108,10 @@
#define HID_LOCAL_ITEM_TAG_STRING_MIN 0x08 #define HID_LOCAL_ITEM_TAG_STRING_MIN 0x08
#define HID_LOCAL_ITEM_TAG_STRING_MAX 0x09 #define HID_LOCAL_ITEM_TAG_STRING_MAX 0x09
#define HID_LOCAL_ITEM_TAG_DELIMITER 0x0A #define HID_LOCAL_ITEM_TAG_DELIMITER 0x0A
#define HID_REPORT_DIRECTION_IN 0x01
#define HID_REPORT_DIRECTION_OUT 0x02
/* States for HID State Machine */ /* States for HID State Machine */
@ -114,8 +121,7 @@ typedef enum
HID_IDLE, HID_IDLE,
HID_GET_DATA, HID_GET_DATA,
HID_GET_POLL, HID_GET_POLL,
HID_SET_DATA, HID_SET_DATA_POLL,
HID_SET_POLL,
HID_ERROR, HID_ERROR,
} }
HID_StateTypeDef; HID_StateTypeDef;
@ -227,7 +233,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;
FreePacketCallbackTypeDef ReportCallback; TransactionCompleteCallbackTypeDef ReportCallback;
uint8_t Data[HID_MAX_REPORT_SIZE]; uint8_t Data[HID_MAX_REPORT_SIZE];
} }
HID_HandleTypeDef; HID_HandleTypeDef;
@ -288,7 +294,8 @@ USBH_StatusTypeDef USBH_HID_SetReport (USBH_HandleTypeDef *phost,
uint8_t reportType, uint8_t reportType,
uint8_t reportId, uint8_t reportId,
uint8_t* reportBuff, uint8_t* reportBuff,
uint8_t reportLen); uint8_t reportLen,
TransactionCompleteCallbackTypeDef callback);
USBH_StatusTypeDef USBH_HID_GetReport (USBH_HandleTypeDef *phost, USBH_StatusTypeDef USBH_HID_GetReport (USBH_HandleTypeDef *phost,
uint8_t reportType, uint8_t reportType,
@ -322,7 +329,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,
FreePacketCallbackTypeDef callback); TransactionCompleteCallbackTypeDef callback);
/** /**

@ -373,17 +373,17 @@ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost)
HID_Handle->Data, HID_Handle->Data,
HID_Handle->length, HID_Handle->length,
HID_Handle->InPipe); HID_Handle->InPipe);
HID_Handle->state = HID_GET_POLL; HID_Handle->state = HID_GET_POLL;
HID_Handle->timer = phost->Timer; HID_Handle->timer = phost->Timer;
} }
break; break;
case HID_GET_POLL: case HID_GET_POLL:
urbStatus = USBH_LL_GetURBState(phost, HID_Handle->InPipe); urbStatus = USBH_LL_GetURBState(phost, HID_Handle->InPipe);
if (urbStatus == USBH_URB_DONE) if (urbStatus == USBH_URB_DONE)
{ {
Downstream_GetFreePacket(HID_Handle->ReportCallback); HID_Handle->ReportCallback();
HID_Handle->state = HID_IDLE; HID_Handle->state = HID_IDLE;
break; break;
} }
@ -405,15 +405,14 @@ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost)
} }
break; break;
case HID_SET_DATA: case HID_SET_DATA_POLL:
if (USBH_CtlReq(phost, HID_Handle->Data, phost->Control.setup.b.wLength.w) == USBH_OK)
break; {
HID_Handle->ReportCallback();
case HID_SET_POLL: HID_Handle->state = HID_IDLE;
}
break; break;
case HID_IDLE: case HID_IDLE:
break; break;
@ -441,7 +440,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,
FreePacketCallbackTypeDef callback) TransactionCompleteCallbackTypeDef callback)
{ {
HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData; HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData;
@ -452,7 +451,8 @@ HAL_StatusTypeDef USBH_HID_GetInterruptReport(USBH_HandleTypeDef *phost,
return HAL_OK; return HAL_OK;
} }
return HAL_ERROR; //return HAL_ERROR;
while (1);
} }
@ -533,16 +533,18 @@ USBH_StatusTypeDef USBH_HID_SetIdle (USBH_HandleTypeDef *phost,
uint8_t duration, uint8_t duration,
uint8_t reportId) uint8_t reportId)
{ {
if (phost->RequestState == CMD_SEND)
phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\ {
USB_REQ_TYPE_CLASS; phost->Control.setup.b.bmRequestType = USB_H2D |
USB_REQ_RECIPIENT_INTERFACE |
USB_REQ_TYPE_CLASS;
phost->Control.setup.b.bRequest = USB_HID_SET_IDLE;
phost->Control.setup.b.wValue.w = (duration << 8 ) | reportId; phost->Control.setup.b.bRequest = USB_HID_SET_IDLE;
phost->Control.setup.b.wValue.w = (duration << 8 ) | reportId;
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = 0; phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = 0;
}
return USBH_CtlReq(phost, 0 , 0 ); return USBH_CtlReq(phost, 0 , 0 );
} }
@ -562,20 +564,41 @@ USBH_StatusTypeDef USBH_HID_SetReport (USBH_HandleTypeDef *phost,
uint8_t reportType, uint8_t reportType,
uint8_t reportId, uint8_t reportId,
uint8_t* reportBuff, uint8_t* reportBuff,
uint8_t reportLen) uint8_t reportLen,
TransactionCompleteCallbackTypeDef callback)
{ {
HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData;
uint32_t i;
if (phost->RequestState == CMD_SEND)
{
if ((HID_Handle->state != HID_IDLE) ||
(reportLen > HID_MAX_REPORT_SIZE))
{
while (1);
}
HID_Handle->ReportCallback = callback;
HID_Handle->state = HID_SET_DATA_POLL;
for (i = 0; i < reportLen; i++)
{
HID_Handle->Data[i] = *reportBuff;
reportBuff++;
}
phost->Control.setup.b.bmRequestType = USB_H2D |
USB_REQ_RECIPIENT_INTERFACE |
USB_REQ_TYPE_CLASS;
phost->Control.setup.b.bRequest = USB_HID_SET_REPORT;
phost->Control.setup.b.wValue.w = (reportType << 8 ) | reportId;
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = reportLen;
}
phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\ //return USBH_CtlReq(phost, reportBuff, reportLen);
USB_REQ_TYPE_CLASS; return USBH_OK;
phost->Control.setup.b.bRequest = USB_HID_SET_REPORT;
phost->Control.setup.b.wValue.w = (reportType << 8 ) | reportId;
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = reportLen;
return USBH_CtlReq(phost, reportBuff , reportLen );
} }
@ -595,17 +618,19 @@ USBH_StatusTypeDef USBH_HID_GetReport (USBH_HandleTypeDef *phost,
uint8_t* reportBuff, uint8_t* reportBuff,
uint8_t reportLen) uint8_t reportLen)
{ {
if (phost->RequestState == CMD_SEND)
phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_RECIPIENT_INTERFACE |\ {
USB_REQ_TYPE_CLASS; phost->Control.setup.b.bmRequestType = USB_D2H |
USB_REQ_RECIPIENT_INTERFACE |
USB_REQ_TYPE_CLASS;
phost->Control.setup.b.bRequest = USB_HID_GET_REPORT;
phost->Control.setup.b.wValue.w = (reportType << 8 ) | reportId; phost->Control.setup.b.bRequest = USB_HID_GET_REPORT;
phost->Control.setup.b.wValue.w = (reportType << 8 ) | reportId;
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = reportLen; phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = reportLen;
}
return USBH_CtlReq(phost, reportBuff , reportLen ); return USBH_CtlReq(phost, reportBuff , reportLen );
} }
@ -619,16 +644,17 @@ USBH_StatusTypeDef USBH_HID_GetReport (USBH_HandleTypeDef *phost,
USBH_StatusTypeDef USBH_HID_SetProtocol(USBH_HandleTypeDef *phost, USBH_StatusTypeDef USBH_HID_SetProtocol(USBH_HandleTypeDef *phost,
uint8_t protocol) uint8_t protocol)
{ {
if (phost->RequestState == CMD_SEND)
{
phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\ phost->Control.setup.b.bmRequestType = USB_H2D |
USB_REQ_TYPE_CLASS; USB_REQ_RECIPIENT_INTERFACE |\
USB_REQ_TYPE_CLASS;
phost->Control.setup.b.bRequest = USB_HID_SET_PROTOCOL; phost->Control.setup.b.bRequest = USB_HID_SET_PROTOCOL;
phost->Control.setup.b.wValue.w = protocol == 0 ? 0 : 1; phost->Control.setup.b.wValue.w = protocol == 0 ? 0 : 1;
phost->Control.setup.b.wIndex.w = 0; phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = 0; phost->Control.setup.b.wLength.w = 0;
}
return USBH_CtlReq(phost, 0 , 0 ); return USBH_CtlReq(phost, 0 , 0 );

@ -58,14 +58,17 @@ USBH_HandleTypeDef *Callback_MSC_phost;
*/ */
USBH_StatusTypeDef USBH_MSC_BOT_REQ_Reset(USBH_HandleTypeDef *phost) USBH_StatusTypeDef USBH_MSC_BOT_REQ_Reset(USBH_HandleTypeDef *phost)
{ {
if (phost->RequestState == CMD_SEND)
phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_TYPE_CLASS | \ {
USB_REQ_RECIPIENT_INTERFACE; phost->Control.setup.b.bmRequestType = USB_H2D |
USB_REQ_TYPE_CLASS |
phost->Control.setup.b.bRequest = USB_REQ_BOT_RESET; USB_REQ_RECIPIENT_INTERFACE;
phost->Control.setup.b.wValue.w = 0;
phost->Control.setup.b.wIndex.w = 0; phost->Control.setup.b.bRequest = USB_REQ_BOT_RESET;
phost->Control.setup.b.wLength.w = 0; phost->Control.setup.b.wValue.w = 0;
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = 0;
}
return USBH_CtlReq(phost, 0 , 0 ); return USBH_CtlReq(phost, 0 , 0 );
} }
@ -79,13 +82,17 @@ USBH_StatusTypeDef USBH_MSC_BOT_REQ_Reset(USBH_HandleTypeDef *phost)
*/ */
USBH_StatusTypeDef USBH_MSC_BOT_REQ_GetMaxLUN(USBH_HandleTypeDef *phost, uint8_t *Maxlun) USBH_StatusTypeDef USBH_MSC_BOT_REQ_GetMaxLUN(USBH_HandleTypeDef *phost, uint8_t *Maxlun)
{ {
phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_TYPE_CLASS | \ if (phost->RequestState == CMD_SEND)
USB_REQ_RECIPIENT_INTERFACE; {
phost->Control.setup.b.bmRequestType = USB_D2H |
phost->Control.setup.b.bRequest = USB_REQ_GET_MAX_LUN; USB_REQ_TYPE_CLASS |
phost->Control.setup.b.wValue.w = 0; USB_REQ_RECIPIENT_INTERFACE;
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = 1; phost->Control.setup.b.bRequest = USB_REQ_GET_MAX_LUN;
phost->Control.setup.b.wValue.w = 0;
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = 1;
}
return USBH_CtlReq(phost, Maxlun , 1 ); return USBH_CtlReq(phost, Maxlun , 1 );
} }

@ -56,6 +56,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(DownstreamPacketTypeDef* packetToSend); static void Downstream_HID_Mouse_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend);
static void Downstream_HID_Keyboard_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend);
static uint8_t Downstream_HID_Mouse_Extract8BitValue(HID_HandleTypeDef* hidHandle, static uint8_t Downstream_HID_Mouse_Extract8BitValue(HID_HandleTypeDef* hidHandle,
uint8_t valueBitOffset, uint8_t valueBitOffset,
uint8_t valueBitLength); uint8_t valueBitLength);
@ -84,7 +85,7 @@ InterfaceCommandClassTypeDef Downstream_HID_ApproveConnectedDevice(void)
HAL_StatusTypeDef Downstream_HID_Mouse_ParseReportDescriptor(void) static HAL_StatusTypeDef Downstream_HID_Mouse_ParseReportDescriptor(void)
{ {
uint32_t currentReportBitIndex = 0; uint32_t currentReportBitIndex = 0;
uint8_t currentUsagePage = 0; uint8_t currentUsagePage = 0;
@ -242,7 +243,7 @@ HAL_StatusTypeDef Downstream_HID_Mouse_ParseReportDescriptor(void)
//Retrieves the next item in the HID report, and at most one of its associated data bytes. //Retrieves the next item in the HID report, and at most one of its associated data bytes.
//Then it updates ReportDataPointer based on the actual length of the retrieved item. //Then it updates ReportDataPointer based on the actual length of the retrieved item.
HAL_StatusTypeDef Downstream_HID_GetNextReportItem(void) static HAL_StatusTypeDef Downstream_HID_GetNextReportItem(void)
{ {
HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData;
uint32_t itemLength; uint32_t itemLength;
@ -287,9 +288,22 @@ void Downstream_HID_PacketProcessor(DownstreamPacketTypeDef* receivedPacket)
Downstream_PacketProcessor_NotifyDisconnectReplyRequired(); Downstream_PacketProcessor_NotifyDisconnectReplyRequired();
} }
if (receivedPacket->Command == COMMAND_HID_SET_REPORT) else 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) ||
((receivedPacket->Data[0] & ~((1 << HID_KEYBOARD_MAX_LED) - 1)) != 0))
{
Downstream_PacketProcessor_FreakOut();
}
USBH_HID_SetReport(&hUsbHostFS,
HID_REPORT_DIRECTION_OUT,
0,
receivedPacket->Data,
HID_KEYBOARD_OUTPUT_DATA_LEN,
Downstream_HID_SendReportCallback);
Downstream_ReleasePacket(receivedPacket);
Downstream_PacketProcessor_NotifyDisconnectReplyRequired();
} }
//else: //else:
@ -297,17 +311,20 @@ void Downstream_HID_PacketProcessor(DownstreamPacketTypeDef* receivedPacket)
} }
void Downstream_HID_InterruptReportCallback(DownstreamPacketTypeDef* packetToSend) void Downstream_HID_InterruptReportCallback(void)
{ {
DownstreamPacketTypeDef* freePacket;
freePacket = Downstream_GetFreePacketImmediately();
if (ConfiguredDeviceClass == COMMAND_CLASS_HID_MOUSE) if (ConfiguredDeviceClass == COMMAND_CLASS_HID_MOUSE)
{ {
Downstream_HID_Mouse_ExtractDataFromReport(packetToSend); Downstream_HID_Mouse_ExtractDataFromReport(freePacket);
packetToSend->Length16 = ((HID_MOUSE_INPUT_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16; freePacket->Length16 = ((HID_MOUSE_INPUT_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16;
} }
else if (ConfiguredDeviceClass == COMMAND_CLASS_HID_KEYBOARD) else if (ConfiguredDeviceClass == COMMAND_CLASS_HID_KEYBOARD)
{ {
Downstream_HID_Keyboard_ExtractDataFromReport(packetToSend); Downstream_HID_Keyboard_ExtractDataFromReport(freePacket);
packetToSend->Length16 = ((HID_KEYBOARD_INPUT_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16; freePacket->Length16 = ((HID_KEYBOARD_INPUT_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16;
} }
//else if... //else if...
@ -317,13 +334,13 @@ void Downstream_HID_InterruptReportCallback(DownstreamPacketTypeDef* packetToSen
return; return;
} }
packetToSend->CommandClass = ConfiguredDeviceClass; freePacket->CommandClass = ConfiguredDeviceClass;
packetToSend->Command = COMMAND_HID_GET_REPORT; freePacket->Command = COMMAND_HID_GET_REPORT;
Downstream_PacketProcessor_ClassReply(packetToSend); Downstream_PacketProcessor_ClassReply(freePacket);
} }
void Downstream_HID_Mouse_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend) static void Downstream_HID_Mouse_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend)
{ {
HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData;
uint32_t readData; uint32_t readData;
@ -348,9 +365,9 @@ void Downstream_HID_Mouse_ExtractDataFromReport(DownstreamPacketTypeDef* packetT
uint8_t Downstream_HID_Mouse_Extract8BitValue(HID_HandleTypeDef* hidHandle, static uint8_t Downstream_HID_Mouse_Extract8BitValue(HID_HandleTypeDef* hidHandle,
uint8_t valueBitOffset, uint8_t valueBitOffset,
uint8_t valueBitLength) uint8_t valueBitLength)
{ {
int32_t readData; int32_t readData;
@ -371,7 +388,7 @@ uint8_t Downstream_HID_Mouse_Extract8BitValue(HID_HandleTypeDef* hidHandle,
void Downstream_HID_Keyboard_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend) static void Downstream_HID_Keyboard_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend)
{ {
HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData;
uint32_t i; uint32_t i;
@ -392,3 +409,14 @@ void Downstream_HID_Keyboard_ExtractDataFromReport(DownstreamPacketTypeDef* pack
} }
void Downstream_HID_SendReportCallback(void)
{
DownstreamPacketTypeDef* freePacket;
freePacket = Downstream_GetFreePacketImmediately();
freePacket->CommandClass = ConfiguredDeviceClass;
freePacket->Command = COMMAND_HID_SET_REPORT;
Downstream_PacketProcessor_ClassReply(freePacket);
}

@ -92,6 +92,33 @@ HAL_StatusTypeDef Downstream_GetFreePacket(FreePacketCallbackTypeDef callback)
} }
DownstreamPacketTypeDef* Downstream_GetFreePacketImmediately(void)
{
if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR)
{
return NULL;
}
//We are expecting a free buffer now
if (DownstreamPacket0.Busy == NOT_BUSY)
{
DownstreamPacket0.Busy = BUSY;
return &DownstreamPacket0;
}
if (DownstreamPacket1.Busy == NOT_BUSY)
{
DownstreamPacket1.Busy = BUSY;
return &DownstreamPacket1;
}
//Should not happen:
DOWNSTREAM_SPI_FREAKOUT;
return NULL;
}
//Used by Downstream state machine and USB host classes. //Used by Downstream state machine and USB host classes.
void Downstream_ReleasePacket(DownstreamPacketTypeDef* packetToRelease) void Downstream_ReleasePacket(DownstreamPacketTypeDef* packetToRelease)
{ {

@ -10,7 +10,6 @@
*/ */
#include <downstream_hid.h>
#include "downstream_statemachine.h" #include "downstream_statemachine.h"
#include "downstream_interface_def.h" #include "downstream_interface_def.h"
#include "downstream_spi.h" #include "downstream_spi.h"

@ -29,10 +29,16 @@
#define HID_KEYBOARD_MAX_LED 3 #define HID_KEYBOARD_MAX_LED 3
typedef uint8_t (*UpstreamHidGetReportCallback)(uint8_t *report, typedef enum
uint16_t len); {
KEYBOARD_OUT_STATE_IDLE,
KEYBOARD_OUT_STATE_DATA_READY,
KEYBOARD_OUT_STATE_BUSY
} KeyboardOutStateTypeDef;
typedef uint8_t (*UpstreamHidGetReportCallback)(uint8_t *report,
uint16_t len);
void Upstream_HID_DeInit(void); void Upstream_HID_DeInit(void);
void Upstream_HID_GetNextInterruptReport(UpstreamHidGetReportCallback callback); void Upstream_HID_GetNextInterruptReport(UpstreamHidGetReportCallback callback);

@ -60,7 +60,7 @@ InterfaceCommandMscTypeDef;
typedef enum typedef enum
{ {
COMMAND_HID_GET_REPORT, //Returns HID report from device COMMAND_HID_GET_REPORT, //Returns HID report from device
COMMAND_HID_SET_REPORT //Sends HID report to device. No reply or ack expected. COMMAND_HID_SET_REPORT //Sends HID report to device. Simple ack packet contains no data.
} }
InterfaceCommandHidTypeDef; InterfaceCommandHidTypeDef;

@ -19,8 +19,8 @@
UpstreamPacketTypeDef* UpstreamHidPacket = NULL; UpstreamPacketTypeDef* UpstreamHidPacket = NULL;
UpstreamHidGetReportCallback GetReportCallback = NULL; UpstreamHidGetReportCallback GetReportCallback = NULL;
uint8_t KeyboardOutDataAvailable = 0; KeyboardOutStateTypeDef KeyboardOutDataState = KEYBOARD_OUT_STATE_IDLE;
uint8_t KeyboardOutData[HID_KEYBOARD_OUTPUT_DATA_LEN]; uint8_t KeyboardOutData[HID_KEYBOARD_OUTPUT_DATA_LEN];
@ -36,7 +36,7 @@ void Upstream_HID_DeInit(void)
UpstreamHidPacket = NULL; UpstreamHidPacket = NULL;
} }
GetReportCallback = NULL; GetReportCallback = NULL;
KeyboardOutDataAvailable = 0; KeyboardOutDataState = KEYBOARD_OUT_STATE_IDLE;
} }
@ -54,11 +54,31 @@ void Upstream_HID_GetNextInterruptReport(UpstreamHidGetReportCallback callback)
return; return;
} }
//Just return if we already have an outstanding request if (callback != NULL)
if (GetReportCallback != NULL)
{ {
return; //This means we were called by the host (normal operation)
if (KeyboardOutDataState == KEYBOARD_OUT_STATE_BUSY)
{
//Just save the callback, because we are still waiting for the OUT report to complete
GetReportCallback = callback;
return;
}
if (GetReportCallback != NULL)
{
//Just return if we already have an outstanding request
return;
}
}
else
{
//This means were called on OUT report completion
if (GetReportCallback == NULL)
{
//The host has not given us the callback yet, so we give up
return;
}
} }
GetReportCallback = callback; GetReportCallback = callback;
//Release packet used for last transaction (if any) //Release packet used for last transaction (if any)
@ -175,7 +195,7 @@ void Upstream_HID_GetNextInterruptReportReceiveCallback(UpstreamPacketTypeDef* r
//Check if we need to send OUT data to the keyboard before requesting next Interrupt IN data //Check if we need to send OUT data to the keyboard before requesting next Interrupt IN data
if (KeyboardOutDataAvailable) if (KeyboardOutDataState == KEYBOARD_OUT_STATE_DATA_READY)
{ {
Upstream_HID_ReallySendControlReport(); Upstream_HID_ReallySendControlReport();
} }
@ -203,7 +223,7 @@ void Upstream_HID_SendControlReport(UpstreamPacketTypeDef* packetToSend, uint8_t
} }
//Save data until after the next interrupt data is received from Downstream //Save data until after the next interrupt data is received from Downstream
KeyboardOutDataAvailable = 1; KeyboardOutDataState = KEYBOARD_OUT_STATE_DATA_READY;
for (i = 0; i < HID_KEYBOARD_OUTPUT_DATA_LEN; i++) for (i = 0; i < HID_KEYBOARD_OUTPUT_DATA_LEN; i++)
{ {
KeyboardOutData[i] = packetToSend->Data[i]; KeyboardOutData[i] = packetToSend->Data[i];
@ -217,7 +237,7 @@ void Upstream_HID_ReallySendControlReport(void)
UpstreamPacketTypeDef* freePacket; UpstreamPacketTypeDef* freePacket;
uint32_t i; uint32_t i;
KeyboardOutDataAvailable = 0; KeyboardOutDataState = KEYBOARD_OUT_STATE_BUSY;
freePacket = Upstream_GetFreePacketImmediately(); freePacket = Upstream_GetFreePacketImmediately();
if (freePacket == NULL) return; if (freePacket == NULL) return;
@ -232,10 +252,39 @@ void Upstream_HID_ReallySendControlReport(void)
} }
freePacket->Data[0] &= ((1 << HID_KEYBOARD_MAX_LED) - 1); freePacket->Data[0] &= ((1 << HID_KEYBOARD_MAX_LED) - 1);
if (Upstream_TransmitPacket(freePacket) != HAL_OK) if (Upstream_TransmitPacket(freePacket) == HAL_OK)
{
Upstream_ReceivePacket(Upstream_HID_GetNextInterruptReportReceiveCallback);
}
else
{ {
Upstream_ReleasePacket(freePacket); Upstream_ReleasePacket(freePacket);
} }
} }
void Upstream_HID_ReallySendControlReportReceiveCallback(UpstreamPacketTypeDef* receivedPacket)
{
InterfaceCommandClassTypeDef activeClass;
activeClass = Upstream_StateMachine_CheckActiveClass();
if (activeClass != COMMAND_CLASS_HID_KEYBOARD) //add classes here
{
UPSTREAM_STATEMACHINE_FREAKOUT;
return;
}
if (receivedPacket == NULL)
{
return; //Just give up...
}
Upstream_ReleasePacket(receivedPacket);
KeyboardOutDataState = KEYBOARD_OUT_STATE_IDLE;
//If upstream host has already requested the next IN report data,
//this will send the request downstream.
Upstream_HID_GetNextInterruptReport(NULL);
}

Loading…
Cancel
Save