diff --git a/Downstream/.cproject b/Downstream/.cproject index 32797fc..bddbb0a 100644 --- a/Downstream/.cproject +++ b/Downstream/.cproject @@ -58,6 +58,7 @@ + @@ -97,7 +98,7 @@ - + @@ -174,6 +175,7 @@ + @@ -212,7 +214,7 @@ - + diff --git a/Downstream/.settings/org.eclipse.cdt.codan.core.prefs b/Downstream/.settings/org.eclipse.cdt.codan.core.prefs index 77386c2..ff135cf 100644 --- a/Downstream/.settings/org.eclipse.cdt.codan.core.prefs +++ b/Downstream/.settings/org.eclipse.cdt.codan.core.prefs @@ -3,6 +3,10 @@ org.eclipse.cdt.codan.checkers.errnoreturn=Warning org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false} org.eclipse.cdt.codan.checkers.errreturnvalue=Error org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.checkers.nocommentinside=-Error +org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.checkers.nolinecomment=-Error +org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} org.eclipse.cdt.codan.checkers.noreturn=Error org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false} org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error diff --git a/Downstream/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hcd.c b/Downstream/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hcd.c index 9a9799c..0374010 100644 --- a/Downstream/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hcd.c +++ b/Downstream/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hcd.c @@ -879,11 +879,14 @@ static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum) hhcd->hc[chnum].urb_state = URB_NOTREADY; } - /* re-activate the channel */ - tmpreg = USBx_HC(chnum)->HCCHAR; - tmpreg &= ~USB_OTG_HCCHAR_CHDIS; - tmpreg |= USB_OTG_HCCHAR_CHENA; - USBx_HC(chnum)->HCCHAR = tmpreg; + if (hhcd->hc[chnum].ep_type != EP_TYPE_INTR) //DON'T re-enable an interrupt-in transaction + { + /* re-activate the channel */ + tmpreg = USBx_HC(chnum)->HCCHAR; + tmpreg &= ~USB_OTG_HCCHAR_CHDIS; + tmpreg |= USB_OTG_HCCHAR_CHENA; + USBx_HC(chnum)->HCCHAR = tmpreg; + } } __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH); HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state); diff --git a/Downstream/Inc/downstream_interface_def.h b/Downstream/Inc/downstream_interface_def.h index 435d6e8..b3dfaf2 100644 --- a/Downstream/Inc/downstream_interface_def.h +++ b/Downstream/Inc/downstream_interface_def.h @@ -15,7 +15,7 @@ //*************** // Attention! -// Keep this file synchronised with downstream_interface_def.h +// Keep this file synchronised with upstream_interface_def.h // in the Upstream project. //*************** @@ -29,6 +29,7 @@ typedef enum { COMMAND_CLASS_INTERFACE, COMMAND_CLASS_MASS_STORAGE, + COMMAND_CLASS_HID_MOUSE, //... COMMAND_CLASS_ERROR } @@ -53,6 +54,13 @@ typedef enum InterfaceCommandMscTypeDef; +typedef enum +{ + COMMAND_HID_REPORT, //Downstream initiates HID report transfer to Upstream. Upstream just needs to Upstream_ReceivePacket each time. +} +InterfaceCommandHidTypeDef; + + typedef enum { COMMAND_ERROR_GENERIC, diff --git a/Downstream/Inc/usbh_config.h b/Downstream/Inc/usbh_config.h index a576fa4..59e70eb 100644 --- a/Downstream/Inc/usbh_config.h +++ b/Downstream/Inc/usbh_config.h @@ -62,13 +62,13 @@ #define USBH_KEEP_CFG_DESCRIPTOR 1 /*---------- -----------*/ -#define USBH_MAX_NUM_SUPPORTED_CLASS 1 +#define USBH_MAX_NUM_SUPPORTED_CLASS 2 /*---------- -----------*/ #define USBH_MAX_SIZE_CONFIGURATION 256 /*---------- -----------*/ -#define USBH_MAX_DATA_BUFFER 512 +#define USBH_MAX_DATA_BUFFER 256 //was 512, string descriptors are max 255 bytes /*---------- -----------*/ #define USBH_DEBUG_LEVEL 0 diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid.h b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid.h new file mode 100644 index 0000000..1f292f3 --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid.h @@ -0,0 +1,350 @@ +/** + ****************************************************************************** + * @file usbh_hid.h + * @author MCD Application Team + * @version V3.2.2 + * @date 07-July-2015 + * @brief This file contains all the prototypes for the usbh_hid.c + ****************************************************************************** + * @attention + * + * © COPYRIGHT 2015 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_HID_H +#define __USBH_HID_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_core.h" +#include "usbh_hid_mouse.h" +#include "usbh_hid_keybd.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_CLASS + * @{ + */ + +/** @addtogroup USBH_HID_CLASS + * @{ + */ + +/** @defgroup USBH_HID_CORE + * @brief This file is the Header file for usbh_hid.c + * @{ + */ + + +/** @defgroup USBH_HID_CORE_Exported_Types + * @{ + */ + +#define HID_MIN_POLL 10 +#define HID_REPORT_SIZE 16 +#define HID_MAX_USAGE 10 +#define HID_MAX_NBR_REPORT_FMT 10 +#define HID_QUEUE_SIZE 10 + +#define HID_ITEM_LONG 0xFE + +#define HID_ITEM_TYPE_MAIN 0x00 +#define HID_ITEM_TYPE_GLOBAL 0x01 +#define HID_ITEM_TYPE_LOCAL 0x02 +#define HID_ITEM_TYPE_RESERVED 0x03 + + +#define HID_MAIN_ITEM_TAG_INPUT 0x08 +#define HID_MAIN_ITEM_TAG_OUTPUT 0x09 +#define HID_MAIN_ITEM_TAG_COLLECTION 0x0A +#define HID_MAIN_ITEM_TAG_FEATURE 0x0B +#define HID_MAIN_ITEM_TAG_ENDCOLLECTION 0x0C + + +#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0x00 +#define HID_GLOBAL_ITEM_TAG_LOG_MIN 0x01 +#define HID_GLOBAL_ITEM_TAG_LOG_MAX 0x02 +#define HID_GLOBAL_ITEM_TAG_PHY_MIN 0x03 +#define HID_GLOBAL_ITEM_TAG_PHY_MAX 0x04 +#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 0x05 +#define HID_GLOBAL_ITEM_TAG_UNIT 0x06 +#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 0x07 +#define HID_GLOBAL_ITEM_TAG_REPORT_ID 0x08 +#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 0x09 +#define HID_GLOBAL_ITEM_TAG_PUSH 0x0A +#define HID_GLOBAL_ITEM_TAG_POP 0x0B + + +#define HID_LOCAL_ITEM_TAG_USAGE 0x00 +#define HID_LOCAL_ITEM_TAG_USAGE_MIN 0x01 +#define HID_LOCAL_ITEM_TAG_USAGE_MAX 0x02 +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 0x03 +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MIN 0x04 +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAX 0x05 +#define HID_LOCAL_ITEM_TAG_STRING_INDEX 0x07 +#define HID_LOCAL_ITEM_TAG_STRING_MIN 0x08 +#define HID_LOCAL_ITEM_TAG_STRING_MAX 0x09 +#define HID_LOCAL_ITEM_TAG_DELIMITER 0x0A + + +/* States for HID State Machine */ +typedef enum +{ + HID_INIT= 0, + HID_IDLE, +// HID_SEND_DATA, +// HID_BUSY, + HID_GET_DATA, + HID_SYNC, + HID_POLL, + HID_ERROR, +} +HID_StateTypeDef; + +typedef enum +{ + HID_REQ_INIT = 0, + HID_REQ_IDLE, + HID_REQ_GET_REPORT_DESC, + HID_REQ_GET_HID_DESC, + HID_REQ_SET_IDLE, + HID_REQ_SET_PROTOCOL, + HID_REQ_SET_REPORT, + +} +HID_CtlStateTypeDef; + +typedef enum +{ + HID_MOUSE = 0x01, + HID_KEYBOARD = 0x02, + HID_UNKNOWN = 0xFF, +} +HID_TypeTypeDef; + + +typedef struct _HID_ReportData +{ + uint8_t ReportID; + uint8_t ReportType; + uint16_t UsagePage; + uint32_t Usage[HID_MAX_USAGE]; + uint32_t NbrUsage; + uint32_t UsageMin; + uint32_t UsageMax; + int32_t LogMin; + int32_t LogMax; + int32_t PhyMin; + int32_t PhyMax; + int32_t UnitExp; + uint32_t Unit; + uint32_t ReportSize; + uint32_t ReportCnt; + uint32_t Flag; + uint32_t PhyUsage; + uint32_t AppUsage; + uint32_t LogUsage; +} +HID_ReportDataTypeDef; + +typedef struct _HID_ReportIDTypeDef { + uint8_t Size; /* Report size return by the device id */ + uint8_t ReportID; /* Report Id */ + uint8_t Type; /* Report Type (INPUT/OUTPUT/FEATURE) */ +} HID_ReportIDTypeDef; + +typedef struct _HID_CollectionTypeDef +{ + uint32_t Usage; + uint8_t Type; + struct _HID_CollectionTypeDef *NextPtr; +} HID_CollectionTypeDef; + + +typedef struct _HID_AppCollectionTypeDef { + uint32_t Usage; + uint8_t Type; + uint8_t NbrReportFmt; + HID_ReportDataTypeDef ReportData[HID_MAX_NBR_REPORT_FMT]; +} HID_AppCollectionTypeDef; + + +typedef struct _HIDDescriptor +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdHID; /* indicates what endpoint this descriptor is describing */ + uint8_t bCountryCode; /* specifies the transfer type. */ + uint8_t bNumDescriptors; /* specifies the transfer type. */ + uint8_t bReportDescriptorType; /* Maximum Packet Size this endpoint is capable of sending or receiving */ + uint16_t wItemLength; /* is used to specify the polling interval of certain transfers. */ +} +HID_DescTypeDef; + + +typedef struct +{ + uint8_t *buf; + uint16_t head; + uint16_t tail; + uint16_t size; + uint8_t lock; +} FIFO_TypeDef; + + +/* Structure for HID process */ +typedef struct _HID_Process +{ + uint8_t OutPipe; + uint8_t InPipe; + HID_StateTypeDef state; + uint8_t OutEp; + uint8_t InEp; + HID_CtlStateTypeDef ctl_state; + FIFO_TypeDef fifo; + uint8_t *pData; + uint16_t length; + uint8_t ep_addr; + uint16_t poll; + uint32_t timer; +// uint8_t DataReady; + HID_DescTypeDef HID_Desc; + //USBH_StatusTypeDef ( * Init)(USBH_HandleTypeDef *phost); +} +HID_HandleTypeDef; + +/** + * @} + */ + +/** @defgroup USBH_HID_CORE_Exported_Defines + * @{ + */ + +#define USB_HID_GET_REPORT 0x01 +#define USB_HID_GET_IDLE 0x02 +#define USB_HID_GET_PROTOCOL 0x03 +#define USB_HID_SET_REPORT 0x09 +#define USB_HID_SET_IDLE 0x0A +#define USB_HID_SET_PROTOCOL 0x0B + + + + +/* HID Class Codes */ +#define USB_HID_CLASS 0x03 + +/* Interface Descriptor field values for HID Boot Protocol */ +#define HID_BOOT_CODE 0x01 +#define HID_KEYBRD_BOOT_CODE 0x01 +#define HID_MOUSE_BOOT_CODE 0x02 + + +/** + * @} + */ + +/** @defgroup USBH_HID_CORE_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_HID_CORE_Exported_Variables + * @{ + */ +extern USBH_ClassTypeDef HID_Class; +#define USBH_HID_CLASS &HID_Class +/** + * @} + */ + +/** @defgroup USBH_HID_CORE_Exported_FunctionsPrototype + * @{ + */ + +USBH_StatusTypeDef USBH_HID_SetReport (USBH_HandleTypeDef *phost, + uint8_t reportType, + uint8_t reportId, + uint8_t* reportBuff, + uint8_t reportLen); + +USBH_StatusTypeDef USBH_HID_GetReport (USBH_HandleTypeDef *phost, + uint8_t reportType, + uint8_t reportId, + uint8_t* reportBuff, + uint8_t reportLen); + +USBH_StatusTypeDef USBH_HID_GetHIDReportDescriptor (USBH_HandleTypeDef *phost, + uint16_t length); + +USBH_StatusTypeDef USBH_HID_GetHIDDescriptor (USBH_HandleTypeDef *phost, + uint16_t length); + +USBH_StatusTypeDef USBH_HID_SetIdle (USBH_HandleTypeDef *phost, + uint8_t duration, + uint8_t reportId); + +USBH_StatusTypeDef USBH_HID_SetProtocol (USBH_HandleTypeDef *phost, + uint8_t protocol); + +void USBH_HID_EventCallback(USBH_HandleTypeDef *phost); + +HID_TypeTypeDef USBH_HID_GetDeviceType(USBH_HandleTypeDef *phost); + +uint8_t USBH_HID_GetPollInterval(USBH_HandleTypeDef *phost); + +void fifo_init(FIFO_TypeDef * f, uint8_t * buf, uint16_t size); + +uint16_t fifo_read(FIFO_TypeDef * f, void * buf, uint16_t nbytes); + +uint16_t fifo_write(FIFO_TypeDef * f, const void * buf, uint16_t nbytes); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_HID_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid.c b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid.c new file mode 100644 index 0000000..972bf23 --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid.c @@ -0,0 +1,824 @@ +/** + ****************************************************************************** + * @file usbh_hid.c + * @author MCD Application Team + * @version V3.2.2 + * @date 07-July-2015 + * @brief This file is the HID Layer Handlers for USB Host HID class. + * + * @verbatim + * + * =================================================================== + * HID Class Description + * =================================================================== + * This module manages the HID 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 + * + * © COPYRIGHT 2015 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. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ + +/* 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 = (HID_HandleTypeDef *) phost->pActiveClass->pData; + HID_Handle->state = HID_ERROR; + + /*Decode Bootclass Protocol: 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 = (HID_HandleTypeDef *) 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 = (HID_HandleTypeDef *) 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_SET_IDLE; //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 descriptor 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_URBStateTypeDef urbStatus; + HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData; + + switch (HID_Handle->state) + { + case HID_INIT: +// HID_Handle->Init(phost); + HID_Handle->pData = phost->device.Data; + +// 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 */ + //Uhhh, doesn't this sync with an odd frame? + //Also, do we need to sync at all? + + if(phost->Timer & 1) + { + HID_Handle->state = HID_GET_DATA; + } + 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; + break; + + case HID_POLL: + urbStatus = USBH_LL_GetURBState(phost , HID_Handle->InPipe); + + if (urbStatus == USBH_URB_DONE) + { + USBH_HID_EventCallback(phost); + HID_Handle->state = HID_IDLE; + break; + } + + if (urbStatus == USBH_URB_NOTREADY) + { + HID_Handle->state = HID_IDLE; + break; + } + + if (urbStatus == USBH_URB_STALL) + { + /* Issue Clear Feature on interrupt IN endpoint */ + if(USBH_ClrFeature(phost, + HID_Handle->ep_addr) == USBH_OK) + { + HID_Handle->state = HID_IDLE; + } + } + break; + + case HID_IDLE: + break; + + + default: + break; + } + return USBH_OK; +} + +/** + * @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 = (HID_HandleTypeDef *) phost->pActiveClass->pData; + + if (HID_Handle->state == HID_IDLE) + { + if ((int32_t)(phost->Timer - HID_Handle->timer) >= HID_Handle->poll) + { + HID_Handle->state = HID_GET_DATA; + } + } + 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 : Targeted 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 : Targeted 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 : Targeted 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 USBH_HID_GetPollInterval + * Return HID device poll time + * @param phost: Host handle + * @retval poll time (ms) + */ +uint8_t USBH_HID_GetPollInterval(USBH_HandleTypeDef *phost) +{ + HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData; + + if((phost->gState == HOST_CLASS_REQUEST) || + (phost->gState == HOST_INPUT) || + (phost->gState == HOST_SET_CONFIGURATION) || + (phost->gState == HOST_CHECK_CLASS) || + ((phost->gState == HOST_CLASS))) + { + return (HID_Handle->poll); + } + else + { + return 0; + } +} +/** + * @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 = (uint8_t*) 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 = (const uint8_t*) 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****/ diff --git a/Downstream/Src/downstream_statemachine.c b/Downstream/Src/downstream_statemachine.c index d4482cd..75ea5b3 100644 --- a/Downstream/Src/downstream_statemachine.c +++ b/Downstream/Src/downstream_statemachine.c @@ -190,7 +190,7 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id) } //Called from main() - if (id == HOST_USER_CLASS_ACTIVE) + if (id == HOST_USER_CLASS_SELECTED) { switch (phost->pActiveClass->ClassCode) { diff --git a/Downstream/Src/usb_host.c b/Downstream/Src/usb_host.c index 442eea1..5db673e 100644 --- a/Downstream/Src/usb_host.c +++ b/Downstream/Src/usb_host.c @@ -38,6 +38,7 @@ #include "usb_host.h" #include "usbh_core.h" #include "usbh_msc.h" +#include "usbh_hid.h" #include "downstream_statemachine.h" /* USB Host Core handle declaration */ @@ -51,6 +52,7 @@ void USB_Host_Init(void) USBH_Init(&hUsbHostFS, Downstream_HostUserCallback, HOST_FS); USBH_RegisterClass(&hUsbHostFS, USBH_MSC_CLASS); + USBH_RegisterClass(&hUsbHostFS, USBH_HID_CLASS); USBH_Start(&hUsbHostFS); } diff --git a/Upstream/Inc/upstream_interface_def.h b/Upstream/Inc/upstream_interface_def.h index d2366a6..f76a6df 100644 --- a/Upstream/Inc/upstream_interface_def.h +++ b/Upstream/Inc/upstream_interface_def.h @@ -58,7 +58,7 @@ InterfaceCommandMscTypeDef; typedef enum { - COMMAND_HID_REPORT, //Downstream initiates HID report transfer to Upstream. Upstream just needs to Upstream_ReceivePacket each time. + COMMAND_HID_REPORT, //Downstream initiates HID report transfer to Upstream. Upstream just needs to Upstream_ReceivePacket each time. } InterfaceCommandHidTypeDef; diff --git a/Upstream/Src/upstream_hid.c b/Upstream/Src/upstream_hid.c index cd7502f..6a48b2d 100644 --- a/Upstream/Src/upstream_hid.c +++ b/Upstream/Src/upstream_hid.c @@ -21,7 +21,7 @@ -InterfaceCommandClassTypeDef ActiveHidClass = COMMAND_CLASS_INTERFACE; +InterfaceCommandClassTypeDef ActiveHidClass = COMMAND_CLASS_INTERFACE; UpstreamPacketTypeDef* UpstreamHidPacket = NULL; @@ -37,7 +37,8 @@ void Upstream_HID_Init(InterfaceCommandClassTypeDef newClass) return; } - if (UpstreamHidPacket != NULL) + if ((ActiveHidClass != COMMAND_CLASS_INTERFACE) || + (UpstreamHidPacket != NULL)) { UPSTREAM_SPI_FREAKOUT; return; @@ -81,7 +82,7 @@ void Upstream_HID_GetNextReport(UpstreamHidSendReportCallback callback) void Upstream_HID_GetNextReportReceiveCallback(UpstreamPacketTypeDef* receivedPacket) { - uint8_t reportLength; + uint8_t reportLength = 0; if (UpstreamHidPacket != NULL) { @@ -111,7 +112,14 @@ void Upstream_HID_GetNextReportReceiveCallback(UpstreamPacketTypeDef* receivedPa //Other HID classes go here... + if (reportLength == 0) + { + UPSTREAM_SPI_FREAKOUT; + return; + } + UpstreamHidPacket = receivedPacket; //Save packet so we can free it when upstream USB transaction is done USBD_HID_SendReport(receivedPacket->Data, reportLength); } + diff --git a/Upstream/Src/upstream_statemachine.c b/Upstream/Src/upstream_statemachine.c index 1f1fdbe..0b38360 100644 --- a/Upstream/Src/upstream_statemachine.c +++ b/Upstream/Src/upstream_statemachine.c @@ -176,11 +176,11 @@ void Upstream_StateMachine_NotifyDeviceReplyCallback(UpstreamPacketTypeDef* repl break; case COMMAND_CLASS_HID_MOUSE: - newActiveClass = COMMAND_CLASS_HID_MOUSE; - newClassPointer = &USBD_HID_Mouse; - break; + newActiveClass = COMMAND_CLASS_HID_MOUSE; + newClassPointer = &USBD_HID_Mouse; + break; - //Add other supported classes here... + //Add other supported classes here... } Upstream_ReleasePacket(replyPacket);