801 lines
22 KiB
C
801 lines
22 KiB
C
|
/**
|
||
|
******************************************************************************
|
||
|
* @file usbh_hid.c
|
||
|
* @author MCD Application Team
|
||
|
* @version V3.0.0
|
||
|
* @date 18-February-2014
|
||
|
* @brief This file is the HID Layer Handlers for USB Host HID class.
|
||
|
*
|
||
|
* @verbatim
|
||
|
*
|
||
|
* ===================================================================
|
||
|
* HID Class Description
|
||
|
* ===================================================================
|
||
|
* This module manages the MSC class V1.11 following the "Device Class Definition
|
||
|
* for Human Interface Devices (HID) Version 1.11 Jun 27, 2001".
|
||
|
* This driver implements the following aspects of the specification:
|
||
|
* - The Boot Interface Subclass
|
||
|
* - The Mouse and Keyboard protocols
|
||
|
*
|
||
|
* @endverbatim
|
||
|
*
|
||
|
******************************************************************************
|
||
|
* @attention
|
||
|
*
|
||
|
* <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
|
||
|
*
|
||
|
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||
|
* You may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at:
|
||
|
*
|
||
|
* http://www.st.com/software_license_agreement_liberty_v2
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*
|
||
|
******************************************************************************
|
||
|
*/
|
||
|
|
||
|
/* Includes ------------------------------------------------------------------*/
|
||
|
#include "usbh_hid.h"
|
||
|
#include "usbh_hid_parser.h"
|
||
|
|
||
|
|
||
|
/** @addtogroup USBH_LIB
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/** @addtogroup USBH_CLASS
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/** @addtogroup USBH_HID_CLASS
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/** @defgroup USBH_HID_CORE
|
||
|
* @brief This file includes HID Layer Handlers for USB Host HID class.
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/** @defgroup USBH_HID_CORE_Private_TypesDefinitions
|
||
|
* @{
|
||
|
*/
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
|
||
|
/** @defgroup USBH_HID_CORE_Private_Defines
|
||
|
* @{
|
||
|
*/
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
|
||
|
/** @defgroup USBH_HID_CORE_Private_Macros
|
||
|
* @{
|
||
|
*/
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
|
||
|
/** @defgroup USBH_HID_CORE_Private_Variables
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
|
||
|
/** @defgroup USBH_HID_CORE_Private_FunctionPrototypes
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
static USBH_StatusTypeDef USBH_HID_InterfaceInit (USBH_HandleTypeDef *phost);
|
||
|
static USBH_StatusTypeDef USBH_HID_InterfaceDeInit (USBH_HandleTypeDef *phost);
|
||
|
static USBH_StatusTypeDef USBH_HID_ClassRequest(USBH_HandleTypeDef *phost);
|
||
|
static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost);
|
||
|
static USBH_StatusTypeDef USBH_HID_SOFProcess(USBH_HandleTypeDef *phost);
|
||
|
static void USBH_HID_ParseHIDDesc (HID_DescTypeDef *desc, uint8_t *buf);
|
||
|
|
||
|
extern USBH_StatusTypeDef USBH_HID_MouseInit(USBH_HandleTypeDef *phost);
|
||
|
extern USBH_StatusTypeDef USBH_HID_KeybdInit(USBH_HandleTypeDef *phost);
|
||
|
|
||
|
USBH_ClassTypeDef HID_Class =
|
||
|
{
|
||
|
"HID",
|
||
|
USB_HID_CLASS,
|
||
|
USBH_HID_InterfaceInit,
|
||
|
USBH_HID_InterfaceDeInit,
|
||
|
USBH_HID_ClassRequest,
|
||
|
USBH_HID_Process,
|
||
|
USBH_HID_SOFProcess,
|
||
|
NULL,
|
||
|
};
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
|
||
|
/** @defgroup USBH_HID_CORE_Private_Functions
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief USBH_HID_InterfaceInit
|
||
|
* The function init the HID class.
|
||
|
* @param phost: Host handle
|
||
|
* @retval USBH Status
|
||
|
*/
|
||
|
static USBH_StatusTypeDef USBH_HID_InterfaceInit (USBH_HandleTypeDef *phost)
|
||
|
{
|
||
|
uint8_t max_ep;
|
||
|
uint8_t num = 0;
|
||
|
uint8_t interface;
|
||
|
|
||
|
USBH_StatusTypeDef status = USBH_FAIL ;
|
||
|
HID_HandleTypeDef *HID_Handle;
|
||
|
|
||
|
interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_BOOT_CODE, 0xFF);
|
||
|
|
||
|
if(interface == 0xFF) /* No Valid Interface */
|
||
|
{
|
||
|
status = USBH_FAIL;
|
||
|
USBH_DbgLog ("Cannot Find the interface for %s class.", phost->pActiveClass->Name);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
USBH_SelectInterface (phost, interface);
|
||
|
phost->pActiveClass->pData = (HID_HandleTypeDef *)USBH_malloc (sizeof(HID_HandleTypeDef));
|
||
|
HID_Handle = phost->pActiveClass->pData;
|
||
|
HID_Handle->state = HID_ERROR;
|
||
|
|
||
|
/*Decode Bootclass Protocl: Mouse or Keyboard*/
|
||
|
if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol == HID_KEYBRD_BOOT_CODE)
|
||
|
{
|
||
|
USBH_UsrLog ("KeyBoard device found!");
|
||
|
HID_Handle->Init = USBH_HID_KeybdInit;
|
||
|
}
|
||
|
else if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol == HID_MOUSE_BOOT_CODE)
|
||
|
{
|
||
|
USBH_UsrLog ("Mouse device found!");
|
||
|
HID_Handle->Init = USBH_HID_MouseInit;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
USBH_UsrLog ("Protocol not supported.");
|
||
|
return USBH_FAIL;
|
||
|
}
|
||
|
|
||
|
HID_Handle->state = HID_INIT;
|
||
|
HID_Handle->ctl_state = HID_REQ_INIT;
|
||
|
HID_Handle->ep_addr = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bEndpointAddress;
|
||
|
HID_Handle->length = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].wMaxPacketSize;
|
||
|
HID_Handle->poll = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bInterval ;
|
||
|
|
||
|
if (HID_Handle->poll < HID_MIN_POLL)
|
||
|
{
|
||
|
HID_Handle->poll = HID_MIN_POLL;
|
||
|
}
|
||
|
|
||
|
/* Check fo available number of endpoints */
|
||
|
/* Find the number of EPs in the Interface Descriptor */
|
||
|
/* Choose the lower number in order not to overrun the buffer allocated */
|
||
|
max_ep = ( (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) ?
|
||
|
phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bNumEndpoints :
|
||
|
USBH_MAX_NUM_ENDPOINTS);
|
||
|
|
||
|
|
||
|
/* Decode endpoint IN and OUT address from interface descriptor */
|
||
|
for ( ;num < max_ep; num++)
|
||
|
{
|
||
|
if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[num].bEndpointAddress & 0x80)
|
||
|
{
|
||
|
HID_Handle->InEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[num].bEndpointAddress);
|
||
|
HID_Handle->InPipe =\
|
||
|
USBH_AllocPipe(phost, HID_Handle->InEp);
|
||
|
|
||
|
/* Open pipe for IN endpoint */
|
||
|
USBH_OpenPipe (phost,
|
||
|
HID_Handle->InPipe,
|
||
|
HID_Handle->InEp,
|
||
|
phost->device.address,
|
||
|
phost->device.speed,
|
||
|
USB_EP_TYPE_INTR,
|
||
|
HID_Handle->length);
|
||
|
|
||
|
USBH_LL_SetToggle (phost, HID_Handle->InPipe, 0);
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
HID_Handle->OutEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[num].bEndpointAddress);
|
||
|
HID_Handle->OutPipe =\
|
||
|
USBH_AllocPipe(phost, HID_Handle->OutEp);
|
||
|
|
||
|
/* Open pipe for OUT endpoint */
|
||
|
USBH_OpenPipe (phost,
|
||
|
HID_Handle->OutPipe,
|
||
|
HID_Handle->OutEp,
|
||
|
phost->device.address,
|
||
|
phost->device.speed,
|
||
|
USB_EP_TYPE_INTR,
|
||
|
HID_Handle->length);
|
||
|
|
||
|
USBH_LL_SetToggle (phost, HID_Handle->OutPipe, 0);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
status = USBH_OK;
|
||
|
}
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief USBH_HID_InterfaceDeInit
|
||
|
* The function DeInit the Pipes used for the HID class.
|
||
|
* @param phost: Host handle
|
||
|
* @retval USBH Status
|
||
|
*/
|
||
|
USBH_StatusTypeDef USBH_HID_InterfaceDeInit (USBH_HandleTypeDef *phost )
|
||
|
{
|
||
|
HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData;
|
||
|
|
||
|
if(HID_Handle->InPipe != 0x00)
|
||
|
{
|
||
|
USBH_ClosePipe (phost, HID_Handle->InPipe);
|
||
|
USBH_FreePipe (phost, HID_Handle->InPipe);
|
||
|
HID_Handle->InPipe = 0; /* Reset the pipe as Free */
|
||
|
}
|
||
|
|
||
|
if(HID_Handle->OutPipe != 0x00)
|
||
|
{
|
||
|
USBH_ClosePipe(phost, HID_Handle->OutPipe);
|
||
|
USBH_FreePipe (phost, HID_Handle->OutPipe);
|
||
|
HID_Handle->OutPipe = 0; /* Reset the pipe as Free */
|
||
|
}
|
||
|
|
||
|
if(phost->pActiveClass->pData)
|
||
|
{
|
||
|
USBH_free (phost->pActiveClass->pData);
|
||
|
}
|
||
|
|
||
|
return USBH_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief USBH_HID_ClassRequest
|
||
|
* The function is responsible for handling Standard requests
|
||
|
* for HID class.
|
||
|
* @param phost: Host handle
|
||
|
* @retval USBH Status
|
||
|
*/
|
||
|
static USBH_StatusTypeDef USBH_HID_ClassRequest(USBH_HandleTypeDef *phost)
|
||
|
{
|
||
|
|
||
|
USBH_StatusTypeDef status = USBH_BUSY;
|
||
|
USBH_StatusTypeDef classReqStatus = USBH_BUSY;
|
||
|
HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData;
|
||
|
|
||
|
/* Switch HID state machine */
|
||
|
switch (HID_Handle->ctl_state)
|
||
|
{
|
||
|
case HID_REQ_INIT:
|
||
|
case HID_REQ_GET_HID_DESC:
|
||
|
|
||
|
/* Get HID Desc */
|
||
|
if (USBH_HID_GetHIDDescriptor (phost, USB_HID_DESC_SIZE)== USBH_OK)
|
||
|
{
|
||
|
|
||
|
USBH_HID_ParseHIDDesc(&HID_Handle->HID_Desc, phost->device.Data);
|
||
|
HID_Handle->ctl_state = HID_REQ_GET_REPORT_DESC;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
case HID_REQ_GET_REPORT_DESC:
|
||
|
|
||
|
|
||
|
/* Get Report Desc */
|
||
|
if (USBH_HID_GetHIDReportDescriptor(phost, HID_Handle->HID_Desc.wItemLength) == USBH_OK)
|
||
|
{
|
||
|
/* The decriptor is available in phost->device.Data */
|
||
|
|
||
|
HID_Handle->ctl_state = HID_REQ_SET_IDLE;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case HID_REQ_SET_IDLE:
|
||
|
|
||
|
classReqStatus = USBH_HID_SetIdle (phost, 0, 0);
|
||
|
|
||
|
/* set Idle */
|
||
|
if (classReqStatus == USBH_OK)
|
||
|
{
|
||
|
HID_Handle->ctl_state = HID_REQ_SET_PROTOCOL;
|
||
|
}
|
||
|
else if(classReqStatus == USBH_NOT_SUPPORTED)
|
||
|
{
|
||
|
HID_Handle->ctl_state = HID_REQ_SET_PROTOCOL;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case HID_REQ_SET_PROTOCOL:
|
||
|
/* set protocol */
|
||
|
if (USBH_HID_SetProtocol (phost, 0) == USBH_OK)
|
||
|
{
|
||
|
HID_Handle->ctl_state = HID_REQ_IDLE;
|
||
|
|
||
|
/* all requests performed*/
|
||
|
phost->pUser(phost, HOST_USER_CLASS_ACTIVE);
|
||
|
status = USBH_OK;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case HID_REQ_IDLE:
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief USBH_HID_Process
|
||
|
* The function is for managing state machine for HID data transfers
|
||
|
* @param phost: Host handle
|
||
|
* @retval USBH Status
|
||
|
*/
|
||
|
static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost)
|
||
|
{
|
||
|
USBH_StatusTypeDef status = USBH_OK;
|
||
|
HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData;
|
||
|
|
||
|
switch (HID_Handle->state)
|
||
|
{
|
||
|
case HID_INIT:
|
||
|
HID_Handle->Init(phost);
|
||
|
case HID_IDLE:
|
||
|
if(USBH_HID_GetReport (phost,
|
||
|
0x01,
|
||
|
0,
|
||
|
HID_Handle->pData,
|
||
|
HID_Handle->length) == USBH_OK)
|
||
|
{
|
||
|
|
||
|
fifo_write(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length);
|
||
|
HID_Handle->state = HID_SYNC;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case HID_SYNC:
|
||
|
|
||
|
/* Sync with start of Even Frame */
|
||
|
if(phost->Timer & 1)
|
||
|
{
|
||
|
HID_Handle->state = HID_GET_DATA;
|
||
|
}
|
||
|
#if (USBH_USE_OS == 1)
|
||
|
osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
|
||
|
#endif
|
||
|
break;
|
||
|
|
||
|
case HID_GET_DATA:
|
||
|
|
||
|
USBH_InterruptReceiveData(phost,
|
||
|
HID_Handle->pData,
|
||
|
HID_Handle->length,
|
||
|
HID_Handle->InPipe);
|
||
|
|
||
|
HID_Handle->state = HID_POLL;
|
||
|
HID_Handle->timer = phost->Timer;
|
||
|
HID_Handle->DataReady = 0;
|
||
|
break;
|
||
|
|
||
|
case HID_POLL:
|
||
|
|
||
|
if(USBH_LL_GetURBState(phost , HID_Handle->InPipe) == USBH_URB_DONE)
|
||
|
{
|
||
|
if(HID_Handle->DataReady == 0)
|
||
|
{
|
||
|
fifo_write(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length);
|
||
|
HID_Handle->DataReady = 1;
|
||
|
USBH_HID_EventCallback(phost);
|
||
|
#if (USBH_USE_OS == 1)
|
||
|
osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
else if(USBH_LL_GetURBState(phost , HID_Handle->InPipe) == USBH_URB_STALL) /* IN Endpoint Stalled */
|
||
|
{
|
||
|
|
||
|
/* Issue Clear Feature on interrupt IN endpoint */
|
||
|
if(USBH_ClrFeature(phost,
|
||
|
HID_Handle->ep_addr) == USBH_OK)
|
||
|
{
|
||
|
/* Change state to issue next IN token */
|
||
|
HID_Handle->state = HID_GET_DATA;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief USBH_HID_SOFProcess
|
||
|
* The function is for managing the SOF Process
|
||
|
* @param phost: Host handle
|
||
|
* @retval USBH Status
|
||
|
*/
|
||
|
static USBH_StatusTypeDef USBH_HID_SOFProcess(USBH_HandleTypeDef *phost)
|
||
|
{
|
||
|
HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData;
|
||
|
|
||
|
if(HID_Handle->state == HID_POLL)
|
||
|
{
|
||
|
if(( phost->Timer - HID_Handle->timer) >= HID_Handle->poll)
|
||
|
{
|
||
|
HID_Handle->state = HID_GET_DATA;
|
||
|
#if (USBH_USE_OS == 1)
|
||
|
osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
return USBH_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief USBH_Get_HID_ReportDescriptor
|
||
|
* Issue report Descriptor command to the device. Once the response
|
||
|
* received, parse the report descriptor and update the status.
|
||
|
* @param phost: Host handle
|
||
|
* @param Length : HID Report Descriptor Length
|
||
|
* @retval USBH Status
|
||
|
*/
|
||
|
USBH_StatusTypeDef USBH_HID_GetHIDReportDescriptor (USBH_HandleTypeDef *phost,
|
||
|
uint16_t length)
|
||
|
{
|
||
|
|
||
|
USBH_StatusTypeDef status;
|
||
|
|
||
|
status = USBH_GetDescriptor(phost,
|
||
|
USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_STANDARD,
|
||
|
USB_DESC_HID_REPORT,
|
||
|
phost->device.Data,
|
||
|
length);
|
||
|
|
||
|
/* HID report descriptor is available in phost->device.Data.
|
||
|
In case of USB Boot Mode devices for In report handling ,
|
||
|
HID report descriptor parsing is not required.
|
||
|
In case, for supporting Non-Boot Protocol devices and output reports,
|
||
|
user may parse the report descriptor*/
|
||
|
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief USBH_Get_HID_Descriptor
|
||
|
* Issue HID Descriptor command to the device. Once the response
|
||
|
* received, parse the report descriptor and update the status.
|
||
|
* @param phost: Host handle
|
||
|
* @param Length : HID Descriptor Length
|
||
|
* @retval USBH Status
|
||
|
*/
|
||
|
USBH_StatusTypeDef USBH_HID_GetHIDDescriptor (USBH_HandleTypeDef *phost,
|
||
|
uint16_t length)
|
||
|
{
|
||
|
|
||
|
USBH_StatusTypeDef status;
|
||
|
|
||
|
status = USBH_GetDescriptor( phost,
|
||
|
USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_STANDARD,
|
||
|
USB_DESC_HID,
|
||
|
phost->device.Data,
|
||
|
length);
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief USBH_Set_Idle
|
||
|
* Set Idle State.
|
||
|
* @param phost: Host handle
|
||
|
* @param duration: Duration for HID Idle request
|
||
|
* @param reportId : Targetted report ID for Set Idle request
|
||
|
* @retval USBH Status
|
||
|
*/
|
||
|
USBH_StatusTypeDef USBH_HID_SetIdle (USBH_HandleTypeDef *phost,
|
||
|
uint8_t duration,
|
||
|
uint8_t reportId)
|
||
|
{
|
||
|
|
||
|
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.wIndex.w = 0;
|
||
|
phost->Control.setup.b.wLength.w = 0;
|
||
|
|
||
|
return USBH_CtlReq(phost, 0 , 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief USBH_HID_Set_Report
|
||
|
* Issues Set Report
|
||
|
* @param phost: Host handle
|
||
|
* @param reportType : Report type to be sent
|
||
|
* @param reportId : Targetted report ID for Set Report request
|
||
|
* @param reportBuff : Report Buffer
|
||
|
* @param reportLen : Length of data report to be send
|
||
|
* @retval USBH Status
|
||
|
*/
|
||
|
USBH_StatusTypeDef USBH_HID_SetReport (USBH_HandleTypeDef *phost,
|
||
|
uint8_t reportType,
|
||
|
uint8_t reportId,
|
||
|
uint8_t* reportBuff,
|
||
|
uint8_t reportLen)
|
||
|
{
|
||
|
|
||
|
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;
|
||
|
|
||
|
return USBH_CtlReq(phost, reportBuff , reportLen );
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief USBH_HID_GetReport
|
||
|
* retreive Set Report
|
||
|
* @param phost: Host handle
|
||
|
* @param reportType : Report type to be sent
|
||
|
* @param reportId : Targetted report ID for Set Report request
|
||
|
* @param reportBuff : Report Buffer
|
||
|
* @param reportLen : Length of data report to be send
|
||
|
* @retval USBH Status
|
||
|
*/
|
||
|
USBH_StatusTypeDef USBH_HID_GetReport (USBH_HandleTypeDef *phost,
|
||
|
uint8_t reportType,
|
||
|
uint8_t reportId,
|
||
|
uint8_t* reportBuff,
|
||
|
uint8_t reportLen)
|
||
|
{
|
||
|
|
||
|
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.wIndex.w = 0;
|
||
|
phost->Control.setup.b.wLength.w = reportLen;
|
||
|
|
||
|
return USBH_CtlReq(phost, reportBuff , reportLen );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief USBH_Set_Protocol
|
||
|
* Set protocol State.
|
||
|
* @param phost: Host handle
|
||
|
* @param protocol : Set Protocol for HID : boot/report protocol
|
||
|
* @retval USBH Status
|
||
|
*/
|
||
|
USBH_StatusTypeDef USBH_HID_SetProtocol(USBH_HandleTypeDef *phost,
|
||
|
uint8_t protocol)
|
||
|
{
|
||
|
|
||
|
|
||
|
phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\
|
||
|
USB_REQ_TYPE_CLASS;
|
||
|
|
||
|
|
||
|
phost->Control.setup.b.bRequest = USB_HID_SET_PROTOCOL;
|
||
|
phost->Control.setup.b.wValue.w = protocol != 0 ? 0 : 1;
|
||
|
phost->Control.setup.b.wIndex.w = 0;
|
||
|
phost->Control.setup.b.wLength.w = 0;
|
||
|
|
||
|
return USBH_CtlReq(phost, 0 , 0 );
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief USBH_ParseHIDDesc
|
||
|
* This function Parse the HID descriptor
|
||
|
* @param desc: HID Descriptor
|
||
|
* @param buf: Buffer where the source descriptor is available
|
||
|
* @retval None
|
||
|
*/
|
||
|
static void USBH_HID_ParseHIDDesc (HID_DescTypeDef *desc, uint8_t *buf)
|
||
|
{
|
||
|
|
||
|
desc->bLength = *(uint8_t *) (buf + 0);
|
||
|
desc->bDescriptorType = *(uint8_t *) (buf + 1);
|
||
|
desc->bcdHID = LE16 (buf + 2);
|
||
|
desc->bCountryCode = *(uint8_t *) (buf + 4);
|
||
|
desc->bNumDescriptors = *(uint8_t *) (buf + 5);
|
||
|
desc->bReportDescriptorType = *(uint8_t *) (buf + 6);
|
||
|
desc->wItemLength = LE16 (buf + 7);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief USBH_HID_GetDeviceType
|
||
|
* Return Device function.
|
||
|
* @param phost: Host handle
|
||
|
* @retval HID function: HID_MOUSE / HID_KEYBOARD
|
||
|
*/
|
||
|
HID_TypeTypeDef USBH_HID_GetDeviceType(USBH_HandleTypeDef *phost)
|
||
|
{
|
||
|
HID_TypeTypeDef type = HID_UNKNOWN;
|
||
|
|
||
|
if(phost->gState == HOST_CLASS)
|
||
|
{
|
||
|
|
||
|
if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol \
|
||
|
== HID_KEYBRD_BOOT_CODE)
|
||
|
{
|
||
|
type = HID_KEYBOARD;
|
||
|
}
|
||
|
else if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol \
|
||
|
== HID_MOUSE_BOOT_CODE)
|
||
|
{
|
||
|
type= HID_MOUSE;
|
||
|
}
|
||
|
}
|
||
|
return type;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief fifo_init
|
||
|
* Initialize FIFO.
|
||
|
* @param f: Fifo address
|
||
|
* @param buf: Fifo buffer
|
||
|
* @param size: Fifo Size
|
||
|
* @retval none
|
||
|
*/
|
||
|
void fifo_init(FIFO_TypeDef * f, uint8_t * buf, uint16_t size)
|
||
|
{
|
||
|
f->head = 0;
|
||
|
f->tail = 0;
|
||
|
f->lock = 0;
|
||
|
f->size = size;
|
||
|
f->buf = buf;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief fifo_read
|
||
|
* Read from FIFO.
|
||
|
* @param f: Fifo address
|
||
|
* @param buf: read buffer
|
||
|
* @param nbytes: number of item to read
|
||
|
* @retval number of read items
|
||
|
*/
|
||
|
uint16_t fifo_read(FIFO_TypeDef * f, void * buf, uint16_t nbytes)
|
||
|
{
|
||
|
uint16_t i;
|
||
|
uint8_t * p;
|
||
|
p = buf;
|
||
|
|
||
|
if(f->lock == 0)
|
||
|
{
|
||
|
f->lock = 1;
|
||
|
for(i=0; i < nbytes; i++)
|
||
|
{
|
||
|
if( f->tail != f->head )
|
||
|
{
|
||
|
*p++ = f->buf[f->tail];
|
||
|
f->tail++;
|
||
|
if( f->tail == f->size )
|
||
|
{
|
||
|
f->tail = 0;
|
||
|
}
|
||
|
} else
|
||
|
{
|
||
|
f->lock = 0;
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
f->lock = 0;
|
||
|
return nbytes;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief fifo_write
|
||
|
* Read from FIFO.
|
||
|
* @param f: Fifo address
|
||
|
* @param buf: read buffer
|
||
|
* @param nbytes: number of item to write
|
||
|
* @retval number of written items
|
||
|
*/
|
||
|
uint16_t fifo_write(FIFO_TypeDef * f, const void * buf, uint16_t nbytes)
|
||
|
{
|
||
|
uint16_t i;
|
||
|
const uint8_t * p;
|
||
|
p = buf;
|
||
|
if(f->lock == 0)
|
||
|
{
|
||
|
f->lock = 1;
|
||
|
for(i=0; i < nbytes; i++)
|
||
|
{
|
||
|
if( (f->head + 1 == f->tail) ||
|
||
|
( (f->head + 1 == f->size) && (f->tail == 0)) )
|
||
|
{
|
||
|
f->lock = 0;
|
||
|
return i;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
f->buf[f->head] = *p++;
|
||
|
f->head++;
|
||
|
if( f->head == f->size )
|
||
|
{
|
||
|
f->head = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
f->lock = 0;
|
||
|
return nbytes;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief The function is a callback about HID Data events
|
||
|
* @param phost: Selected device
|
||
|
* @retval None
|
||
|
*/
|
||
|
__weak void USBH_HID_EventCallback(USBH_HandleTypeDef *phost)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|