/** ****************************************************************************** * @file usbd_hid.c * @author MCD Application Team * @version V2.0.0 * @date 18-February-2014 * @brief This file provides the CUSTOM_HID core functions. * * @verbatim * * =================================================================== * CUSTOM_HID Class Description * =================================================================== * This module manages the CUSTOM_HID class V1.11 following the "Device Class Definition * for Human Interface Devices (CUSTOM_HID) Version 1.11 Jun 27, 2001". * This driver implements the following aspects of the specification: * - The Boot Interface Subclass * - The Mouse protocol * - Usage Page : Generic Desktop * - Usage : Joystick) * - Collection : Application * * @note In HS mode and when the DMA is used, all variables and data structures * dealing with the DMA during the transaction process should be 32-bit aligned. * * * @endverbatim * ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * 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 "usbd_customhid.h" #include "usbd_desc.h" #include "usbd_ctlreq.h" /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @{ */ /** @defgroup USBD_CUSTOM_HID * @brief usbd core module * @{ */ /** @defgroup USBD_CUSTOM_HID_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBD_CUSTOM_HID_Private_Defines * @{ */ /** * @} */ /** @defgroup USBD_CUSTOM_HID_Private_Macros * @{ */ /** * @} */ uint8_t Report_buf[2]; extern uint8_t PrevXferDone; uint32_t flag = 0; uint8_t USBD_CUSTOM_HID_Report_ID=0; /** @defgroup USBD_CUSTOM_HID_Private_FunctionPrototypes * @{ */ static uint8_t USBD_CUSTOM_HID_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx); static uint8_t USBD_CUSTOM_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_CUSTOM_HID_GetCfgDesc (uint16_t *length); static uint8_t *USBD_CUSTOM_HID_GetDeviceQualifierDesc (uint16_t *length); static uint8_t USBD_CUSTOM_HID_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum); static uint8_t USBD_CUSTOM_HID_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum); static uint8_t USBD_CUSTOM_HID_EP0_RxReady (USBD_HandleTypeDef *pdev); /** * @} */ /** @defgroup USBD_CUSTOM_HID_Private_Variables * @{ */ USBD_ClassTypeDef USBD_CUSTOM_HID = { USBD_CUSTOM_HID_Init, USBD_CUSTOM_HID_DeInit, USBD_CUSTOM_HID_Setup, NULL, /*EP0_TxSent*/ USBD_CUSTOM_HID_EP0_RxReady, /*EP0_RxReady*/ /* STATUS STAGE IN */ USBD_CUSTOM_HID_DataIn, /*DataIn*/ USBD_CUSTOM_HID_DataOut, NULL, /*SOF */ NULL, NULL, USBD_CUSTOM_HID_GetCfgDesc, USBD_CUSTOM_HID_GetCfgDesc, USBD_CUSTOM_HID_GetCfgDesc, USBD_CUSTOM_HID_GetDeviceQualifierDesc, }; /* USB CUSTOM_HID device Configuration Descriptor */ __ALIGN_BEGIN static uint8_t USBD_CUSTOM_HID_CfgDesc[USB_CUSTOM_HID_CONFIG_DESC_SIZ] __ALIGN_END = { 0x09, /* bLength: Configuration Descriptor size */ USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ USB_CUSTOM_HID_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */ 0x00, 0x01, /*bNumInterfaces: 1 interface*/ 0x01, /*bConfigurationValue: Configuration value*/ 0x00, /*iConfiguration: Index of string descriptor describing the configuration*/ 0xC0, /*bmAttributes: bus powered */ 0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/ /************** Descriptor of CUSTOM HID interface ****************/ /* 09 */ 0x09, /*bLength: Interface Descriptor size*/ USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/ 0x00, /*bInterfaceNumber: Number of Interface*/ 0x00, /*bAlternateSetting: Alternate setting*/ 0x02, /*bNumEndpoints*/ 0x03, /*bInterfaceClass: CUSTOM_HID*/ 0x00, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/ 0x00, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/ 0, /*iInterface: Index of string descriptor*/ /******************** Descriptor of CUSTOM_HID *************************/ /* 18 */ 0x09, /*bLength: CUSTOM_HID Descriptor size*/ CUSTOM_HID_DESCRIPTOR_TYPE, /*bDescriptorType: CUSTOM_HID*/ 0x11, /*bcdCUSTOM_HID: CUSTOM_HID Class Spec release number*/ 0x01, 0x00, /*bCountryCode: Hardware target country*/ 0x01, /*bNumDescriptors: Number of CUSTOM_HID class descriptors to follow*/ 0x22, /*bDescriptorType*/ CUSTOM_HID_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/ 0x00, /******************** Descriptor of Custom HID endpoints ********************/ /* 27 */ 0x07, /*bLength: Endpoint Descriptor size*/ USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/ CUSTOM_HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/ 0x03, /*bmAttributes: Interrupt endpoint*/ CUSTOM_HID_EPIN_SIZE, /*wMaxPacketSize: 2 Byte max */ 0x00, 0x20, /*bInterval: Polling Interval (20 ms)*/ /* 34 */ 0x07, /* bLength: Endpoint Descriptor size */ USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */ CUSTOM_HID_EPOUT_ADDR, /*bEndpointAddress: Endpoint Address (OUT)*/ 0x03, /* bmAttributes: Interrupt endpoint */ CUSTOM_HID_EPOUT_SIZE, /* wMaxPacketSize: 2 Bytes max */ 0x00, 0x20, /* bInterval: Polling Interval (20 ms) */ /* 41 */ } ; /* USB CUSTOM_HID device Configuration Descriptor */ __ALIGN_BEGIN static uint8_t USBD_CUSTOM_HID_Desc[USB_CUSTOM_HID_DESC_SIZ] __ALIGN_END = { /* 18 */ 0x09, /*bLength: CUSTOM_HID Descriptor size*/ CUSTOM_HID_DESCRIPTOR_TYPE, /*bDescriptorType: CUSTOM_HID*/ 0x11, /*bcdCUSTOM_HID: CUSTOM_HID Class Spec release number*/ 0x01, 0x00, /*bCountryCode: Hardware target country*/ 0x01, /*bNumDescriptors: Number of CUSTOM_HID class descriptors to follow*/ 0x22, /*bDescriptorType*/ CUSTOM_HID_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/ 0x00, }; /* USB Standard Device Descriptor */ __ALIGN_BEGIN static uint8_t USBD_CUSTOM_HID_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END = { USB_LEN_DEV_QUALIFIER_DESC, USB_DESC_TYPE_DEVICE_QUALIFIER, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, }; __ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc[CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END = { 0x06, 0xFF, 0x00, /* USAGE_PAGE (Vendor Page: 0xFF00) */ 0x09, 0x01, /* USAGE (Demo Kit) */ 0xa1, 0x01, /* COLLECTION (Application) */ /* 6 */ /* Led 1 */ 0x85, 0x01, /* REPORT_ID (1) */ 0x09, 0x01, /* USAGE (LED 1) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ 0x75, 0x08, /* REPORT_SIZE (8) */ 0x95, 0x01, /* REPORT_COUNT (1) */ 0xB1, 0x82, /* FEATURE (Data,Var,Abs,Vol) */ 0x85, 0x01, /* REPORT_ID (1) */ 0x09, 0x01, /* USAGE (LED 1) */ 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ /* 26 */ /* Led 2 */ 0x85, 0x02, /* REPORT_ID 2 */ 0x09, 0x02, /* USAGE (LED 2) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ 0x75, 0x08, /* REPORT_SIZE (8) */ 0x95, 0x01, /* REPORT_COUNT (1) */ 0xB1, 0x82, /* FEATURE (Data,Var,Abs,Vol) */ 0x85, 0x02, /* REPORT_ID (2) */ 0x09, 0x02, /* USAGE (LED 2) */ 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ /* 46 */ /* Led 3 */ 0x85, 0x03, /* REPORT_ID (3) */ 0x09, 0x03, /* USAGE (LED 3) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ 0x75, 0x08, /* REPORT_SIZE (8) */ 0x95, 0x01, /* REPORT_COUNT (1) */ 0xB1, 0x82, /* FEATURE (Data,Var,Abs,Vol) */ 0x85, 0x03, /* REPORT_ID (3) */ 0x09, 0x03, /* USAGE (LED 3) */ 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ /* 66 */ /* Led 4 */ 0x85, 0x04, /* REPORT_ID 4) */ 0x09, 0x04, /* USAGE (LED 4) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ 0x75, 0x08, /* REPORT_SIZE (8) */ 0x95, 0x01, /* REPORT_COUNT (1) */ 0xB1, 0x82, /* FEATURE (Data,Var,Abs,Vol) */ 0x85, 0x04, /* REPORT_ID (4) */ 0x09, 0x04, /* USAGE (LED 4) */ 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ /* 86 */ /* key Push Button */ 0x85, 0x05, /* REPORT_ID (5) */ 0x09, 0x05, /* USAGE (Push Button) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ 0x75, 0x01, /* REPORT_SIZE (1) */ 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ 0x09, 0x05, /* USAGE (Push Button) */ 0x75, 0x01, /* REPORT_SIZE (1) */ 0xb1, 0x82, /* FEATURE (Data,Var,Abs,Vol) */ 0x75, 0x07, /* REPORT_SIZE (7) */ 0x81, 0x83, /* INPUT (Cnst,Var,Abs,Vol) */ 0x85, 0x05, /* REPORT_ID (2) */ 0x75, 0x07, /* REPORT_SIZE (7) */ 0xb1, 0x83, /* FEATURE (Cnst,Var,Abs,Vol) */ /* 114 */ /* Tamper Push Button */ 0x85, 0x06, /* REPORT_ID (6) */ 0x09, 0x06, /* USAGE (Tamper Push Button) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ 0x75, 0x01, /* REPORT_SIZE (1) */ 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ 0x09, 0x06, /* USAGE (Tamper Push Button) */ 0x75, 0x01, /* REPORT_SIZE (1) */ 0xb1, 0x82, /* FEATURE (Data,Var,Abs,Vol) */ 0x75, 0x07, /* REPORT_SIZE (7) */ 0x81, 0x83, /* INPUT (Cnst,Var,Abs,Vol) */ 0x85, 0x06, /* REPORT_ID (6) */ 0x75, 0x07, /* REPORT_SIZE (7) */ 0xb1, 0x83, /* FEATURE (Cnst,Var,Abs,Vol) */ /* 142 */ /* ADC IN */ 0x85, 0x07, /* REPORT_ID (7) */ 0x09, 0x07, /* USAGE (ADC IN) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ 0x75, 0x08, /* REPORT_SIZE (8) */ 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ 0x85, 0x07, /* REPORT_ID (7) */ 0x09, 0x07, /* USAGE (ADC in) */ 0xb1, 0x82, /* FEATURE (Data,Var,Abs,Vol) */ /* 161 */ 0xc0 /* END_COLLECTION */ }; /** * @} */ /** @defgroup USBD_CUSTOM_HID_Private_Functions * @{ */ /** * @brief USBD_CUSTOM_HID_Init * Initialize the CUSTOM_HID interface * @param pdev: device instance * @param cfgidx: Configuration index * @retval status */ static uint8_t USBD_CUSTOM_HID_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx) { uint8_t ret = 0; /* Open EP IN */ USBD_LL_OpenEP(pdev, CUSTOM_HID_EPIN_ADDR, USBD_EP_TYPE_INTR, CUSTOM_HID_EPIN_SIZE); /* Open EP OUT */ USBD_LL_OpenEP(pdev, CUSTOM_HID_EPOUT_ADDR, USBD_EP_TYPE_INTR, CUSTOM_HID_EPOUT_SIZE); pdev->pClassData = USBD_malloc(sizeof (USBD_CUSTOM_HID_HandleTypeDef)); if(pdev->pClassData == NULL) { ret = 1; } else { ((USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassData)->state = CUSTOM_HID_IDLE; /* Prepare Out endpoint to receive 1st packet */ USBD_LL_PrepareReceive(pdev, CUSTOM_HID_EPOUT_ADDR , Report_buf , 2); } return ret; } /** * @brief USBD_CUSTOM_HID_Init * DeInitialize the CUSTOM_HID layer * @param pdev: device instance * @param cfgidx: Configuration index * @retval status */ static uint8_t USBD_CUSTOM_HID_DeInit (USBD_HandleTypeDef *pdev, uint8_t cfgidx) { /* Close CUSTOM_HID EP IN */ USBD_LL_CloseEP(pdev, CUSTOM_HID_EPIN_SIZE); /* Close CUSTOM_HID EP OUT */ USBD_LL_CloseEP(pdev, CUSTOM_HID_EPOUT_SIZE); /* FRee allocated memory */ if(pdev->pClassData != NULL) { USBD_free(pdev->pClassData); pdev->pClassData = NULL; } return USBD_OK; } /** * @brief USBD_CUSTOM_HID_Setup * Handle the CUSTOM_HID specific requests * @param pdev: instance * @param req: usb requests * @retval status */ static uint8_t USBD_CUSTOM_HID_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) { uint8_t USBD_CUSTOM_HID_Report_LENGTH=0; uint16_t len = 0; uint8_t *pbuf = NULL; USBD_CUSTOM_HID_HandleTypeDef *hhid = pdev->pClassData; switch (req->bmRequest & USB_REQ_TYPE_MASK) { case USB_REQ_TYPE_CLASS : switch (req->bRequest) { case CUSTOM_HID_REQ_SET_PROTOCOL: hhid->Protocol = (uint8_t)(req->wValue); break; case CUSTOM_HID_REQ_GET_PROTOCOL: USBD_CtlSendData (pdev, (uint8_t *)&hhid->Protocol, 1); break; case CUSTOM_HID_REQ_SET_IDLE: hhid->IdleState = (uint8_t)(req->wValue >> 8); break; case CUSTOM_HID_REQ_GET_IDLE: USBD_CtlSendData (pdev, (uint8_t *)&hhid->IdleState, 1); break; case CUSTOM_HID_REQ_SET_REPORT: flag = 1; USBD_CUSTOM_HID_Report_ID = (uint8_t)(req->wValue); USBD_CUSTOM_HID_Report_LENGTH = (uint8_t)(req->wLength); USBD_CtlPrepareRx (pdev, Report_buf, USBD_CUSTOM_HID_Report_LENGTH); break; default: USBD_CtlError (pdev, req); return USBD_FAIL; } break; case USB_REQ_TYPE_STANDARD: switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: if( req->wValue >> 8 == CUSTOM_HID_REPORT_DESC) { len = MIN(CUSTOM_HID_REPORT_DESC_SIZE , req->wLength); pbuf = CUSTOM_HID_ReportDesc; } else if( req->wValue >> 8 == CUSTOM_HID_DESCRIPTOR_TYPE) { pbuf = USBD_CUSTOM_HID_Desc; len = MIN(USB_CUSTOM_HID_DESC_SIZ , req->wLength); } USBD_CtlSendData (pdev, pbuf, len); break; case USB_REQ_GET_INTERFACE : USBD_CtlSendData (pdev, (uint8_t *)&hhid->AltSetting, 1); break; case USB_REQ_SET_INTERFACE : hhid->AltSetting = (uint8_t)(req->wValue); break; } } return USBD_OK; } /** * @brief USBD_CUSTOM_HID_SendReport * Send CUSTOM_HID Report * @param pdev: device instance * @param buff: pointer to report * @retval status */ uint8_t USBD_CUSTOM_HID_SendReport (USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len) { USBD_CUSTOM_HID_HandleTypeDef *hhid = pdev->pClassData; if (pdev->dev_state == USBD_STATE_CONFIGURED ) { if(hhid->state == CUSTOM_HID_IDLE) { hhid->state = CUSTOM_HID_BUSY; USBD_LL_Transmit (pdev, CUSTOM_HID_EPIN_ADDR, report, len); } } return USBD_OK; } /** * @brief USBD_CUSTOM_HID_GetCfgDesc * return configuration descriptor * @param speed : current device speed * @param length : pointer data length * @retval pointer to descriptor buffer */ static uint8_t *USBD_CUSTOM_HID_GetCfgDesc (uint16_t *length) { *length = sizeof (USBD_CUSTOM_HID_CfgDesc); return USBD_CUSTOM_HID_CfgDesc; } /** * @brief USBD_CUSTOM_HID_DataIn * handle data IN Stage * @param pdev: device instance * @param epnum: endpoint index * @retval status */ static uint8_t USBD_CUSTOM_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 */ ((USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassData)->state = CUSTOM_HID_IDLE; if (epnum == 1) PrevXferDone = 1; return USBD_OK; } /** * @brief USBD_CUSTOM_HID_DataOut * handle data OUT Stage * @param pdev: device instance * @param epnum: endpoint index * @retval status */ static uint8_t USBD_CUSTOM_HID_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum) { USBD_HID_DataOutCallback(pdev, epnum); return USBD_OK; } /** * @brief USBD_CUSTOM_HID_EP0_RxReady * Handles control request data. * @param pdev: device instance * @retval status */ uint8_t USBD_CUSTOM_HID_EP0_RxReady(USBD_HandleTypeDef *pdev) { USBD_HID_EP0_DataOutCallback(pdev); return USBD_OK; } /** * @brief DeviceQualifierDescriptor * return Device Qualifier descriptor * @param length : pointer data length * @retval pointer to descriptor buffer */ static uint8_t *USBD_CUSTOM_HID_GetDeviceQualifierDesc (uint16_t *length) { *length = sizeof (USBD_CUSTOM_HID_DeviceQualifierDesc); return USBD_CUSTOM_HID_DeviceQualifierDesc; } /** * @brief The function is a callback about HID OUT Data events * @param pdev: device instance * @param epnum: endpoint index */ __weak void USBD_HID_DataOutCallback(USBD_HandleTypeDef *pdev, uint8_t epnum) { } __weak void USBD_HID_EP0_DataOutCallback(USBD_HandleTypeDef *pdev) { } /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/