Upstream HID mouse support probably done, not tested yet.

USG_1.0
Robert Fisk 9 years ago
parent c3c4d47145
commit 4c40373a32

@ -0,0 +1,35 @@
/*
* upstream_hid.h
*
* Created on: Jan 16, 2016
* Author: Robert Fisk
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef UPSTREAM_HID_H_
#define UPSTREAM_HID_H_
//#include "usbd_def.h"
#include "stm32f4xx_hal.h"
#include "upstream_interface_def.h"
typedef uint8_t UpstreamHidSendReportCallback(uint8_t *report,
uint16_t len);
void Upstream_HID_Init(InterfaceCommandClassTypeDef newClass);
void Upstream_HID_DeInit(void);
void Upstream_HID_GetNextReport(UpstreamHidSendReportCallback callback);
#endif /* UPSTREAM_HID_H_ */

@ -56,6 +56,13 @@ typedef enum
InterfaceCommandMscTypeDef; InterfaceCommandMscTypeDef;
typedef enum
{
COMMAND_HID_REPORT, //Downstream initiates HID report transfer to Upstream. Upstream just needs to Upstream_ReceivePacket each time.
}
InterfaceCommandHidTypeDef;
typedef enum typedef enum
{ {
COMMAND_ERROR_GENERIC, COMMAND_ERROR_GENERIC,

@ -13,7 +13,10 @@
#define INC_UPSTREAM_SPI_H_ #define INC_UPSTREAM_SPI_H_
#include "upstream_statemachine.h"
#include "usbd_config.h" #include "usbd_config.h"
#include "led.h"
#define UPSTREAM_PACKET_HEADER_LEN (2) //Min length = CommandClass & Command bytes #define UPSTREAM_PACKET_HEADER_LEN (2) //Min length = CommandClass & Command bytes
@ -84,6 +87,8 @@ HAL_StatusTypeDef Upstream_ReceivePacket(SpiPacketReceivedCallbackTypeDef callba
void Upstream_TxOkInterrupt(void); void Upstream_TxOkInterrupt(void);
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi); void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi);
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi); void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi);
void Upstream_SetExpectedReceivedCommand(uint8_t expectedCommandClass,
uint8_t expectedCommand);
#endif /* INC_UPSTREAM_SPI_H_ */ #endif /* INC_UPSTREAM_SPI_H_ */

@ -124,9 +124,8 @@ extern USBD_ClassTypeDef USBD_HID_Keyboard;
/** @defgroup USB_CORE_Exported_Functions /** @defgroup USB_CORE_Exported_Functions
* @{ * @{
*/ */
uint8_t USBD_HID_SendReport (USBD_HandleTypeDef *pdev, uint8_t USBD_HID_SendReport (uint8_t *report,
uint8_t *report, uint16_t len);
uint16_t len);
uint32_t USBD_HID_GetPollingInterval (USBD_HandleTypeDef *pdev); uint32_t USBD_HID_GetPollingInterval (USBD_HandleTypeDef *pdev);

@ -44,11 +44,14 @@
* limitations under the License. * limitations under the License.
* *
****************************************************************************** ******************************************************************************
*/ *
* Modifications by Robert Fisk
*/
/* Includes ------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
#include "usbd_hid.h" #include "usbd_hid.h"
#include "usbd_ctlreq.h" #include "usbd_ctlreq.h"
#include "upstream_hid.h"
@ -113,8 +116,8 @@ USBD_ClassTypeDef USBD_HID_Keyboard =
#define USB_HID_CFGDESC_HID_REPORT_DESC_SIZE_OFFSET 25 #define USB_HID_CFGDESC__HID_REPORT_DESC_SIZE_OFFSET 25
#define USB_HID_DESC_HID_REPORT_DESC_SIZE_OFFSET 7 #define USB_HID_DESC__HID_REPORT_DESC_SIZE_OFFSET 7
/* USB HID device Configuration Descriptor */ /* USB HID device Configuration Descriptor */
@ -198,57 +201,52 @@ __ALIGN_BEGIN static uint8_t USBD_HID_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END = __ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{ {
0x05, 0x01, 0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x02, 0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, 0xA1, 0x01, // Collection (Application)
0x09, 0x01, 0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection (Physical)
0xA1, 0x00, 0x05, 0x09, // Usage Page (Button)
0x05, 0x09, 0x19, 0x01, // Usage Minimum (0x01)
0x19, 0x01, 0x29, 0x03, // Usage Maximum (0x03)
0x29, 0x03, 0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x15, 0x00, 0x95, 0x03, // Report Count (3)
0x25, 0x01, 0x75, 0x01, // Report Size (1)
0x95, 0x03, 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x75, 0x01, 0x95, 0x01, // Report Count (1)
0x75, 0x05, // Report Size (5)
0x81, 0x02, 0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x01, 0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x75, 0x05, 0x09, 0x30, // Usage (X)
0x81, 0x01, 0x09, 0x31, // Usage (Y)
0x09, 0x38, // Usage (Wheel)
0x05, 0x01, 0x15, 0x81, // Logical Minimum (129)
0x09, 0x30, 0x25, 0x7F, // Logical Maximum (127)
0x09, 0x31, 0x75, 0x08, // Report Size (8)
0x09, 0x38, 0x95, 0x03, // Report Count (3)
0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
0x15, 0x81, 0xC0, // End Collection
0x25, 0x7F, 0x09, 0x3C, // Usage (Motion Wakeup)
0x75, 0x08, 0x05, 0xFF, // Usage Page (Reserved 0xFF)
0x95, 0x03, 0x09, 0x01, // Usage (0x01)
0x15, 0x00, // Logical Minimum (0)
0x81, 0x06, 0x25, 0x01, // Logical Maximum (1)
0xC0, 0x09, 0x75, 0x01, // Report Size (1)
0x3c, 0x05, 0x95, 0x01, // Report Count (1)
0xff, 0x09, 0xB1, 0x22, // Feature (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Non-volatile)
0x75, 0x07, // Report Size (7)
0x95, 0x01, // Report Count (1)
0xB1, 0x01, // Feature (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0, // End Collection
0x01, 0x15, // 74 bytes
0x00, 0x25,
0x01, 0x75,
0x01, 0x95,
0x02, 0xb1,
0x22, 0x75,
0x06, 0x95,
0x01, 0xb1,
0x01, 0xc0
}; };
uint8_t* ActiveReportDescriptor = NULL; USBD_HandleTypeDef *USBD_HID_pdev;
uint8_t ActiveReportDescriptorLength; uint8_t* ActiveReportDescriptor = NULL;
uint8_t ActiveReportDescriptorLength;
/** /**
@ -266,14 +264,16 @@ uint8_t ActiveReportDescriptorLength;
* @param cfgidx: Configuration index * @param cfgidx: Configuration index
* @retval status * @retval status
*/ */
static uint8_t USBD_HID_InitMouse(USBD_HandleTypeDef *pdev, static uint8_t USBD_HID_InitMouse(USBD_HandleTypeDef *pdev,
uint8_t cfgidx) uint8_t cfgidx)
{ {
ActiveReportDescriptor = HID_MOUSE_ReportDesc; ActiveReportDescriptor = HID_MOUSE_ReportDesc;
ActiveReportDescriptorLength = HID_MOUSE_REPORT_DESC_SIZE; ActiveReportDescriptorLength = 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__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; USBD_HID_Desc[USB_HID_DESC__HID_REPORT_DESC_SIZE_OFFSET] = HID_MOUSE_REPORT_DESC_SIZE;
Upstream_HID_Init(COMMAND_CLASS_HID_MOUSE);
return USBD_HID_Init(pdev, cfgidx); return USBD_HID_Init(pdev, cfgidx);
} }
@ -301,7 +301,11 @@ static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev,
else else
{ {
((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE; ((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE;
USBD_HID_pdev = pdev;
Upstream_HID_GetNextReport(USBD_HID_SendReport);
} }
return ret; return ret;
} }
@ -316,6 +320,7 @@ static uint8_t USBD_HID_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx) uint8_t cfgidx)
{ {
ActiveReportDescriptor = NULL; ActiveReportDescriptor = NULL;
Upstream_HID_DeInit();
/* Close HID EPs */ /* Close HID EPs */
USBD_LL_CloseEP(pdev, USBD_LL_CloseEP(pdev,
@ -426,18 +431,17 @@ static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev,
* @param buff: pointer to report * @param buff: pointer to report
* @retval status * @retval status
*/ */
uint8_t USBD_HID_SendReport (USBD_HandleTypeDef *pdev, uint8_t USBD_HID_SendReport(uint8_t *report,
uint8_t *report, uint16_t len)
uint16_t len)
{ {
USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*)pdev->pClassData; USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*)USBD_HID_pdev->pClassData;
if (pdev->dev_state == USBD_STATE_CONFIGURED ) if (USBD_HID_pdev->dev_state == USBD_STATE_CONFIGURED )
{ {
if(hhid->state == HID_IDLE) if(hhid->state == HID_IDLE)
{ {
hhid->state = HID_BUSY; hhid->state = HID_BUSY;
USBD_LL_Transmit (pdev, USBD_LL_Transmit (USBD_HID_pdev,
HID_EPIN_ADDR, HID_EPIN_ADDR,
report, report,
len); len);
@ -501,12 +505,15 @@ static uint8_t *USBD_HID_GetCfgDesc (uint16_t *length)
* @retval status * @retval status
*/ */
static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev, static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev,
uint8_t epnum) uint8_t epnum)
{ {
/* Ensure that the FIFO is empty before a new transfer, this condition could /* Ensure that the FIFO is empty before a new transfer, this condition could
be caused by a new transfer before the end of the previous transfer */ be caused by a new transfer before the end of the previous transfer */
((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE; ((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE;
USBD_HID_pdev = pdev;
Upstream_HID_GetNextReport(USBD_HID_SendReport);
return USBD_OK; return USBD_OK;
} }

@ -0,0 +1,117 @@
/*
* upstream_hid.c
*
* Created on: Jan 16, 2016
* Author: Robert Fisk
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include "upstream_hid.h"
#include "upstream_spi.h"
#include "upstream_interface_def.h"
#include "usbd_hid.h"
#define HID_MOUSE_REPORT_LEN 4
InterfaceCommandClassTypeDef ActiveHidClass = COMMAND_CLASS_INTERFACE;
UpstreamPacketTypeDef* UpstreamHidPacket = NULL;
void Upstream_HID_GetNextReportReceiveCallback(UpstreamPacketTypeDef* receivedPacket);
void Upstream_HID_Init(InterfaceCommandClassTypeDef newClass)
{
if ((newClass != COMMAND_CLASS_HID_MOUSE)) //add classes here
{
UPSTREAM_SPI_FREAKOUT;
return;
}
if (UpstreamHidPacket != NULL)
{
UPSTREAM_SPI_FREAKOUT;
return;
}
ActiveHidClass = newClass;
}
void Upstream_HID_DeInit(void)
{
ActiveHidClass = COMMAND_CLASS_INTERFACE;
if (UpstreamHidPacket != NULL)
{
Upstream_ReleasePacket(UpstreamHidPacket);
UpstreamHidPacket = NULL;
}
}
void Upstream_HID_GetNextReport(UpstreamHidSendReportCallback callback)
{
if ((ActiveHidClass != COMMAND_CLASS_HID_MOUSE)) //add classes here
{
UPSTREAM_SPI_FREAKOUT;
return;
}
//Release packet used for last transaction (if any)
if (UpstreamHidPacket != NULL)
{
Upstream_ReleasePacket(UpstreamHidPacket);
UpstreamHidPacket = NULL;
}
//Get next packet
Upstream_SetExpectedReceivedCommand(ActiveHidClass, COMMAND_HID_REPORT);
Upstream_ReceivePacket(Upstream_HID_GetNextReportReceiveCallback);
}
void Upstream_HID_GetNextReportReceiveCallback(UpstreamPacketTypeDef* receivedPacket)
{
uint8_t reportLength;
if (UpstreamHidPacket != NULL)
{
UPSTREAM_SPI_FREAKOUT;
return;
}
if (receivedPacket == NULL)
{
return; //Just give up...
}
if (ActiveHidClass == COMMAND_CLASS_HID_MOUSE)
{
if (receivedPacket->Length16 != (UPSTREAM_PACKET_HEADER_LEN_16 + ((HID_MOUSE_REPORT_LEN + 1) / 2)))
{
UPSTREAM_SPI_FREAKOUT;
return;
}
//Mouse sanity checks & stuff go here...
reportLength = HID_MOUSE_REPORT_LEN;
}
//Other HID classes go here...
UpstreamHidPacket = receivedPacket; //Save packet so we can free it when upstream USB transaction is done
USBD_HID_SendReport(receivedPacket->Data, reportLength);
}

@ -11,9 +11,7 @@
#include "upstream_interface_def.h" #include "upstream_interface_def.h"
#include "upstream_spi.h" #include "upstream_spi.h"
#include "upstream_statemachine.h"
#include "stm32f4xx_hal.h" #include "stm32f4xx_hal.h"
#include "usbd_def.h"
#include "board_config.h" #include "board_config.h"
#include "interrupts.h" #include "interrupts.h"
@ -148,6 +146,12 @@ void Upstream_ReleasePacket(UpstreamPacketTypeDef* packetToRelease)
return; return;
} }
if (packetToRelease->Busy != BUSY)
{
UPSTREAM_SPI_FREAKOUT;
return;
}
if (PendingFreePacketCallback != NULL) if (PendingFreePacketCallback != NULL)
{ {
tempCallback = PendingFreePacketCallback; //In extreme situations, running this callback can trigger another request for a free packet, tempCallback = PendingFreePacketCallback; //In extreme situations, running this callback can trigger another request for a free packet,
@ -445,8 +449,8 @@ void Upstream_BeginTransmitPacketSize(void)
if (HAL_SPI_TransmitReceive(&Hspi1, if (HAL_SPI_TransmitReceive(&Hspi1,
(uint8_t*)&CurrentWorkingPacket->Length16, (uint8_t*)&CurrentWorkingPacket->Length16,
(uint8_t*)&TemporaryIncomingPacketLength, (uint8_t*)&TemporaryIncomingPacketLength,
2, 2, //We only need to write one word, but the peripheral library freaks out...
SPI_TIMEOUT_VALUE) != HAL_OK) //We only need to write one word, but the peripheral library freaks out... SPI_TIMEOUT_VALUE) != HAL_OK)
{ {
UPSTREAM_SPI_FREAKOUT; UPSTREAM_SPI_FREAKOUT;
} }
@ -491,8 +495,8 @@ void Upstream_BeginReceivePacketSize(UpstreamPacketTypeDef* freePacket)
if (HAL_SPI_TransmitReceive(&Hspi1, if (HAL_SPI_TransmitReceive(&Hspi1,
(uint8_t*)&CurrentWorkingPacket->Length16, (uint8_t*)&CurrentWorkingPacket->Length16,
(uint8_t*)&CurrentWorkingPacket->Length16, (uint8_t*)&CurrentWorkingPacket->Length16,
2, 2, //We only need to write one word, but the peripheral library freaks out...
SPI_TIMEOUT_VALUE) != HAL_OK) //We only need to write one word, but the peripheral library freaks out... SPI_TIMEOUT_VALUE) != HAL_OK)
{ {
UPSTREAM_SPI_FREAKOUT; UPSTREAM_SPI_FREAKOUT;
} }
@ -515,7 +519,6 @@ void Upstream_BeginReceivePacketBody(void)
} }
//Something bad happened! Possibly CRC error... //Something bad happened! Possibly CRC error...
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
{ {
@ -537,3 +540,12 @@ void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
} }
//Used by USB interface classes.
//This is required when Downstream sends a packet without an initiating request from us
void Upstream_SetExpectedReceivedCommand(uint8_t expectedCommandClass,
uint8_t expectedCommand)
{
SentCommandClass = expectedCommandClass;
SentCommand = expectedCommand;
}

Loading…
Cancel
Save