Incomplete and untested implementation of keyboard support

USG_1.0
Robert Fisk 8 years ago
parent 5c18898611
commit 9b2b8972a4

@ -57,7 +57,8 @@ InterfaceCommandMscTypeDef;
typedef enum typedef enum
{ {
COMMAND_HID_REPORT, //Returns HID report COMMAND_HID_GET_REPORT, //Returns HID report from device
COMMAND_HID_SET_REPORT //Sends HID report to device. No reply or ack expected.
} }
InterfaceCommandHidTypeDef; InterfaceCommandHidTypeDef;

@ -113,8 +113,9 @@ typedef enum
HID_INIT= 0, HID_INIT= 0,
HID_IDLE, HID_IDLE,
HID_GET_DATA, HID_GET_DATA,
HID_SYNC, HID_GET_POLL,
HID_POLL, HID_SET_DATA,
HID_SET_POLL,
HID_ERROR, HID_ERROR,
} }
HID_StateTypeDef; HID_StateTypeDef;

@ -327,8 +327,10 @@ static USBH_StatusTypeDef USBH_HID_ClassRequest(USBH_HandleTypeDef *phost)
break; break;
case HID_REQ_SET_PROTOCOL: case HID_REQ_SET_PROTOCOL:
/* set protocol */ //Mouse in 'report' mode,
if (USBH_HID_SetProtocol (phost, 1) == USBH_OK) //Keyboard in 'boot' mode
if (USBH_HID_SetProtocol(phost,
(HID_Handle->Protocol == HID_MOUSE_BOOT_CODE ? 1 : 0)) == USBH_OK)
{ {
HID_Handle->ctl_state = HID_REQ_IDLE; HID_Handle->ctl_state = HID_REQ_IDLE;
@ -372,12 +374,11 @@ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost)
HID_Handle->length, HID_Handle->length,
HID_Handle->InPipe); HID_Handle->InPipe);
HID_Handle->state = HID_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_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)
@ -404,6 +405,15 @@ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost)
} }
break; break;
case HID_SET_DATA:
break;
case HID_SET_POLL:
break;
case HID_IDLE: case HID_IDLE:
break; break;

@ -18,11 +18,17 @@
#define HID_MAX_REPORT_LEN 8 #define HID_MAX_REPORT_LEN 8
#define HID_MOUSE_DATA_LEN 4
#define HID_KEYBOARD_DATA_LEN 0
#define HID_MOUSE_MAX_BUTTONS 4 //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
@ -59,17 +65,21 @@ InterfaceCommandClassTypeDef Downstream_HID_ApproveConnectedDevice(void)
{ {
HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData;
if (HID_Handle->Protocol != HID_MOUSE_BOOT_CODE) if (HID_Handle->Protocol == HID_MOUSE_BOOT_CODE)
{ {
return COMMAND_CLASS_INTERFACE; //fail if (Downstream_HID_Mouse_ParseReportDescriptor() == HAL_OK)
{
return COMMAND_CLASS_HID_MOUSE; //success!
}
} }
if (Downstream_HID_Mouse_ParseReportDescriptor() != HAL_OK) if (HID_Handle->Protocol == HID_KEYBRD_BOOT_CODE)
{ {
return COMMAND_CLASS_INTERFACE; //fail return COMMAND_CLASS_HID_KEYBOARD; //success!
} }
return COMMAND_CLASS_HID_MOUSE; //success! //else:
return COMMAND_CLASS_INTERFACE; //fail
} }
@ -266,19 +276,24 @@ HAL_StatusTypeDef Downstream_HID_GetNextReportItem(void)
void Downstream_HID_PacketProcessor(DownstreamPacketTypeDef* receivedPacket) void Downstream_HID_PacketProcessor(DownstreamPacketTypeDef* receivedPacket)
{ {
if (receivedPacket->Command != COMMAND_HID_REPORT) if (receivedPacket->Command == COMMAND_HID_GET_REPORT)
{ {
Downstream_PacketProcessor_FreakOut(); Downstream_ReleasePacket(receivedPacket);
return; if (USBH_HID_GetInterruptReport(&hUsbHostFS,
Downstream_HID_InterruptReportCallback) != HAL_OK)
{
Downstream_PacketProcessor_FreakOut();
}
Downstream_PacketProcessor_NotifyDisconnectReplyRequired();
} }
Downstream_ReleasePacket(receivedPacket); if (receivedPacket->Command == COMMAND_HID_SET_REPORT)
if (USBH_HID_GetInterruptReport(&hUsbHostFS,
Downstream_HID_InterruptReportCallback) != HAL_OK)
{ {
Downstream_PacketProcessor_FreakOut();
} }
Downstream_PacketProcessor_NotifyDisconnectReplyRequired();
//else:
Downstream_PacketProcessor_FreakOut();
} }
@ -287,9 +302,15 @@ void Downstream_HID_InterruptReportCallback(DownstreamPacketTypeDef* packetToSen
if (ConfiguredDeviceClass == COMMAND_CLASS_HID_MOUSE) if (ConfiguredDeviceClass == COMMAND_CLASS_HID_MOUSE)
{ {
Downstream_HID_Mouse_ExtractDataFromReport(packetToSend); Downstream_HID_Mouse_ExtractDataFromReport(packetToSend);
packetToSend->Length16 = ((HID_MOUSE_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16; packetToSend->Length16 = ((HID_MOUSE_INPUT_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16;
}
else if (ConfiguredDeviceClass == COMMAND_CLASS_HID_KEYBOARD)
{
Downstream_HID_Keyboard_ExtractDataFromReport(packetToSend);
packetToSend->Length16 = ((HID_KEYBOARD_INPUT_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16;
} }
//else if... //else if...
else else
{ {
Downstream_PacketProcessor_FreakOut(); Downstream_PacketProcessor_FreakOut();
@ -297,7 +318,7 @@ void Downstream_HID_InterruptReportCallback(DownstreamPacketTypeDef* packetToSen
} }
packetToSend->CommandClass = ConfiguredDeviceClass; packetToSend->CommandClass = ConfiguredDeviceClass;
packetToSend->Command = COMMAND_HID_REPORT; packetToSend->Command = COMMAND_HID_GET_REPORT;
Downstream_PacketProcessor_ClassReply(packetToSend); Downstream_PacketProcessor_ClassReply(packetToSend);
} }
@ -348,3 +369,26 @@ uint8_t Downstream_HID_Mouse_Extract8BitValue(HID_HandleTypeDef* hidHandle,
return (int8_t)readData; return (int8_t)readData;
} }
void Downstream_HID_Keyboard_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend)
{
HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData;
uint32_t i;
uint8_t readData;
packetToSend->Data[0] = HID_Handle->Data[0]; //Modifier keys - pass straight through
packetToSend->Data[1] = 0; //Constant byte
for (i = 2; i < HID_KEYBOARD_INPUT_DATA_LEN; i++) //Key array
{
readData = HID_Handle->Data[i];
if (readData > HID_KEYBOARD_MAX_KEY)
{
readData = HID_KEYBOARD_MAX_KEY;
}
packetToSend->Data[i] = readData;
}
}

@ -14,18 +14,30 @@
#define UPSTREAM_HID_H_ #define UPSTREAM_HID_H_
#include "stm32f4xx_hal.h" #include "stm32f4xx_hal.h"
#include "upstream_spi.h"
//These defines are duplicated in downstream_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
#define HID_KEYBOARD_MAX_LED 3
typedef uint8_t (*UpstreamHidSendReportCallback)(uint8_t *report,
typedef uint8_t (*UpstreamHidGetReportCallback)(uint8_t *report,
uint16_t len); uint16_t len);
void Upstream_HID_DeInit(void); void Upstream_HID_DeInit(void);
HAL_StatusTypeDef Upstream_HID_GetNextReport(UpstreamHidSendReportCallback callback); void Upstream_HID_GetNextInterruptReport(UpstreamHidGetReportCallback callback);
void Upstream_HID_SendControlReport(UpstreamPacketTypeDef* packetToSend, uint8_t dataLength);
void Upstream_HID_ReallySendControlReport(void);

@ -59,7 +59,8 @@ InterfaceCommandMscTypeDef;
typedef enum typedef enum
{ {
COMMAND_HID_REPORT, //Returns HID report COMMAND_HID_GET_REPORT, //Returns HID report from device
COMMAND_HID_SET_REPORT //Sends HID report to device. No reply or ack expected.
} }
InterfaceCommandHidTypeDef; InterfaceCommandHidTypeDef;

@ -23,6 +23,9 @@
* limitations under the License. * limitations under the License.
* *
****************************************************************************** ******************************************************************************
*
* Modifications by Robert Fisk
*
*/ */
/* Define to prevent recursive inclusion -------------------------------------*/ /* Define to prevent recursive inclusion -------------------------------------*/
@ -50,11 +53,11 @@
* @{ * @{
*/ */
#define HID_EPIN_ADDR 0x81 #define HID_EPIN_ADDR 0x81
#define HID_EPIN_SIZE 0x04
#define USB_HID_CONFIG_DESC_SIZ 34 #define USB_HID_CONFIG_DESC_SIZ 34
#define USB_HID_DESC_SIZ 9 #define USB_HID_DESC_SIZ 9
#define HID_MOUSE_REPORT_DESC_SIZE 74 #define HID_MOUSE_REPORT_DESC_SIZE 74
#define HID_KEYBOARD_REPORT_DESC_SIZE 63
#define HID_DESCRIPTOR_TYPE 0x21 #define HID_DESCRIPTOR_TYPE 0x21
#define HID_REPORT_DESC 0x22 #define HID_REPORT_DESC 0x22
@ -71,6 +74,10 @@
#define HID_REQ_SET_REPORT 0x09 #define HID_REQ_SET_REPORT 0x09
#define HID_REQ_GET_REPORT 0x01 #define HID_REQ_GET_REPORT 0x01
#define HID_KEYBRD_BOOT_CODE 0x01
#define HID_MOUSE_BOOT_CODE 0x02
/** /**
* @} * @}
*/ */

@ -73,6 +73,8 @@ static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_HID_SendReport (uint8_t *report, static uint8_t USBD_HID_SendReport (uint8_t *report,
uint16_t len); uint16_t len);
static uint8_t USBD_HID_EP0RxReady(USBD_HandleTypeDef *pdev);
#define USBD_PID_HID 0x0002 #define USBD_PID_HID 0x0002
@ -84,7 +86,7 @@ USBD_ClassTypeDef USBD_HID =
USBD_HID_DeInit, USBD_HID_DeInit,
USBD_HID_Setup, USBD_HID_Setup,
NULL, /*EP0_TxSent*/ NULL, /*EP0_TxSent*/
NULL, /*EP0_RxReady*/ USBD_HID_EP0RxReady, /*EP0_RxReady*/
USBD_HID_DataIn, /*DataIn*/ USBD_HID_DataIn, /*DataIn*/
NULL, /*DataOut*/ NULL, /*DataOut*/
NULL, /*SOF */ NULL, /*SOF */
@ -99,9 +101,11 @@ USBD_ClassTypeDef USBD_HID =
}; };
#define USB_HID_CFGDESC__INTERFACE_PROTOCOL_OFFSET 16
#define USB_HID_CFGDESC__HID_REPORT_DESC_SIZE_OFFSET 25
#define USB_HID_CFGDESC__EPIN_SIZE_OFFSET 31
#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 */ /* USB HID device Configuration Descriptor */
@ -128,7 +132,7 @@ __ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_
0x01, /*bNumEndpoints*/ 0x01, /*bNumEndpoints*/
0x03, /*bInterfaceClass: HID*/ 0x03, /*bInterfaceClass: HID*/
0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/ 0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
0x02, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/ 0x00, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
0, /*iInterface: Index of string descriptor*/ 0, /*iInterface: Index of string descriptor*/
/******************** Descriptor of Joystick Mouse HID ********************/ /******************** Descriptor of Joystick Mouse HID ********************/
/* 18 */ /* 18 */
@ -148,7 +152,7 @@ __ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_
HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/ HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
0x03, /*bmAttributes: Interrupt endpoint*/ 0x03, /*bmAttributes: Interrupt endpoint*/
HID_EPIN_SIZE, /*wMaxPacketSize: 4 Byte max */ 0x00, //HID_EPIN_SIZE, /*wMaxPacketSize: 4 Byte max */
0x00, 0x00,
HID_FS_BINTERVAL, /*bInterval: Polling Interval (10 ms)*/ HID_FS_BINTERVAL, /*bInterval: Polling Interval (10 ms)*/
/* 34 */ /* 34 */
@ -192,14 +196,14 @@ __ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] _
0xA1, 0x00, // Collection (Physical) 0xA1, 0x00, // Collection (Physical)
0x05, 0x09, // Usage Page (Button) 0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (0x01) 0x19, 0x01, // Usage Minimum (0x01)
0x29, 0x03, // Usage Maximum (0x03) 0x29, HID_MOUSE_MAX_BUTTONS, // Usage Maximum (0x03)
0x15, 0x00, // Logical Minimum (0) 0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1) 0x25, 0x01, // Logical Maximum (1)
0x95, 0x03, // Report Count (3) 0x95, HID_MOUSE_MAX_BUTTONS, // Report Count (3)
0x75, 0x01, // Report Size (1) 0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x01, // Report Count (1) 0x95, 0x01, // Report Count (1)
0x75, 0x05, // Report Size (5) 0x75, (8 - HID_MOUSE_MAX_BUTTONS), // Report Size (5)
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x30, // Usage (X) 0x09, 0x30, // Usage (X)
@ -223,14 +227,54 @@ __ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] _
0x95, 0x01, // Report Count (1) 0x95, 0x01, // Report Count (1)
0xB1, 0x01, // Feature (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0xB1, 0x01, // Feature (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0, // End Collection 0xC0, // End Collection
// 74 bytes // 74 bytes
}; };
USBD_HandleTypeDef *USBD_HID_pdev; __ALIGN_BEGIN static uint8_t HID_KEYBOARD_ReportDesc[HID_KEYBOARD_REPORT_DESC_SIZE] __ALIGN_END = {
uint8_t* ActiveReportDescriptor = NULL; 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
uint8_t ActiveReportDescriptorLength; 0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, HID_KEYBOARD_MAX_LED, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x03, // USAGE_MAXIMUM (Scroll Lock)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, (8 - HID_KEYBOARD_MAX_LED), // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, HID_KEYBOARD_MAX_KEY, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
};
USBD_HandleTypeDef *USBD_HID_pdev;
UpstreamPacketTypeDef* OutReportPacket = NULL;
uint8_t* ActiveReportDescriptor = NULL;
uint8_t ActiveReportDescriptorLength;
uint8_t InReportSize;
uint8_t OutReportSize;
/** /**
@ -252,12 +296,29 @@ void USBD_HID_PreinitMouse(void)
{ {
ActiveReportDescriptor = HID_MOUSE_ReportDesc; ActiveReportDescriptor = HID_MOUSE_ReportDesc;
ActiveReportDescriptorLength = HID_MOUSE_REPORT_DESC_SIZE; ActiveReportDescriptorLength = HID_MOUSE_REPORT_DESC_SIZE;
InReportSize = HID_MOUSE_INPUT_DATA_LEN;
OutReportSize = HID_MOUSE_OUTPUT_DATA_LEN;
USBD_HID_CfgDesc[USB_HID_CFGDESC__INTERFACE_PROTOCOL_OFFSET] = HID_MOUSE_BOOT_CODE;
USBD_HID_CfgDesc[USB_HID_CFGDESC__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_CfgDesc[USB_HID_CFGDESC__EPIN_SIZE_OFFSET] = HID_MOUSE_INPUT_DATA_LEN;
USBD_HID_Desc[USB_HID_DESC__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;
} }
void USBD_HID_PreinitKeyboard(void)
{
ActiveReportDescriptor = HID_KEYBOARD_ReportDesc;
ActiveReportDescriptorLength = HID_KEYBOARD_REPORT_DESC_SIZE;
InReportSize = HID_KEYBOARD_INPUT_DATA_LEN;
OutReportSize = HID_KEYBOARD_OUTPUT_DATA_LEN;
USBD_HID_CfgDesc[USB_HID_CFGDESC__INTERFACE_PROTOCOL_OFFSET] = HID_KEYBRD_BOOT_CODE;
USBD_HID_CfgDesc[USB_HID_CFGDESC__HID_REPORT_DESC_SIZE_OFFSET] = HID_KEYBOARD_REPORT_DESC_SIZE;
USBD_HID_CfgDesc[USB_HID_CFGDESC__EPIN_SIZE_OFFSET] = HID_KEYBOARD_INPUT_DATA_LEN;
USBD_HID_Desc[USB_HID_DESC__HID_REPORT_DESC_SIZE_OFFSET] = HID_KEYBOARD_REPORT_DESC_SIZE;
}
static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev, static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev,
@ -269,7 +330,7 @@ static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev,
USBD_LL_OpenEP(pdev, USBD_LL_OpenEP(pdev,
HID_EPIN_ADDR, HID_EPIN_ADDR,
USBD_EP_TYPE_INTR, USBD_EP_TYPE_INTR,
HID_EPIN_SIZE); InReportSize);
pdev->pClassData = USBD_malloc(sizeof (USBD_HID_HandleTypeDef)); pdev->pClassData = USBD_malloc(sizeof (USBD_HID_HandleTypeDef));
@ -282,7 +343,7 @@ static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev,
((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE; ((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE;
USBD_HID_pdev = pdev; USBD_HID_pdev = pdev;
Upstream_HID_GetNextReport(USBD_HID_SendReport); Upstream_HID_GetNextInterruptReport(USBD_HID_SendReport);
} }
return ret; return ret;
@ -326,7 +387,7 @@ static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev,
{ {
uint16_t len = 0; uint16_t len = 0;
uint8_t *pbuf = NULL; uint8_t *pbuf = NULL;
USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*) pdev->pClassData; USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*) pdev->pClassData;
if (ActiveReportDescriptor == NULL) if (ActiveReportDescriptor == NULL)
{ {
@ -340,7 +401,6 @@ static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev,
switch (req->bRequest) switch (req->bRequest)
{ {
case HID_REQ_SET_PROTOCOL: case HID_REQ_SET_PROTOCOL:
hhid->Protocol = (uint8_t)(req->wValue); hhid->Protocol = (uint8_t)(req->wValue);
break; break;
@ -361,6 +421,23 @@ static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev,
1); 1);
break; break;
case HID_REQ_SET_REPORT:
if ((OutReportSize > 0) &&
(req->wLength == OutReportSize))
{
if (OutReportPacket != NULL) while(1);
OutReportPacket = Upstream_GetFreePacketImmediately();
if (OutReportPacket == NULL) while(1);
USBD_CtlPrepareRx(pdev, OutReportPacket->Data, OutReportSize);
}
else
{
USBD_CtlError (pdev, req);
return USBD_FAIL;
}
break;
default: default:
USBD_CtlError (pdev, req); USBD_CtlError (pdev, req);
return USBD_FAIL; return USBD_FAIL;
@ -489,7 +566,7 @@ static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev,
((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE; ((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE;
USBD_HID_pdev = pdev; USBD_HID_pdev = pdev;
Upstream_HID_GetNextReport(USBD_HID_SendReport); Upstream_HID_GetNextInterruptReport(USBD_HID_SendReport);
return USBD_OK; return USBD_OK;
} }
@ -507,6 +584,23 @@ static uint8_t *USBD_HID_GetDeviceQualifierDesc (uint16_t *length)
return USBD_HID_DeviceQualifierDesc; return USBD_HID_DeviceQualifierDesc;
} }
//Called when data is received from host on control endpoint.
//Upstream_HID may send this immediately, but will probably have to save it and send after the next interrupt transfer
static uint8_t USBD_HID_EP0RxReady(USBD_HandleTypeDef *pdev)
{
if ((OutReportPacket == NULL) ||
(OutReportSize == 0))
{
while(1);
}
Upstream_HID_SendControlReport(OutReportPacket, OutReportSize);
Upstream_ReleasePacket(OutReportPacket);
OutReportPacket = NULL;
return USBD_OK;
}
/** /**
* @} * @}
*/ */

@ -314,7 +314,7 @@ USBD_StatusTypeDef USBD_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, u
USBD_CtlContinueRx (pdev, USBD_CtlContinueRx (pdev,
pdata, pdata,
MIN(pep->rem_length ,pep->maxpacket)); pep->rem_length);
} }
else else
{ {
@ -354,35 +354,24 @@ USBD_StatusTypeDef USBD_DataInStage(USBD_HandleTypeDef *pdev ,uint8_t epnum, uin
{ {
if(pep->rem_length > pep->maxpacket) if(pep->rem_length > pep->maxpacket)
{ {
pep->rem_length -= pep->maxpacket; pep->rem_length -= pep->maxpacket;
USBD_CtlContinueSendData (pdev, USBD_CtlContinueSendData (pdev,
pdata, pdata,
pep->rem_length); pep->rem_length);
} }
else else
{
/* Prepare endpoint for premature end of transfer */ //We sent less data than host was expecting?
USBD_LL_PrepareReceive (pdev, /* last packet is MPS multiple, so send ZLP packet */
0,
NULL,
0);
{ /* last packet is MPS multiple, so send ZLP packet */
if((pep->total_length % pep->maxpacket == 0) && if((pep->total_length % pep->maxpacket == 0) &&
(pep->total_length >= pep->maxpacket) && (pep->total_length >= pep->maxpacket) &&
(pep->total_length < pdev->ep0_data_len )) (pep->total_length < pdev->ep0_data_len ))
{ {
USBD_CtlContinueSendData(pdev , NULL, 0); USBD_CtlContinueSendData(pdev , NULL, 0);
pdev->ep0_data_len = 0; pdev->ep0_data_len = 0;
} }
else else
/* Prepare endpoint for premature end of transfer */
USBD_LL_PrepareReceive (pdev,
0,
NULL,
0);
{ {
if((pdev->pClass->EP0_TxSent != NULL)&& if((pdev->pClass->EP0_TxSent != NULL)&&
(pdev->dev_state == USBD_STATE_CONFIGURED)) (pdev->dev_state == USBD_STATE_CONFIGURED))

@ -12,23 +12,19 @@
#include "upstream_hid.h" #include "upstream_hid.h"
#include "upstream_spi.h"
#include "upstream_interface_def.h" #include "upstream_interface_def.h"
#include "usbd_hid.h"
#define HID_MOUSE_DATA_LEN 4
#define HID_KEYBOARD_DATA_LEN 0
#define HID_MOUSE_MAX_BUTTONS 4
UpstreamPacketTypeDef* UpstreamHidPacket = NULL; UpstreamPacketTypeDef* UpstreamHidPacket = NULL;
UpstreamHidSendReportCallback ReportCallback = NULL; UpstreamHidGetReportCallback GetReportCallback = NULL;
uint8_t KeyboardOutDataAvailable = 0;
uint8_t KeyboardOutData[HID_KEYBOARD_OUTPUT_DATA_LEN];
void Upstream_HID_GetNextReportReceiveCallback(UpstreamPacketTypeDef* receivedPacket);
void Upstream_HID_GetNextInterruptReportReceiveCallback(UpstreamPacketTypeDef* receivedPacket);
@ -39,29 +35,31 @@ void Upstream_HID_DeInit(void)
Upstream_ReleasePacket(UpstreamHidPacket); Upstream_ReleasePacket(UpstreamHidPacket);
UpstreamHidPacket = NULL; UpstreamHidPacket = NULL;
} }
ReportCallback = NULL; GetReportCallback = NULL;
KeyboardOutDataAvailable = 0;
} }
HAL_StatusTypeDef Upstream_HID_GetNextReport(UpstreamHidSendReportCallback callback) void Upstream_HID_GetNextInterruptReport(UpstreamHidGetReportCallback callback)
{ {
UpstreamPacketTypeDef* freePacket; UpstreamPacketTypeDef* freePacket;
InterfaceCommandClassTypeDef activeClass; InterfaceCommandClassTypeDef activeClass;
activeClass = Upstream_StateMachine_CheckActiveClass(); activeClass = Upstream_StateMachine_CheckActiveClass();
if ((activeClass != COMMAND_CLASS_HID_MOUSE)) //add classes here if ((activeClass != COMMAND_CLASS_HID_MOUSE) &&
(activeClass != COMMAND_CLASS_HID_KEYBOARD)) //add classes here
{ {
UPSTREAM_STATEMACHINE_FREAKOUT; UPSTREAM_STATEMACHINE_FREAKOUT;
return HAL_ERROR; return;
} }
//Just return if we already have an outstanding request //Just return if we already have an outstanding request
if (ReportCallback != NULL) if (GetReportCallback != NULL)
{ {
return HAL_OK; return;
} }
ReportCallback = callback; GetReportCallback = callback;
//Release packet used for last transaction (if any) //Release packet used for last transaction (if any)
if (UpstreamHidPacket != NULL) if (UpstreamHidPacket != NULL)
@ -73,41 +71,43 @@ HAL_StatusTypeDef Upstream_HID_GetNextReport(UpstreamHidSendReportCallback callb
freePacket = Upstream_GetFreePacketImmediately(); freePacket = Upstream_GetFreePacketImmediately();
if (freePacket == NULL) if (freePacket == NULL)
{ {
return HAL_ERROR; return;
} }
freePacket->Length16 = UPSTREAM_PACKET_HEADER_LEN_16; freePacket->Length16 = UPSTREAM_PACKET_HEADER_LEN_16;
freePacket->CommandClass = activeClass; freePacket->CommandClass = activeClass;
freePacket->Command = COMMAND_HID_REPORT; freePacket->Command = COMMAND_HID_GET_REPORT;
if (Upstream_TransmitPacket(freePacket) == HAL_OK) if (Upstream_TransmitPacket(freePacket) == HAL_OK)
{ {
return Upstream_ReceivePacket(Upstream_HID_GetNextReportReceiveCallback); Upstream_ReceivePacket(Upstream_HID_GetNextInterruptReportReceiveCallback);
}
else
{
Upstream_ReleasePacket(freePacket);
} }
//else:
Upstream_ReleasePacket(freePacket);
return HAL_ERROR;
} }
void Upstream_HID_GetNextReportReceiveCallback(UpstreamPacketTypeDef* receivedPacket) void Upstream_HID_GetNextInterruptReportReceiveCallback(UpstreamPacketTypeDef* receivedPacket)
{ {
UpstreamHidSendReportCallback tempReportCallback; UpstreamHidGetReportCallback tempReportCallback;
InterfaceCommandClassTypeDef activeClass; InterfaceCommandClassTypeDef activeClass;
uint8_t dataLength = 0; uint32_t i;
uint8_t i; uint8_t dataLength;
activeClass = Upstream_StateMachine_CheckActiveClass(); activeClass = Upstream_StateMachine_CheckActiveClass();
if ((activeClass != COMMAND_CLASS_HID_MOUSE)) //add classes here if ((activeClass != COMMAND_CLASS_HID_MOUSE) &&
(activeClass != COMMAND_CLASS_HID_KEYBOARD)) //add classes here
{ {
UPSTREAM_STATEMACHINE_FREAKOUT; UPSTREAM_STATEMACHINE_FREAKOUT;
return; return;
} }
if ((UpstreamHidPacket != NULL) || if ((UpstreamHidPacket != NULL) ||
(ReportCallback == NULL)) (GetReportCallback == NULL))
{ {
UPSTREAM_SPI_FREAKOUT; UPSTREAM_SPI_FREAKOUT;
return; return;
@ -121,37 +121,121 @@ void Upstream_HID_GetNextReportReceiveCallback(UpstreamPacketTypeDef* receivedPa
if (activeClass == COMMAND_CLASS_HID_MOUSE) if (activeClass == COMMAND_CLASS_HID_MOUSE)
{ {
if (receivedPacket->Length16 != (UPSTREAM_PACKET_HEADER_LEN_16 + ((HID_MOUSE_DATA_LEN + 1) / 2))) if (receivedPacket->Length16 != (UPSTREAM_PACKET_HEADER_LEN_16 + ((HID_MOUSE_INPUT_DATA_LEN + 1) / 2)))
{ {
UPSTREAM_SPI_FREAKOUT; UPSTREAM_SPI_FREAKOUT;
return; return;
} }
dataLength = HID_MOUSE_INPUT_DATA_LEN;
if ((receivedPacket->Data[0] & ~((1 << HID_MOUSE_MAX_BUTTONS) - 1)) != 0) //Check number of buttons received
{
UPSTREAM_SPI_FREAKOUT;
return;
}
//Other mouse sanity checks & stuff go here...
}
receivedPacket->Data[0] &= ((1 << HID_MOUSE_MAX_BUTTONS) - 1); //Limit number of buttons received else if (activeClass == COMMAND_CLASS_HID_KEYBOARD)
{
//Mouse sanity checks & stuff go here... if (receivedPacket->Length16 != (UPSTREAM_PACKET_HEADER_LEN_16 + ((HID_KEYBOARD_INPUT_DATA_LEN + 1) / 2)))
{
UPSTREAM_SPI_FREAKOUT;
return;
}
dataLength = HID_KEYBOARD_INPUT_DATA_LEN;
dataLength = HID_MOUSE_DATA_LEN; if (receivedPacket->Data[1] != 0)
{
UPSTREAM_SPI_FREAKOUT;
return;
}
for (i = 2; i < HID_KEYBOARD_INPUT_DATA_LEN; i++)
{
if (receivedPacket->Data[i] > HID_KEYBOARD_MAX_KEY)
{
UPSTREAM_SPI_FREAKOUT;
return;
}
}
//Other keyboard sanity checks here...
} }
//Other HID classes go here... //Other HID classes go here...
else
{
UPSTREAM_SPI_FREAKOUT;
return;
}
UpstreamHidPacket = receivedPacket; //Save packet so we can free it when upstream USB transaction is done
tempReportCallback = GetReportCallback;
GetReportCallback = NULL;
tempReportCallback(receivedPacket->Data, dataLength);
if (dataLength == 0) //Check if we need to send OUT data to the keyboard before requesting next Interrupt IN data
if (KeyboardOutDataAvailable)
{
Upstream_HID_ReallySendControlReport();
}
}
void Upstream_HID_SendControlReport(UpstreamPacketTypeDef* packetToSend, uint8_t dataLength)
{
InterfaceCommandClassTypeDef activeClass;
uint32_t i;
activeClass = Upstream_StateMachine_CheckActiveClass();
if ((packetToSend == NULL) ||
(activeClass != COMMAND_CLASS_HID_KEYBOARD) ||
(dataLength != HID_KEYBOARD_OUTPUT_DATA_LEN))
{ {
UPSTREAM_SPI_FREAKOUT; UPSTREAM_SPI_FREAKOUT;
return; return;
} }
for (i = dataLength; i < HID_EPIN_SIZE; i++) if (GetReportCallback == NULL)
{ {
receivedPacket->Data[i] = 0; //Zero out unused bytes before we send report upstream while(1); //checkme!
} }
UpstreamHidPacket = receivedPacket; //Save packet so we can free it when upstream USB transaction is done //Save data until after the next interrupt data is received from Downstream
tempReportCallback = ReportCallback; KeyboardOutDataAvailable = 1;
ReportCallback = NULL; for (i = 0; i < HID_KEYBOARD_OUTPUT_DATA_LEN; i++)
tempReportCallback(receivedPacket->Data, HID_EPIN_SIZE); {
KeyboardOutData[i] = packetToSend->Data[i];
}
}
void Upstream_HID_ReallySendControlReport(void)
{
UpstreamPacketTypeDef* freePacket;
uint32_t i;
KeyboardOutDataAvailable = 0;
freePacket = Upstream_GetFreePacketImmediately();
if (freePacket == NULL) return;
freePacket->Length16 = UPSTREAM_PACKET_HEADER_LEN_16 + ((HID_KEYBOARD_OUTPUT_DATA_LEN + 1) / 2);
freePacket->CommandClass = COMMAND_CLASS_HID_KEYBOARD;
freePacket->Command = COMMAND_HID_SET_REPORT;
for (i = 0; i < HID_KEYBOARD_OUTPUT_DATA_LEN; i++)
{
freePacket->Data[i] = KeyboardOutData[i];
}
freePacket->Data[0] &= ((1 << HID_KEYBOARD_MAX_LED) - 1);
if (Upstream_TransmitPacket(freePacket) != HAL_OK)
{
Upstream_ReleasePacket(freePacket);
}
} }

@ -180,6 +180,12 @@ void Upstream_StateMachine_NotifyDeviceReplyCallback(UpstreamPacketTypeDef* repl
USBD_HID_PreinitMouse(); USBD_HID_PreinitMouse();
break; break;
case COMMAND_CLASS_HID_KEYBOARD:
newActiveClass = COMMAND_CLASS_HID_KEYBOARD;
newClassPointer = &USBD_HID;
USBD_HID_PreinitKeyboard();
break;
//Add other supported classes here... //Add other supported classes here...
} }

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="ilg.gnuarmeclipse.debug.gdbjtag.openocd.launchConfigurationType"> <launchConfiguration type="ilg.gnuarmeclipse.debug.gdbjtag.openocd.launchConfigurationType">
<stringAttribute key="ilg.gnuarmeclipse.debug.gdbjtag.PERIPHERALS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;peripherals&gt;&#10;&lt;peripheral name=&quot;DMA2&quot;/&gt;&#10;&lt;/peripherals&gt;&#10;"/> <stringAttribute key="ilg.gnuarmeclipse.debug.gdbjtag.PERIPHERALS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;peripherals&gt;&#10;&lt;peripheral name=&quot;DMA2&quot;/&gt;&#10;&lt;peripheral name=&quot;GPIOA&quot;/&gt;&#10;&lt;/peripherals&gt;&#10;"/>
<booleanAttribute key="ilg.gnuarmeclipse.debug.gdbjtag.openocd.doContinue" value="true"/> <booleanAttribute key="ilg.gnuarmeclipse.debug.gdbjtag.openocd.doContinue" value="true"/>
<booleanAttribute key="ilg.gnuarmeclipse.debug.gdbjtag.openocd.doDebugInRam" value="false"/> <booleanAttribute key="ilg.gnuarmeclipse.debug.gdbjtag.openocd.doDebugInRam" value="false"/>
<booleanAttribute key="ilg.gnuarmeclipse.debug.gdbjtag.openocd.doFirstReset" value="true"/> <booleanAttribute key="ilg.gnuarmeclipse.debug.gdbjtag.openocd.doFirstReset" value="true"/>

Loading…
Cancel
Save