You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
opentrackpadcontroller/src/usbd_hid_custom.cpp

286 lines
8.6 KiB
C++

#include "usbd_hid_custom.h"
#include "usbd_ctlreq.h"
#include "usbd_descriptors.h"
static uint8_t USBD_HID_Init(USBD_HandleTypeDef* pdev, uint8_t cfgidx);
static uint8_t USBD_HID_DeInit(USBD_HandleTypeDef* pdev, uint8_t cfgidx);
static uint8_t USBD_CUSTOM_HID_Setup(USBD_HandleTypeDef* pdev, USBD_SetupReqTypedef* req);
static uint8_t USBD_HID_MOUSE_Setup(USBD_HandleTypeDef* pdev, USBD_SetupReqTypedef* req);
static uint8_t* USBD_HID_GetFSCfgDesc(uint16_t* length);
static uint8_t* USBD_HID_GetHSCfgDesc(uint16_t* length);
static uint8_t* USBD_HID_GetOtherSpeedCfgDesc(uint16_t* length);
static uint8_t* USBD_HID_GetDeviceQualifierDesc(uint16_t* length);
static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef* pdev, uint8_t epnum);
USBD_ClassTypeDef USBD_CUSTOM_HID = {
USBD_HID_Init,
USBD_HID_DeInit,
USBD_CUSTOM_HID_Setup,
NULL, //EP0_TxSent
NULL, //EP0_RxReady
USBD_HID_DataIn, //DataIn
NULL, //DataOut
NULL, //SOF
NULL,
NULL,
USBD_HID_GetHSCfgDesc,
USBD_HID_GetFSCfgDesc,
USBD_HID_GetOtherSpeedCfgDesc,
USBD_HID_GetDeviceQualifierDesc,
};
static uint8_t USBD_HID_Init(USBD_HandleTypeDef* pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
uint8_t ret = USBD_OK;
// Open EP IN
USBD_LL_OpenEP(pdev, HID_CUSTOM_EPIN_ADDR, USBD_EP_TYPE_INTR, HID_CUSTOM_EPIN_SIZE);
pdev->ep_in[HID_CUSTOM_EPIN_ADDR & 0xFU].is_used = 1U;
/*
// Open EP IN
USBD_LL_OpenEP(pdev,
HID_KEYBOARD_EPIN_ADDR,
USBD_EP_TYPE_INTR,
HID_KEYBOARD_EPIN_SIZE);
pdev->ep_in[HID_KEYBOARD_EPIN_ADDR & 0xFU].is_used = 1U;
*/
pdev->pClassData = USBD_malloc(sizeof(USBD_HID_HandleTypeDef));
if (pdev->pClassData == NULL)
{
ret = USBD_FAIL;
}
else
{
((USBD_HID_HandleTypeDef*)pdev->pClassData)->Mousestate = HID_IDLE;
//((USBD_HID_HandleTypeDef *)pdev->pClassData)->Keyboardstate = HID_IDLE;
}
return ret;
}
static uint8_t USBD_HID_DeInit(USBD_HandleTypeDef* pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
/* Close HID EPs */
USBD_LL_CloseEP(pdev, HID_CUSTOM_EPIN_ADDR);
pdev->ep_in[HID_CUSTOM_EPIN_ADDR & 0xFU].is_used = 0U;
/*
USBD_LL_CloseEP(pdev, HID_KEYBOARD_EPIN_ADDR);
pdev->ep_in[HID_KEYBOARD_EPIN_ADDR & 0xFU].is_used = 0U;
*/
/* Free allocated memory */
if (pdev->pClassData != NULL)
{
USBD_free(pdev->pClassData);
pdev->pClassData = NULL;
}
return USBD_OK;
}
static uint8_t USBD_CUSTOM_HID_Setup(USBD_HandleTypeDef* pdev, USBD_SetupReqTypedef* req)
{
/* Check which interface is targetted by this request */
//if ((req->wIndex & 0x00FF) == HID_KEYBOARD_INTERFACE)
//{
// return USBD_HID_KEYBOARD_Setup(pdev, req);
//}
//else
//{
return USBD_HID_MOUSE_Setup(pdev, req);
//}
}
static uint8_t USBD_HID_MOUSE_Setup(USBD_HandleTypeDef* pdev, USBD_SetupReqTypedef* req)
{
USBD_HID_HandleTypeDef* hhid = (USBD_HID_HandleTypeDef*)pdev->pClassData;
uint16_t len = 0U;
uint8_t* pbuf = NULL;
uint16_t status_info = 0U;
USBD_StatusTypeDef ret = USBD_OK;
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
case USB_REQ_TYPE_CLASS:
switch (req->bRequest)
{
case HID_REQ_SET_PROTOCOL:
hhid->Protocol = (uint8_t)(req->wValue);
break;
case HID_REQ_GET_PROTOCOL:
USBD_CtlSendData(pdev, (uint8_t*)&hhid->Protocol, 1U);
break;
case HID_REQ_SET_IDLE:
hhid->IdleState = (uint8_t)(req->wValue >> 8);
break;
case HID_REQ_GET_IDLE:
USBD_CtlSendData(pdev, (uint8_t*)&hhid->IdleState, 1U);
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest)
{
case USB_REQ_GET_STATUS:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
USBD_CtlSendData(pdev, (uint8_t*)(void*)&status_info, 2U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_GET_DESCRIPTOR:
if (req->wValue >> 8 == HID_REPORT_DESC)
{
len = MIN(HID_CUSTOM_REPORT_DESC_SIZE, req->wLength);
pbuf = HID_CUSTOM_ReportDesc;
}
else if (req->wValue >> 8 == HID_DESCRIPTOR_TYPE)
{
pbuf = USBD_HID_CUSTOM_Desc;
len = MIN(USB_HID_CUSTOM_DESC_SIZ, req->wLength);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
USBD_CtlSendData(pdev, pbuf, len);
break;
case USB_REQ_GET_INTERFACE:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
USBD_CtlSendData(pdev, (uint8_t*)&hhid->AltSetting, 1U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_SET_INTERFACE:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
hhid->AltSetting = (uint8_t)(req->wValue);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
return ret;
}
uint8_t USBD_HID_CUSTOM_SendReport(USBD_HandleTypeDef* pdev, uint8_t* report, uint16_t len)
{
USBD_HID_HandleTypeDef* hhid = (USBD_HID_HandleTypeDef*)pdev->pClassData;
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
if (hhid->Mousestate == HID_IDLE)
{
hhid->Mousestate = HID_BUSY;
USBD_LL_Transmit(pdev, HID_CUSTOM_EPIN_ADDR, report, len);
}
}
return USBD_OK;
}
uint32_t USBD_HID_GetPollingInterval(USBD_HandleTypeDef* pdev)
{
uint32_t polling_interval = 0U;
/* HIGH-speed endpoints */
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
/* Sets the data transfer polling interval for high speed transfers.
Values between 1..16 are allowed. Values correspond to interval
of 2 ^ (bInterval-1). This option (8 ms, corresponds to HID_HS_BINTERVAL */
polling_interval = (((1U << (HID_HS_BINTERVAL - 1U))) / 8U);
}
else
{ /* LOW and FULL-speed endpoints */
/* Sets the data transfer polling interval for low and full
speed transfers */
polling_interval = HID_FS_BINTERVAL;
}
return ((uint32_t)(polling_interval));
}
static uint8_t* USBD_HID_GetFSCfgDesc(uint16_t* length)
{
*length = sizeof(USBD_HID_CUSTOM_CfgFSDesc);
return USBD_HID_CUSTOM_CfgFSDesc;
}
static uint8_t* USBD_HID_GetHSCfgDesc(uint16_t* length)
{
*length = sizeof(USBD_HID_CUSTOM_CfgHSDesc);
return USBD_HID_CUSTOM_CfgHSDesc;
}
static uint8_t* USBD_HID_GetOtherSpeedCfgDesc(uint16_t* length)
{
*length = sizeof(USBD_HID_CUSTOM_OtherSpeedCfgDesc);
return USBD_HID_CUSTOM_OtherSpeedCfgDesc;
}
static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef* pdev, uint8_t epnum)
{
/* 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 */
//if (epnum == (HID_KEYBOARD_EPIN_ADDR & 0x7F))
//{
//((USBD_HID_HandleTypeDef *)pdev->pClassData)->Keyboardstate = HID_IDLE;
//}
//else if (epnum == (HID_CUSTOM_EPIN_ADDR & 0x7F))
//{
((USBD_HID_HandleTypeDef*)pdev->pClassData)->Mousestate = HID_IDLE;
//}
return USBD_OK;
}
static uint8_t* USBD_HID_GetDeviceQualifierDesc(uint16_t* length)
{
*length = sizeof(USBD_HID_DeviceQualifierDesc);
return USBD_HID_DeviceQualifierDesc;
}