From 19dcbdaba86846fbc35d153efd9b922ccd9da469 Mon Sep 17 00:00:00 2001 From: hemi454 Date: Sun, 30 May 2021 17:50:35 +0300 Subject: [PATCH 01/13] Add usb host support --- ports/stm32/Makefile | 13 +- .../boards/STM32F469DISC/mpconfigboard.h | 2 +- ports/stm32/main.c | 3 +- ports/stm32/mphalport.c | 6 +- ports/stm32/usb.c | 23 +- ports/stm32/usb.h | 1 - ports/stm32/usb_host.c | 128 +++ .../stm32/usbdev/class/inc/usbd_cdc_msc_hid.h | 6 +- .../stm32/usbdev/class/src/usbd_cdc_msc_hid.c | 10 +- ports/stm32/usbh_conf.c | 551 +++++++++++ ports/stm32/usbh_conf_template.c | 270 +++++ ports/stm32/usbh_core.c | 936 ++++++++++++++++++ ports/stm32/usbh_ctlreq.c | 881 +++++++++++++++++ ports/stm32/usbh_ioreq.c | 358 +++++++ ports/stm32/usbh_pipes.c | 204 ++++ ports/stm32/usbh_platform.c | 54 + ports/stm32/usbhost/Class/HID/Inc/usbh_hid.h | 20 +- ports/stm32/usbhost/Core/Inc/usb_host.h | 95 ++ ports/stm32/usbhost/Core/Inc/usbh_conf.h | 195 ++++ ports/stm32/usbhost/Core/Inc/usbh_core.h | 2 + ports/stm32/usbhost/Core/Inc/usbh_def.h | 1 + ports/stm32/usbhost/Core/Inc/usbh_main.h | 271 +++++ ports/stm32/usbhost/Core/Inc/usbh_platform.h | 44 + ports/stm32/usbhost/Core/Src/usbh_conf.c | 553 +++++++++++ ports/stm32/usbhost/Core/Src/usbh_core.c | 33 + 25 files changed, 4623 insertions(+), 37 deletions(-) create mode 100644 ports/stm32/usb_host.c create mode 100644 ports/stm32/usbh_conf.c create mode 100644 ports/stm32/usbh_conf_template.c create mode 100644 ports/stm32/usbh_core.c create mode 100644 ports/stm32/usbh_ctlreq.c create mode 100644 ports/stm32/usbh_ioreq.c create mode 100644 ports/stm32/usbh_pipes.c create mode 100644 ports/stm32/usbh_platform.c create mode 100644 ports/stm32/usbhost/Core/Inc/usb_host.h create mode 100644 ports/stm32/usbhost/Core/Inc/usbh_conf.h create mode 100644 ports/stm32/usbhost/Core/Inc/usbh_main.h create mode 100644 ports/stm32/usbhost/Core/Inc/usbh_platform.h create mode 100644 ports/stm32/usbhost/Core/Src/usbh_conf.c diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index d7f6e3e71ee5..08b9aef5588b 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -36,7 +36,7 @@ LD_DIR=boards CMSIS_DIR=$(TOP)/lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Include HAL_DIR=lib/stm32lib/STM32$(MCU_SERIES_UPPER)xx_HAL_Driver USBDEV_DIR=usbdev -#USBHOST_DIR=usbhost +USBHOST_DIR=usbhost DFU=$(TOP)/tools/dfu.py # may need to prefix dfu-util with sudo USE_PYDFU ?= 1 @@ -48,7 +48,6 @@ OPENOCD ?= openocd OPENOCD_CONFIG ?= boards/openocd_stm32f4.cfg STARTUP_FILE ?= lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Source/Templates/gcc/startup_$(CMSIS_MCU_LOWER).o SYSTEM_FILE ?= lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Source/Templates/system_stm32$(MCU_SERIES)xx.o - # Select the cross compile prefix CROSS_COMPILE ?= arm-none-eabi- @@ -59,7 +58,7 @@ INC += -I$(TOP)/lib/cmsis/inc INC += -I$(CMSIS_DIR)/ INC += -I$(TOP)/$(HAL_DIR)/Inc INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/inc -#INC += -I$(USBHOST_DIR) +INC += -I$(USBHOST_DIR)/Core/Inc -I$(USBHOST_DIR)/Class/HID/Inc INC += -Ilwip_inc # Basic Cortex-M flags @@ -257,6 +256,13 @@ SRC_C = \ usbd_cdc_interface.c \ usbd_hid_interface.c \ usbd_msc_interface.c \ + usbh_conf.c \ + usbh_core.c \ + usb_host.c \ + usbh_platform.c \ + usbh_pipes.c \ + usbh_ctlreq.c\ + usbh_ioreq.c \ mphalport.c \ mpthreadport.c \ irq.c \ @@ -364,6 +370,7 @@ SRC_HAL = $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ hal_tim.c \ hal_tim_ex.c \ hal_uart.c \ + hal_hcd.c \ ) ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7 l0 l4 wb)) diff --git a/ports/stm32/boards/STM32F469DISC/mpconfigboard.h b/ports/stm32/boards/STM32F469DISC/mpconfigboard.h index d9424e9b5fda..fb939d63e4be 100644 --- a/ports/stm32/boards/STM32F469DISC/mpconfigboard.h +++ b/ports/stm32/boards/STM32F469DISC/mpconfigboard.h @@ -139,4 +139,4 @@ extern struct _spi_bdev_t spi_bdev; #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) - +#define USE_HOST_MODE (1) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index aa245da8db4d..709d53036829 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -770,7 +770,7 @@ void stm32_main(uint32_t reset_mode) { // Now we initialise sub-systems that need configuration from boot.py, // or whose initialisation can be safely deferred until after running // boot.py. - + #ifndef USE_HOST_MODE #ifndef SKIP_USBINIT #if MICROPY_HW_ENABLE_USB // init USB device to default setting if it was not already configured @@ -786,6 +786,7 @@ void stm32_main(uint32_t reset_mode) { } #endif #endif + #endif #if MICROPY_HW_HAS_MMA7660 // MMA accel: init and reset diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index c8d83be0a140..0bacac5f7dfc 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -33,15 +33,17 @@ MP_WEAK uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { MP_WEAK int mp_hal_stdin_rx_chr(void) { for (;;) { -#if 0 +//#if 0 #ifdef USE_HOST_MODE pyb_usb_host_process(); +/* int c = pyb_usb_host_get_keyboard(); if (c != 0) { return c; } +*/ #endif -#endif +//#endif if (MP_STATE_PORT(pyb_stdio_uart) != NULL && uart_rx_any(MP_STATE_PORT(pyb_stdio_uart))) { return uart_rx_char(MP_STATE_PORT(pyb_stdio_uart)); } diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 8a4b7485bb79..dcc413958797 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -26,14 +26,12 @@ #include #include - #include "usbd_core.h" #include "usbd_desc.h" #include "usbd_cdc_msc_hid.h" #include "usbd_cdc_interface.h" #include "usbd_msc_interface.h" #include "usbd_hid_interface.h" - #include "py/objstr.h" #include "py/runtime.h" #include "py/stream.h" @@ -1007,28 +1005,31 @@ const mp_obj_type_t pyb_usb_hid_type = { #include "led.h" #include "usbh_core.h" -#include "usbh_usr.h" -#include "usbh_hid_core.h" +//#include "usbh_usr.h" +//#include "usbh_hid_core.h" #include "usbh_hid_keybd.h" #include "usbh_hid_mouse.h" - -__ALIGN_BEGIN USBH_HOST USB_Host __ALIGN_END ; - +#include "usb_host.h" +//__ALIGN_BEGIN USBH_HOST USB_Host __ALIGN_END ; +/* USB Host core handle declaration */ +USBH_HandleTypeDef hUsbHostFS; +//ApplicationTypeDef Appli_state = APPLICATION_IDLE; static int host_is_enabled = 0; void pyb_usb_host_init(void) { if (!host_is_enabled) { // only init USBH once in the device's power-lifetime /* Init Host Library */ - USBH_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USB_Host, &HID_cb, &USR_Callbacks); + //USBH_Init(&hUsbHostFS, USB_OTG_FS_CORE_ID, &USB_Host, &HID_cb, &USR_Callbacks); + USBH_Init(&hUsbHostFS, USBH_UserProcess, HOST_FS); } host_is_enabled = 1; } void pyb_usb_host_process(void) { - USBH_Process(&USB_OTG_Core, &USB_Host); + USBH_Process(&hUsbHostFS); } - +/* uint8_t usb_keyboard_key = 0; // TODO this is an ugly hack to get key presses @@ -1062,7 +1063,7 @@ void USR_KEYBRD_ProcessData(uint8_t pbuf) { led_state(4, 0); usb_keyboard_key = pbuf; } - +*/ #endif // USE_HOST_MODE #endif // MICROPY_HW_ENABLE_USB diff --git a/ports/stm32/usb.h b/ports/stm32/usb.h index 457c7313c4d5..93b7a1271d88 100644 --- a/ports/stm32/usb.h +++ b/ports/stm32/usb.h @@ -27,7 +27,6 @@ #define MICROPY_INCLUDED_STM32_USB_H #include "usbd_cdc_msc_hid0.h" - #define PYB_USB_FLAG_USB_MODE_CALLED (0x0002) // Windows needs a different PID to distinguish different device configurations diff --git a/ports/stm32/usb_host.c b/ports/stm32/usb_host.c new file mode 100644 index 000000000000..db59bd63bb83 --- /dev/null +++ b/ports/stm32/usb_host.c @@ -0,0 +1,128 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : usb_host.c + * @version : v1.0_Cube + * @brief : This file implements the USB Host + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ + +#include "usb_host.h" +#include "usbh_core.h" +#include "usbh_hid.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +/* USER CODE BEGIN PFP */ +/* Private function prototypes -----------------------------------------------*/ + +/* USER CODE END PFP */ + +/* USB Host core handle declaration */ +USBH_HandleTypeDef hUsbHostFS; +ApplicationTypeDef Appli_state = APPLICATION_IDLE; + +/* + * -- Insert your variables declaration here -- + */ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* + * -- Insert your external function declaration here -- + */ +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/** + * Init USB host library, add supported class and start the library + * @retval None + */ +void MX_USB_HOST_Init(void) +{ + /* USER CODE BEGIN USB_HOST_Init_PreTreatment */ + + /* USER CODE END USB_HOST_Init_PreTreatment */ + + /* Init host Library, add supported class and start the library. */ + if (USBH_Init(&hUsbHostFS, USBH_UserProcess, HOST_FS) != USBH_OK) + { + //Error_Handler(); + return; + } + if (USBH_RegisterClass(&hUsbHostFS, USBH_HID_CLASS) != USBH_OK) + { + //Error_Handler(); + return; + } + if (USBH_Start(&hUsbHostFS) != USBH_OK) + { + //Error_Handler(); + return; + } + /* USER CODE BEGIN USB_HOST_Init_PostTreatment */ + + /* USER CODE END USB_HOST_Init_PostTreatment */ +} + +/* + * user callback definition + */ +void USBH_UserProcess (USBH_HandleTypeDef *phost, uint8_t id) +{ + /* USER CODE BEGIN CALL_BACK_1 */ + switch(id) + { + case HOST_USER_SELECT_CONFIGURATION: + break; + + case HOST_USER_DISCONNECTION: + Appli_state = APPLICATION_DISCONNECT; + break; + + case HOST_USER_CLASS_ACTIVE: + Appli_state = APPLICATION_READY; + break; + + case HOST_USER_CONNECTION: + Appli_state = APPLICATION_START; + break; + + default: + break; + } + /* USER CODE END CALL_BACK_1 */ +} + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h index d934f4676c4d..1d1ee89a8373 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h @@ -89,9 +89,9 @@ typedef struct { } USBD_MSC_BOT_HandleTypeDef; typedef enum { - HID_IDLE = 0, - HID_BUSY, -} HID_StateTypeDef; + HID_IDLE_DEV = 0, + HID_BUSY_DEV, +} HID_Device_StateTypeDef; typedef struct { struct _usbd_cdc_msc_hid_state_t *usbd; // The parent USB device diff --git a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c index 5e24730a0fac..3978c254a30a 100644 --- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c +++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c @@ -754,7 +754,7 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { // Prepare Out endpoint to receive next packet USBD_LL_PrepareReceive(pdev, usbd->hid->out_ep, buf, mps_out); - usbd->hid->state = HID_IDLE; + usbd->hid->state = HID_IDLE_DEV; } #endif @@ -1061,7 +1061,7 @@ static uint8_t USBD_CDC_MSC_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) if ((usbd->usbd_mode & USBD_MODE_IFACE_HID) && epnum == (usbd->hid->in_ep & 0x7f)) { /* 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->hid->state = HID_IDLE; + usbd->hid->state = HID_IDLE_DEV; return USBD_OK; } #endif @@ -1257,13 +1257,13 @@ uint8_t USBD_HID_ReceivePacket(usbd_hid_state_t *hid, uint8_t *buf) { } int USBD_HID_CanSendReport(usbd_hid_state_t *hid) { - return hid->usbd->pdev->dev_state == USBD_STATE_CONFIGURED && hid->state == HID_IDLE; + return hid->usbd->pdev->dev_state == USBD_STATE_CONFIGURED && hid->state == HID_IDLE_DEV; } uint8_t USBD_HID_SendReport(usbd_hid_state_t *hid, uint8_t *report, uint16_t len) { if (hid->usbd->pdev->dev_state == USBD_STATE_CONFIGURED) { - if (hid->state == HID_IDLE) { - hid->state = HID_BUSY; + if (hid->state == HID_IDLE_DEV) { + hid->state = HID_BUSY_DEV; USBD_LL_Transmit(hid->usbd->pdev, hid->in_ep, report, len); return USBD_OK; } diff --git a/ports/stm32/usbh_conf.c b/ports/stm32/usbh_conf.c new file mode 100644 index 000000000000..8a761f946839 --- /dev/null +++ b/ports/stm32/usbh_conf.c @@ -0,0 +1,551 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : Target/usbh_conf.c + * @version : v1.0_Cube + * @brief : This file implements the board support package for the USB host library + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_core.h" +#include "usbh_platform.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +HCD_HandleTypeDef hhcd_USB_OTG_FS; +void Error_Handler(void); + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* USER CODE BEGIN PFP */ +/* Private function prototypes -----------------------------------------------*/ +USBH_StatusTypeDef USBH_Get_USB_Status(HAL_StatusTypeDef hal_status); + +/* USER CODE END PFP */ + +/* Private functions ---------------------------------------------------------*/ + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/******************************************************************************* + LL Driver Callbacks (HCD -> USB Host Library) +*******************************************************************************/ +/* MSP Init */ + +void HAL_HCD_MspInit(HCD_HandleTypeDef* hcdHandle) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(hcdHandle->Instance==USB_OTG_FS) + { + /* USER CODE BEGIN USB_OTG_FS_MspInit 0 */ + + /* USER CODE END USB_OTG_FS_MspInit 0 */ + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**USB_OTG_FS GPIO Configuration + PA12 ------> USB_OTG_FS_DP + PA11 ------> USB_OTG_FS_DM + PA10 ------> USB_OTG_FS_ID + PA9 ------> USB_OTG_FS_VBUS + */ + GPIO_InitStruct.Pin = USB_FS1_P_Pin|USB_FS1_N_Pin|USB_FS1_ID_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = VBUS_FS1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(VBUS_FS1_GPIO_Port, &GPIO_InitStruct); + + /* Peripheral clock enable */ + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + + /* Peripheral interrupt init */ + HAL_NVIC_SetPriority(OTG_FS_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(OTG_FS_IRQn); + /* USER CODE BEGIN USB_OTG_FS_MspInit 1 */ + + /* USER CODE END USB_OTG_FS_MspInit 1 */ + } +} + +void HAL_HCD_MspDeInit(HCD_HandleTypeDef* hcdHandle) +{ + if(hcdHandle->Instance==USB_OTG_FS) + { + /* USER CODE BEGIN USB_OTG_FS_MspDeInit 0 */ + + /* USER CODE END USB_OTG_FS_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); + + /**USB_OTG_FS GPIO Configuration + PA12 ------> USB_OTG_FS_DP + PA11 ------> USB_OTG_FS_DM + PA10 ------> USB_OTG_FS_ID + PA9 ------> USB_OTG_FS_VBUS + */ + HAL_GPIO_DeInit(GPIOA, USB_FS1_P_Pin|USB_FS1_N_Pin|USB_FS1_ID_Pin|VBUS_FS1_Pin); + + /* Peripheral interrupt Deinit*/ + HAL_NVIC_DisableIRQ(OTG_FS_IRQn); + + /* USER CODE BEGIN USB_OTG_FS_MspDeInit 1 */ + + /* USER CODE END USB_OTG_FS_MspDeInit 1 */ + } +} + +/** + * @brief SOF callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_IncTimer(hhcd->pData); +} + +/** + * @brief SOF callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_Connect(hhcd->pData); +} + +/** + * @brief SOF callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_Disconnect(hhcd->pData); +} + +/** + * @brief Notify URB state change callback. + * @param hhcd: HCD handle + * @param chnum: channel number + * @param urb_state: state + * @retval None + */ +void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state) +{ + /* To be used with OS to sync URB state with the global state machine */ +#if (USBH_USE_OS == 1) + USBH_LL_NotifyURBChange(hhcd->pData); +#endif +} +/** +* @brief Port Port Enabled callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_PortEnabled(hhcd->pData); +} + +/** + * @brief Port Port Disabled callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_PortDisabled(hhcd->pData); +} + +/******************************************************************************* + LL Driver Interface (USB Host Library --> HCD) +*******************************************************************************/ + +/** + * @brief Initialize the low level portion of the host driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_Init(USBH_HandleTypeDef *phost) +{ + /* Init USB_IP */ + if (phost->id == HOST_FS) { + /* Link the driver to the stack. */ + hhcd_USB_OTG_FS.pData = phost; + phost->pData = &hhcd_USB_OTG_FS; + + hhcd_USB_OTG_FS.Instance = USB_OTG_FS; + hhcd_USB_OTG_FS.Init.Host_channels = 8; + hhcd_USB_OTG_FS.Init.speed = HCD_SPEED_FULL; + hhcd_USB_OTG_FS.Init.dma_enable = DISABLE; + hhcd_USB_OTG_FS.Init.phy_itface = HCD_PHY_EMBEDDED; + hhcd_USB_OTG_FS.Init.Sof_enable = DISABLE; + if (HAL_HCD_Init(&hhcd_USB_OTG_FS) != HAL_OK) + { + //Error_Handler( ); + return USBH_FAIL; + } + + USBH_LL_SetTimer(phost, HAL_HCD_GetCurrentFrame(&hhcd_USB_OTG_FS)); + } + return USBH_OK; +} + +/** + * @brief De-Initialize the low level portion of the host driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_DeInit(USBH_HandleTypeDef *phost) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_DeInit(phost->pData); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Start the low level portion of the host driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_Start(USBH_HandleTypeDef *phost) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_Start(phost->pData); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Stop the low level portion of the host driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_Stop(USBH_HandleTypeDef *phost) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_Stop(phost->pData); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Return the USB host speed from the low level driver. + * @param phost: Host handle + * @retval USBH speeds + */ +USBH_SpeedTypeDef USBH_LL_GetSpeed(USBH_HandleTypeDef *phost) +{ + USBH_SpeedTypeDef speed = USBH_SPEED_FULL; + + switch (HAL_HCD_GetCurrentSpeed(phost->pData)) + { + case 0 : + speed = USBH_SPEED_HIGH; + break; + + case 1 : + speed = USBH_SPEED_FULL; + break; + + case 2 : + speed = USBH_SPEED_LOW; + break; + + default: + speed = USBH_SPEED_FULL; + break; + } + return speed; +} + +/** + * @brief Reset the Host port of the low level driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_ResetPort(USBH_HandleTypeDef *phost) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_ResetPort(phost->pData); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Return the last transfered packet size. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval Packet size + */ +uint32_t USBH_LL_GetLastXferSize(USBH_HandleTypeDef *phost, uint8_t pipe) +{ + return HAL_HCD_HC_GetXferCount(phost->pData, pipe); +} + +/** + * @brief Open a pipe of the low level driver. + * @param phost: Host handle + * @param pipe_num: Pipe index + * @param epnum: Endpoint number + * @param dev_address: Device USB address + * @param speed: Device Speed + * @param ep_type: Endpoint type + * @param mps: Endpoint max packet size + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_OpenPipe(USBH_HandleTypeDef *phost, uint8_t pipe_num, uint8_t epnum, + uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_HC_Init(phost->pData, pipe_num, epnum, + dev_address, speed, ep_type, mps); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Close a pipe of the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_ClosePipe(USBH_HandleTypeDef *phost, uint8_t pipe) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_HC_Halt(phost->pData, pipe); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Submit a new URB to the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * This parameter can be a value from 1 to 15 + * @param direction : Channel number + * This parameter can be one of the these values: + * 0 : Output + * 1 : Input + * @param ep_type : Endpoint Type + * This parameter can be one of the these values: + * @arg EP_TYPE_CTRL: Control type + * @arg EP_TYPE_ISOC: Isochrounous type + * @arg EP_TYPE_BULK: Bulk type + * @arg EP_TYPE_INTR: Interrupt type + * @param token : Endpoint Type + * This parameter can be one of the these values: + * @arg 0: PID_SETUP + * @arg 1: PID_DATA + * @param pbuff : pointer to URB data + * @param length : Length of URB data + * @param do_ping : activate do ping protocol (for high speed only) + * This parameter can be one of the these values: + * 0 : do ping inactive + * 1 : do ping active + * @retval Status + */ +USBH_StatusTypeDef USBH_LL_SubmitURB(USBH_HandleTypeDef *phost, uint8_t pipe, uint8_t direction, + uint8_t ep_type, uint8_t token, uint8_t *pbuff, uint16_t length, + uint8_t do_ping) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_HC_SubmitRequest(phost->pData, pipe, direction , + ep_type, token, pbuff, length, + do_ping); + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Get a URB state from the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * This parameter can be a value from 1 to 15 + * @retval URB state + * This parameter can be one of the these values: + * @arg URB_IDLE + * @arg URB_DONE + * @arg URB_NOTREADY + * @arg URB_NYET + * @arg URB_ERROR + * @arg URB_STALL + */ +USBH_URBStateTypeDef USBH_LL_GetURBState(USBH_HandleTypeDef *phost, uint8_t pipe) +{ + return (USBH_URBStateTypeDef)HAL_HCD_HC_GetURBState (phost->pData, pipe); +} + +/** + * @brief Drive VBUS. + * @param phost: Host handle + * @param state : VBUS state + * This parameter can be one of the these values: + * 0 : VBUS Inactive + * 1 : VBUS Active + * @retval Status + */ +USBH_StatusTypeDef USBH_LL_DriverVBUS(USBH_HandleTypeDef *phost, uint8_t state) +{ + if (phost->id == HOST_FS) { + MX_DriverVbusFS(state); + } + + /* USER CODE BEGIN 0 */ + + /* USER CODE END 0*/ + + HAL_Delay(200); + return USBH_OK; +} + +/** + * @brief Set toggle for a pipe. + * @param phost: Host handle + * @param pipe: Pipe index + * @param toggle: toggle (0/1) + * @retval Status + */ +USBH_StatusTypeDef USBH_LL_SetToggle(USBH_HandleTypeDef *phost, uint8_t pipe, uint8_t toggle) +{ + HCD_HandleTypeDef *pHandle; + pHandle = phost->pData; + + if(pHandle->hc[pipe].ep_is_in) + { + pHandle->hc[pipe].toggle_in = toggle; + } + else + { + pHandle->hc[pipe].toggle_out = toggle; + } + + return USBH_OK; +} + +/** + * @brief Return the current toggle of a pipe. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval toggle (0/1) + */ +uint8_t USBH_LL_GetToggle(USBH_HandleTypeDef *phost, uint8_t pipe) +{ + uint8_t toggle = 0; + HCD_HandleTypeDef *pHandle; + pHandle = phost->pData; + + if(pHandle->hc[pipe].ep_is_in) + { + toggle = pHandle->hc[pipe].toggle_in; + } + else + { + toggle = pHandle->hc[pipe].toggle_out; + } + return toggle; +} + +/** + * @brief Delay routine for the USB Host Library + * @param Delay: Delay in ms + * @retval None + */ +void USBH_Delay(uint32_t Delay) +{ + HAL_Delay(Delay); +} + +/** + * @brief Retuns the USB status depending on the HAL status: + * @param hal_status: HAL status + * @retval USB status + */ +USBH_StatusTypeDef USBH_Get_USB_Status(HAL_StatusTypeDef hal_status) +{ + USBH_StatusTypeDef usb_status = USBH_OK; + + switch (hal_status) + { + case HAL_OK : + usb_status = USBH_OK; + break; + case HAL_ERROR : + usb_status = USBH_FAIL; + break; + case HAL_BUSY : + usb_status = USBH_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBH_FAIL; + break; + default : + usb_status = USBH_FAIL; + break; + } + return usb_status; +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbh_conf_template.c b/ports/stm32/usbh_conf_template.c new file mode 100644 index 000000000000..de689ec0a119 --- /dev/null +++ b/ports/stm32/usbh_conf_template.c @@ -0,0 +1,270 @@ +/** + ****************************************************************************** + * @file usb_bsp.c + * @author MCD Application Team + * @version V3.0.0 + * @date 18-February-2014 + * @brief This file implements the board support package for the USB host library + ****************************************************************************** + * @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 "usbh_core.h" + +/** + * @brief USBH_LL_Init + * Initialize the Low Level portion of the Host driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_Init (USBH_HandleTypeDef *phost) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_DeInit + * De-Initialize the Low Level portion of the Host driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_DeInit (USBH_HandleTypeDef *phost) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_Start + * Start the Low Level portion of the Host driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_Start(USBH_HandleTypeDef *phost) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_Stop + * Stop the Low Level portion of the Host driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_Stop (USBH_HandleTypeDef *phost) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_GetSpeed + * Return the USB Host Speed from the Low Level Driver. + * @param phost: Host handle + * @retval USBH Speeds + */ +USBH_SpeedTypeDef USBH_LL_GetSpeed (USBH_HandleTypeDef *phost) +{ + USBH_SpeedTypeDef speed = 0; + + + return speed; +} + +/** + * @brief USBH_LL_ResetPort + * Reset the Host Port of the Low Level Driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_ResetPort (USBH_HandleTypeDef *phost) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_GetLastXferSize + * Return the last transfered packet size. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval Packet Size + */ +uint32_t USBH_LL_GetLastXferSize (USBH_HandleTypeDef *phost, uint8_t pipe) +{ + +} + +/** + * @brief USBH_LL_OpenPipe + * Open a pipe of the Low Level Driver. + * @param phost: Host handle + * @param pipe_num: Pipe index + * @param epnum: Endpoint Number + * @param dev_address: Device USB address + * @param speed: Device Speed + * @param ep_type: Endpoint Type + * @param mps: Endpoint Max Packet Size + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_OpenPipe (USBH_HandleTypeDef *phost, + uint8_t pipe_num, + uint8_t epnum, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_ClosePipe + * Close a pipe of the Low Level Driver. + * @param phost: Host handle + * @param pipe_num: Pipe index + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_ClosePipe (USBH_HandleTypeDef *phost, uint8_t pipe) +{ + +} +/** + * @brief USBH_LL_SubmitURB + * Submit a new URB to the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * This parameter can be a value from 1 to 15 + * @param direction : Channel number + * This parameter can be one of the these values: + * 0 : Output + * 1 : Input + * @param ep_type : Endpoint Type + * This parameter can be one of the these values: + * @arg EP_TYPE_CTRL: Control type + * @arg EP_TYPE_ISOC: Isochrounous type + * @arg EP_TYPE_BULK: Bulk type + * @arg EP_TYPE_INTR: Interrupt type + * @param token : Endpoint Type + * This parameter can be one of the these values: + * @arg 0: PID_SETUP + * @arg 1: PID_DATA + * @param pbuff : pointer to URB data + * @param length : Length of URB data + * @param do_ping : activate do ping protocol (for high speed only) + * This parameter can be one of the these values: + * 0 : do ping inactive + * 1 : do ping active + * @retval Status + */ + +USBH_StatusTypeDef USBH_LL_SubmitURB (USBH_HandleTypeDef *phost, + uint8_t pipe, + uint8_t direction , + uint8_t ep_type, + uint8_t token, + uint8_t* pbuff, + uint16_t length, + uint8_t do_ping ) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_GetURBState + * Get a URB state from the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * This parameter can be a value from 1 to 15 + * @retval URB state + * This parameter can be one of the these values: + * @arg URB_IDLE + * @arg URB_DONE + * @arg URB_NOTREADY + * @arg URB_NYET + * @arg URB_ERROR + * @arg URB_STALL + */ +USBH_URBStateTypeDef USBH_LL_GetURBState (USBH_HandleTypeDef *phost, uint8_t pipe) +{ + +} + +/** + * @brief USBH_LL_DriverVBUS + * Drive VBUS. + * @param phost: Host handle + * @param state : VBUS state + * This parameter can be one of the these values: + * 0 : VBUS Active + * 1 : VBUS Inactive + * @retval Status + */ + +USBH_StatusTypeDef USBH_LL_DriverVBUS (USBH_HandleTypeDef *phost, uint8_t state) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_SetToggle + * Set toggle for a pipe. + * @param phost: Host handle + * @param pipe: Pipe index + * @param pipe_num: Pipe index + * @param toggle: toggle (0/1) + * @retval Status + */ +USBH_StatusTypeDef USBH_LL_SetToggle (USBH_HandleTypeDef *phost, uint8_t pipe, uint8_t toggle) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_GetToggle + * Return the current toggle of a pipe. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval toggle (0/1) + */ +uint8_t USBH_LL_GetToggle (USBH_HandleTypeDef *phost, uint8_t pipe) +{ + uint8_t toggle = 0; + + + return toggle; +} +/** + * @brief USBH_Delay + * Delay routine for the USB Host Library + * @param Delay: Delay in ms + * @retval None + */ +void USBH_Delay (uint32_t Delay) +{ + +} +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbh_core.c b/ports/stm32/usbh_core.c new file mode 100644 index 000000000000..a363f968fbed --- /dev/null +++ b/ports/stm32/usbh_core.c @@ -0,0 +1,936 @@ +/** + ****************************************************************************** + * @file usbh_core.c + * @author MCD Application Team + * @version V3.0.0 + * @date 18-February-2014 + * @brief This file implements the functions for the core state machine process + * the enumeration and the control transfer process + ****************************************************************************** + * @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 "usbh_core.h" + + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE + * @{ + */ + +/** @defgroup USBH_CORE + * @brief TThis file handles the basic enumaration when a device is connected + * to the host. + * @{ + */ + + +/** @defgroup USBH_CORE_Private_Defines + * @{ + */ +#define USBH_ADDRESS_DEFAULT 0 +#define USBH_ADDRESS_ASSIGNED 1 +#define USBH_MPS_DEFAULT 0x40 +/** + * @} + */ + +/** @defgroup USBH_CORE_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_CORE_Private_Variables + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_CORE_Private_Functions + * @{ + */ +static USBH_StatusTypeDef USBH_HandleEnum (USBH_HandleTypeDef *phost); +static void USBH_HandleSof (USBH_HandleTypeDef *phost); +static USBH_StatusTypeDef DeInitStateMachine(USBH_HandleTypeDef *phost); + +#if (USBH_USE_OS == 1) +static void USBH_Process_OS(void const * argument); +#endif + +/** + * @brief HCD_Init + * Initialize the HOST Core. + * @param phost: Host Handle + * @param pUsrFunc: User Callback + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Init(USBH_HandleTypeDef *phost, void (*pUsrFunc)(USBH_HandleTypeDef *phost, uint8_t ), uint8_t id) +{ + /* Check whether the USB Host handle is valid */ + if(phost == NULL) + { + USBH_ErrLog("Invalid Host handle"); + return USBH_FAIL; + } + + /* Set DRiver ID */ + phost->id = id; + + /* Unlink class*/ + phost->pActiveClass = NULL; + phost->ClassNumber = 0; + + /* Restore default states and prepare EP0 */ + DeInitStateMachine(phost); + + /* Assign User process */ + if(pUsrFunc != NULL) + { + phost->pUser = pUsrFunc; + } + +#if (USBH_USE_OS == 1) + + /* Create USB Host Queue */ + osMessageQDef(USBH_Queue, 10, uint16_t); + phost->os_event = osMessageCreate (osMessageQ(USBH_Queue), NULL); + + /*Create USB Host Task */ + osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0, 8 * configMINIMAL_STACK_SIZE); + phost->thread = osThreadCreate (osThread(USBH_Thread), phost); +#endif + + /* Initialize low level driver */ + USBH_LL_Init(phost); + return USBH_OK; +} + +/** + * @brief HCD_Init + * De-Initialize the Host portion of the driver. + * @param phost: Host Handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_DeInit(USBH_HandleTypeDef *phost) +{ + DeInitStateMachine(phost); + + if(phost->pData != NULL) + { + phost->pActiveClass->pData = NULL; + USBH_LL_Stop(phost); + } + + return USBH_OK; +} + +/** + * @brief DeInitStateMachine + * De-Initialize the Host state machine. + * @param phost: Host Handle + * @retval USBH Status + */ +static USBH_StatusTypeDef DeInitStateMachine(USBH_HandleTypeDef *phost) +{ + uint32_t i = 0; + + /* Clear Pipes flags*/ + for ( ; i < USBH_MAX_PIPES_NBR; i++) + { + phost->Pipes[i] = 0; + } + + for(i = 0; i< USBH_MAX_DATA_BUFFER; i++) + { + phost->device.Data[i] = 0; + } + + phost->gState = HOST_IDLE; + phost->EnumState = ENUM_IDLE; + phost->RequestState = CMD_SEND; + phost->Timer = 0; + + phost->Control.state = CTRL_SETUP; + phost->Control.pipe_size = USBH_MPS_DEFAULT; + phost->Control.errorcount = 0; + + phost->device.address = USBH_ADDRESS_DEFAULT; + phost->device.speed = USBH_SPEED_FULL; + + return USBH_OK; +} + +/** + * @brief USBH_RegisterClass + * Link class driver to Host Core. + * @param phost : Host Handle + * @param pclass: Class handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_RegisterClass(USBH_HandleTypeDef *phost, USBH_ClassTypeDef *pclass) +{ + USBH_StatusTypeDef status = USBH_OK; + + if(pclass != 0) + { + if(phost->ClassNumber < USBH_MAX_NUM_SUPPORTED_CLASS) + { + /* link the class tgo the USB Host handle */ + phost->pClass[phost->ClassNumber++] = pclass; + status = USBH_OK; + } + else + { + USBH_ErrLog("Max Class Number reached"); + status = USBH_FAIL; + } + } + else + { + USBH_ErrLog("Invalid Class handle"); + status = USBH_FAIL; + } + + return status; +} + +/** + * @brief USBH_SelectInterface + * Select current interface. + * @param phost: Host Handle + * @param interface: Interface number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_SelectInterface(USBH_HandleTypeDef *phost, uint8_t interface) +{ + USBH_StatusTypeDef status = USBH_OK; + + if(interface < phost->device.CfgDesc.bNumInterfaces) + { + phost->device.current_interface = interface; + USBH_UsrLog ("Switching to Interface (#%d)", interface); + USBH_UsrLog ("Class : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass ); + USBH_UsrLog ("SubClass : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceSubClass ); + USBH_UsrLog ("Protocol : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol ); + } + else + { + USBH_ErrLog ("Cannot Select This Interface."); + status = USBH_FAIL; + } + return status; +} + +/** + * @brief USBH_GetActiveClass + * Return Device Class. + * @param phost: Host Handle + * @param interface: Interface index + * @retval Class Code + */ +uint8_t USBH_GetActiveClass(USBH_HandleTypeDef *phost) +{ + return (phost->device.CfgDesc.Itf_Desc[0].bInterfaceClass); +} +/** + * @brief USBH_FindInterface + * Find the interface index for a specific class. + * @param phost: Host Handle + * @param Class: Class code + * @param SubClass: SubClass code + * @param Protocol: Protocol code + * @retval interface index in the configuration structure + * @note : (1)interface index 0xFF means interface index not found + */ +uint8_t USBH_FindInterface(USBH_HandleTypeDef *phost, uint8_t Class, uint8_t SubClass, uint8_t Protocol) +{ + USBH_InterfaceDescTypeDef *pif ; + USBH_CfgDescTypeDef *pcfg ; + int8_t if_ix = 0; + + pif = (USBH_InterfaceDescTypeDef *)0; + pcfg = &phost->device.CfgDesc; + + if((pif->bInterfaceClass == 0xFF) &&(pif->bInterfaceSubClass == 0xFF) && (pif->bInterfaceProtocol == 0xFF)) + { + return 0xFF; + } + + while (if_ix < USBH_MAX_NUM_INTERFACES) + { + pif = &pcfg->Itf_Desc[if_ix]; + if(((pif->bInterfaceClass == Class) || (Class == 0xFF))&& + ((pif->bInterfaceSubClass == SubClass) || (SubClass == 0xFF))&& + ((pif->bInterfaceProtocol == Protocol) || (Protocol == 0xFF))) + { + return if_ix; + } + if_ix++; + } + return 0xFF; +} + +/** + * @brief USBH_FindInterfaceIndex + * Find the interface index for a specific class interface and alternate setting number. + * @param phost: Host Handle + * @param interface_number: interface number + * @param alt_settings : alaternate setting number + * @retval interface index in the configuration structure + * @note : (1)interface index 0xFF means interface index not found + */ +uint8_t USBH_FindInterfaceIndex(USBH_HandleTypeDef *phost, uint8_t interface_number, uint8_t alt_settings) +{ + USBH_InterfaceDescTypeDef *pif ; + USBH_CfgDescTypeDef *pcfg ; + int8_t if_ix = 0; + + pif = (USBH_InterfaceDescTypeDef *)0; + pcfg = &phost->device.CfgDesc; + + while (if_ix < USBH_MAX_NUM_INTERFACES) + { + pif = &pcfg->Itf_Desc[if_ix]; + if((pif->bInterfaceNumber == interface_number) && (pif->bAlternateSetting == alt_settings)) + { + return if_ix; + } + if_ix++; + } + return 0xFF; +} + +/** + * @brief USBH_Start + * Start the USB Host Core. + * @param phost: Host Handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Start (USBH_HandleTypeDef *phost) +{ + /* Start the low level driver */ + USBH_LL_Start(phost); + + /* Activate VBUS on the port */ + USBH_LL_DriverVBUS (phost, TRUE); + + return USBH_OK; +} + +/** + * @brief USBH_Stop + * Stop the USB Host Core. + * @param phost: Host Handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Stop (USBH_HandleTypeDef *phost) +{ + /* Stop and cleanup the low level driver */ + USBH_LL_Stop(phost); + + /* DeActivate VBUS on the port */ + USBH_LL_DriverVBUS (phost, FALSE); + + /* FRee Control Pipes */ + USBH_FreePipe (phost, phost->Control.pipe_in); + USBH_FreePipe (phost, phost->Control.pipe_out); + + return USBH_OK; +} + +/** + * @brief HCD_ReEnumerate + * Perform a new Enumeration phase. + * @param phost: Host Handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_ReEnumerate (USBH_HandleTypeDef *phost) +{ + /*Stop Host */ + USBH_Stop(phost); + + /*Device has disconnected, so wait for 200 ms */ + USBH_Delay(200); + + /* Set State machines in default state */ + DeInitStateMachine(phost); + + /* Start again the host */ + USBH_Start(phost); + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); +#endif + return USBH_OK; +} + +/** + * @brief USBH_Process + * Background process of the USB Core. + * @param phost: Host Handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Process(USBH_HandleTypeDef *phost) +{ + __IO USBH_StatusTypeDef status = USBH_FAIL; + uint8_t idx = 0; + + switch (phost->gState) + { + case HOST_IDLE : + + if (phost->device.is_connected) + { + /* Wait for 200 ms after connection */ + phost->gState = HOST_DEV_WAIT_FOR_ATTACHMENT; + USBH_Delay(200); + USBH_LL_ResetPort(phost); +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); +#endif + } + break; + + case HOST_DEV_WAIT_FOR_ATTACHMENT: + break; + + case HOST_DEV_ATTACHED : + + USBH_UsrLog("USB Device Attached"); + + /* Wait for 100 ms after Reset */ + USBH_Delay(100); + + phost->device.speed = USBH_LL_GetSpeed(phost); + + phost->gState = HOST_ENUMERATION; + + phost->Control.pipe_out = USBH_AllocPipe (phost, 0x00); + phost->Control.pipe_in = USBH_AllocPipe (phost, 0x80); + + + /* Open Control pipes */ + USBH_OpenPipe (phost, + phost->Control.pipe_in, + 0x80, + phost->device.address, + phost->device.speed, + USBH_EP_CONTROL, + phost->Control.pipe_size); + + /* Open Control pipes */ + USBH_OpenPipe (phost, + phost->Control.pipe_out, + 0x00, + phost->device.address, + phost->device.speed, + USBH_EP_CONTROL, + phost->Control.pipe_size); + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); +#endif + + break; + + case HOST_ENUMERATION: + /* Check for enumeration status */ + if ( USBH_HandleEnum(phost) == USBH_OK) + { + /* The function shall return USBH_OK when full enumeration is complete */ + USBH_UsrLog ("Enumeration done."); + phost->device.current_interface = 0; + if(phost->device.DevDesc.bNumConfigurations == 1) + { + USBH_UsrLog ("This device has only 1 configuration."); + phost->gState = HOST_SET_CONFIGURATION; + + } + else + { + phost->gState = HOST_INPUT; + } + + } + break; + + case HOST_INPUT: + { + /* user callback for end of device basic enumeration */ + if(phost->pUser != NULL) + { + phost->pUser(phost, HOST_USER_SELECT_CONFIGURATION); + phost->gState = HOST_SET_CONFIGURATION; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + } + } + break; + + case HOST_SET_CONFIGURATION: + /* set configuration */ + if (USBH_SetCfg(phost, phost->device.CfgDesc.bConfigurationValue) == USBH_OK) + { + phost->gState = HOST_CHECK_CLASS; + USBH_UsrLog ("Default configuration set."); + + } + + break; + + case HOST_CHECK_CLASS: + + if(phost->ClassNumber == 0) + { + USBH_UsrLog ("No Class has been registered."); + } + else + { + phost->pActiveClass = NULL; + + for (idx = 0; idx < USBH_MAX_NUM_SUPPORTED_CLASS ; idx ++) + { + if(phost->pClass[idx]->ClassCode == phost->device.CfgDesc.Itf_Desc[0].bInterfaceClass) + { + phost->pActiveClass = phost->pClass[idx]; + } + } + + if(phost->pActiveClass != NULL) + { + if(phost->pActiveClass->Init(phost)== USBH_OK) + { + phost->gState = HOST_CLASS_REQUEST; + USBH_UsrLog ("%s class started.", phost->pActiveClass->Name); + + /* Inform user that a class has been activated */ + phost->pUser(phost, HOST_USER_CLASS_SELECTED); + } + else + { + phost->gState = HOST_ABORT_STATE; + USBH_UsrLog ("Device not supporting %s class.", phost->pActiveClass->Name); + } + } + else + { + phost->gState = HOST_ABORT_STATE; + USBH_UsrLog ("No registered class for this device."); + } + } + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + break; + + case HOST_CLASS_REQUEST: + /* process class standard contol requests state machine */ + + if(phost->pActiveClass != NULL) + { + status = phost->pActiveClass->Requests(phost); + + if(status == USBH_OK) + { + phost->gState = HOST_CLASS; + } + } + else + { + phost->gState = HOST_ABORT_STATE; + USBH_ErrLog ("Invalid Class Driver."); + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + } + + break; + case HOST_CLASS: + /* process class state machine */ + if(phost->pActiveClass != NULL) + { + phost->pActiveClass->BgndProcess(phost); + } + break; + + case HOST_DEV_DISCONNECTED : + + DeInitStateMachine(phost); + + /* Re-Initilaize Host for new Enumeration */ + if(phost->pActiveClass != NULL) + { + phost->pActiveClass->DeInit(phost); + phost->pActiveClass = NULL; + } + break; + + case HOST_ABORT_STATE: + default : + break; + } + return USBH_OK; +} + + +/** + * @brief USBH_HandleEnum + * This function includes the complete enumeration process + * @param phost: Host Handle + * @retval USBH_Status + */ +static USBH_StatusTypeDef USBH_HandleEnum (USBH_HandleTypeDef *phost) +{ + USBH_StatusTypeDef Status = USBH_BUSY; + + switch (phost->EnumState) + { + case ENUM_IDLE: + /* Get Device Desc for only 1st 8 bytes : To get EP0 MaxPacketSize */ + if ( USBH_Get_DevDesc(phost, 8) == USBH_OK) + { + phost->Control.pipe_size = phost->device.DevDesc.bMaxPacketSize; + + phost->EnumState = ENUM_GET_FULL_DEV_DESC; + + /* modify control channels configuration for MaxPacket size */ + USBH_OpenPipe (phost, + phost->Control.pipe_in, + 0x80, + phost->device.address, + phost->device.speed, + USBH_EP_CONTROL, + phost->Control.pipe_size); + + /* Open Control pipes */ + USBH_OpenPipe (phost, + phost->Control.pipe_out, + 0x00, + phost->device.address, + phost->device.speed, + USBH_EP_CONTROL, + phost->Control.pipe_size); + + } + break; + + case ENUM_GET_FULL_DEV_DESC: + /* Get FULL Device Desc */ + if ( USBH_Get_DevDesc(phost, USB_DEVICE_DESC_SIZE)== USBH_OK) + { + USBH_UsrLog("PID: %xh", phost->device.DevDesc.idProduct ); + USBH_UsrLog("VID: %xh", phost->device.DevDesc.idVendor ); + + phost->EnumState = ENUM_SET_ADDR; + + } + break; + + case ENUM_SET_ADDR: + /* set address */ + if ( USBH_SetAddress(phost, USBH_DEVICE_ADDRESS) == USBH_OK) + { + USBH_Delay(2); + phost->device.address = USBH_DEVICE_ADDRESS; + + /* user callback for device address assigned */ + USBH_UsrLog("Address (#%d) assigned.", phost->device.address); + phost->EnumState = ENUM_GET_CFG_DESC; + + /* modify control channels to update device address */ + USBH_OpenPipe (phost, + phost->Control.pipe_in, + 0x80, + phost->device.address, + phost->device.speed, + USBH_EP_CONTROL, + phost->Control.pipe_size); + + /* Open Control pipes */ + USBH_OpenPipe (phost, + phost->Control.pipe_out, + 0x00, + phost->device.address, + phost->device.speed, + USBH_EP_CONTROL, + phost->Control.pipe_size); + } + break; + + case ENUM_GET_CFG_DESC: + /* get standard configuration descriptor */ + if ( USBH_Get_CfgDesc(phost, + USB_CONFIGURATION_DESC_SIZE) == USBH_OK) + { + phost->EnumState = ENUM_GET_FULL_CFG_DESC; + } + break; + + case ENUM_GET_FULL_CFG_DESC: + /* get FULL config descriptor (config, interface, endpoints) */ + if (USBH_Get_CfgDesc(phost, + phost->device.CfgDesc.wTotalLength) == USBH_OK) + { + phost->EnumState = ENUM_GET_MFC_STRING_DESC; + } + break; + + case ENUM_GET_MFC_STRING_DESC: + if (phost->device.DevDesc.iManufacturer != 0) + { /* Check that Manufacturer String is available */ + + if ( USBH_Get_StringDesc(phost, + phost->device.DevDesc.iManufacturer, + phost->device.Data , + 0xff) == USBH_OK) + { + /* User callback for Manufacturing string */ + USBH_UsrLog("Manufacturer : %s", (char *)phost->device.Data); + phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + } + } + else + { + USBH_UsrLog("Manufacturer : N/A"); + phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + } + break; + + case ENUM_GET_PRODUCT_STRING_DESC: + if (phost->device.DevDesc.iProduct != 0) + { /* Check that Product string is available */ + if ( USBH_Get_StringDesc(phost, + phost->device.DevDesc.iProduct, + phost->device.Data, + 0xff) == USBH_OK) + { + /* User callback for Product string */ + USBH_UsrLog("Product : %s", (char *)phost->device.Data); + phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC; + } + } + else + { + USBH_UsrLog("Product : N/A"); + phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + } + break; + + case ENUM_GET_SERIALNUM_STRING_DESC: + if (phost->device.DevDesc.iSerialNumber != 0) + { /* Check that Serial number string is available */ + if ( USBH_Get_StringDesc(phost, + phost->device.DevDesc.iSerialNumber, + phost->device.Data, + 0xff) == USBH_OK) + { + /* User callback for Serial number string */ + USBH_UsrLog("Serial Number : %s", (char *)phost->device.Data); + Status = USBH_OK; + } + } + else + { + USBH_UsrLog("Serial Number : N/A"); + Status = USBH_OK; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + } + break; + + default: + break; + } + return Status; +} + +/** + * @brief USBH_LL_SetTimer + * Set the initial Host Timer tick + * @param phost: Host Handle + * @retval None + */ +void USBH_LL_SetTimer (USBH_HandleTypeDef *phost, uint32_t time) +{ + phost->Timer = time; +} +/** + * @brief USBH_LL_IncTimer + * Increment Host Timer tick + * @param phost: Host Handle + * @retval None + */ +void USBH_LL_IncTimer (USBH_HandleTypeDef *phost) +{ + phost->Timer ++; + USBH_HandleSof(phost); +} + +/** + * @brief USBH_HandleSof + * Call SOF process + * @param phost: Host Handle + * @retval None + */ +void USBH_HandleSof (USBH_HandleTypeDef *phost) +{ + if((phost->gState == HOST_CLASS)&&(phost->pActiveClass != NULL)) + { + phost->pActiveClass->SOFProcess(phost); + } +} +/** + * @brief USBH_LL_Connect + * Handle USB Host connexion event + * @param phost: Host Handle + * @retval USBH_Status + */ +USBH_StatusTypeDef USBH_LL_Connect (USBH_HandleTypeDef *phost) +{ + if(phost->gState == HOST_IDLE ) + { + phost->device.is_connected = 1; + phost->gState = HOST_IDLE ; + + if(phost->pUser != NULL) + { + phost->pUser(phost, HOST_USER_CONNECTION); + } + } + else if(phost->gState == HOST_DEV_WAIT_FOR_ATTACHMENT ) + { + phost->gState = HOST_DEV_ATTACHED ; + } +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); +#endif + + return USBH_OK; +} + +/** + * @brief USBH_LL_Disconnect + * Handle USB Host disconnexion event + * @param phost: Host Handle + * @retval USBH_Status + */ +USBH_StatusTypeDef USBH_LL_Disconnect (USBH_HandleTypeDef *phost) +{ + /*Stop Host */ + USBH_LL_Stop(phost); + + /* FRee Control Pipes */ + USBH_FreePipe (phost, phost->Control.pipe_in); + USBH_FreePipe (phost, phost->Control.pipe_out); + + phost->device.is_connected = 0; + + if(phost->pUser != NULL) + { + phost->pUser(phost, HOST_USER_DISCONNECTION); + } + USBH_UsrLog("USB Device disconnected"); + + /* Start the low level driver */ + USBH_LL_Start(phost); + + phost->gState = HOST_DEV_DISCONNECTED; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); +#endif + + return USBH_OK; +} + + +#if (USBH_USE_OS == 1) +/** + * @brief USB Host Thread task + * @param pvParameters not used + * @retval None + */ +static void USBH_Process_OS(void const * argument) +{ + osEvent event; + + for(;;) + { + event = osMessageGet(((USBH_HandleTypeDef *)argument)->os_event, osWaitForever ); + + if( event.status == osEventMessage ) + { + USBH_Process((USBH_HandleTypeDef *)argument); + } + } +} + +/** +* @brief USBH_LL_NotifyURBChange +* Notify URB state Change +* @param phost: Host handle +* @retval USBH Status +*/ +USBH_StatusTypeDef USBH_LL_NotifyURBChange (USBH_HandleTypeDef *phost) +{ + osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); + return USBH_OK; +} +#endif +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbh_ctlreq.c b/ports/stm32/usbh_ctlreq.c new file mode 100644 index 000000000000..90dca7ffef12 --- /dev/null +++ b/ports/stm32/usbh_ctlreq.c @@ -0,0 +1,881 @@ +/** + ****************************************************************************** + * @file usbh_ctlreq.c + * @author MCD Application Team + * @version V3.0.0 + * @date 18-February-2014 + * @brief This file implements the control requests for device enumeration + ****************************************************************************** + * @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 "usbh_ctlreq.h" + +/** @addtogroup USBH_LIB +* @{ +*/ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_CTLREQ +* @brief This file implements the standard requests for device enumeration +* @{ +*/ + + +/** @defgroup USBH_CTLREQ_Private_Defines +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_CTLREQ_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + + +/** @defgroup USBH_CTLREQ_Private_Macros +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_CTLREQ_Private_Variables +* @{ +*/ +/** +* @} +*/ + +/** @defgroup USBH_CTLREQ_Private_FunctionPrototypes +* @{ +*/ +static USBH_StatusTypeDef USBH_HandleControl (USBH_HandleTypeDef *phost); + +static void USBH_ParseDevDesc (USBH_DevDescTypeDef* , uint8_t *buf, uint16_t length); + +static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc, + uint8_t *buf, + uint16_t length); + + +static void USBH_ParseEPDesc (USBH_EpDescTypeDef *ep_descriptor, uint8_t *buf); +static void USBH_ParseStringDesc (uint8_t* psrc, uint8_t* pdest, uint16_t length); +static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor, uint8_t *buf); + + +/** +* @} +*/ + + +/** @defgroup USBH_CTLREQ_Private_Functions +* @{ +*/ + + +/** + * @brief USBH_Get_DevDesc + * Issue Get Device Descriptor command to the device. Once the response + * received, it parses the device descriptor and updates the status. + * @param phost: Host Handle + * @param length: Length of the descriptor + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Get_DevDesc(USBH_HandleTypeDef *phost, uint8_t length) +{ + USBH_StatusTypeDef status; + + if((status = USBH_GetDescriptor(phost, + USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD, + USB_DESC_DEVICE, + phost->device.Data, + length)) == USBH_OK) + { + /* Commands successfully sent and Response Received */ + USBH_ParseDevDesc(&phost->device.DevDesc, phost->device.Data, length); + } + return status; +} + +/** + * @brief USBH_Get_CfgDesc + * Issues Configuration Descriptor to the device. Once the response + * received, it parses the configuartion descriptor and updates the + * status. + * @param phost: Host Handle + * @param length: Length of the descriptor + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Get_CfgDesc(USBH_HandleTypeDef *phost, + uint16_t length) + +{ + USBH_StatusTypeDef status; + uint8_t *pData; +#if (USBH_KEEP_CFG_DESCRIPTOR == 1) + pData = phost->device.CfgDesc_Raw; +#else + pData = phost->device.Data; +#endif + if((status = USBH_GetDescriptor(phost, + USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD, + USB_DESC_CONFIGURATION, + pData, + length)) == USBH_OK) + { + + /* Commands successfully sent and Response Received */ + USBH_ParseCfgDesc (&phost->device.CfgDesc, + pData, + length); + + } + return status; +} + + +/** + * @brief USBH_Get_StringDesc + * Issues string Descriptor command to the device. Once the response + * received, it parses the string descriptor and updates the status. + * @param phost: Host Handle + * @param string_index: String index for the descriptor + * @param buff: Buffer address for the descriptor + * @param length: Length of the descriptor + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Get_StringDesc(USBH_HandleTypeDef *phost, + uint8_t string_index, + uint8_t *buff, + uint16_t length) +{ + USBH_StatusTypeDef status; + if((status = USBH_GetDescriptor(phost, + USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD, + USB_DESC_STRING | string_index, + phost->device.Data, + length)) == USBH_OK) + { + /* Commands successfully sent and Response Received */ + USBH_ParseStringDesc(phost->device.Data,buff, length); + } + return status; +} + +/** + * @brief USBH_GetDescriptor + * Issues Descriptor command to the device. Once the response received, + * it parses the descriptor and updates the status. + * @param phost: Host Handle + * @param req_type: Descriptor type + * @param value_idx: wValue for the GetDescriptr request + * @param buff: Buffer to store the descriptor + * @param length: Length of the descriptor + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_GetDescriptor(USBH_HandleTypeDef *phost, + uint8_t req_type, + uint16_t value_idx, + uint8_t* buff, + uint16_t length ) +{ + if(phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_D2H | req_type; + phost->Control.setup.b.bRequest = USB_REQ_GET_DESCRIPTOR; + phost->Control.setup.b.wValue.w = value_idx; + + if ((value_idx & 0xff00) == USB_DESC_STRING) + { + phost->Control.setup.b.wIndex.w = 0x0409; + } + else + { + phost->Control.setup.b.wIndex.w = 0; + } + phost->Control.setup.b.wLength.w = length; + } + return USBH_CtlReq(phost, buff , length ); +} + +/** + * @brief USBH_SetAddress + * This command sets the address to the connected device + * @param phost: Host Handle + * @param DeviceAddress: Device address to assign + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_SetAddress(USBH_HandleTypeDef *phost, + uint8_t DeviceAddress) +{ + if(phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE | \ + USB_REQ_TYPE_STANDARD; + + phost->Control.setup.b.bRequest = USB_REQ_SET_ADDRESS; + + phost->Control.setup.b.wValue.w = (uint16_t)DeviceAddress; + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = 0; + } + return USBH_CtlReq(phost, 0 , 0 ); +} + +/** + * @brief USBH_SetCfg + * The command sets the configuration value to the connected device + * @param phost: Host Handle + * @param cfg_idx: Configuration value + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_SetCfg(USBH_HandleTypeDef *phost, + uint16_t cfg_idx) +{ + if(phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE |\ + USB_REQ_TYPE_STANDARD; + phost->Control.setup.b.bRequest = USB_REQ_SET_CONFIGURATION; + phost->Control.setup.b.wValue.w = cfg_idx; + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = 0; + } + + return USBH_CtlReq(phost, 0 , 0 ); +} + +/** + * @brief USBH_SetInterface + * The command sets the Interface value to the connected device + * @param phost: Host Handle + * @param altSetting: Interface value + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_SetInterface(USBH_HandleTypeDef *phost, + uint8_t ep_num, uint8_t altSetting) +{ + + if(phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE | \ + USB_REQ_TYPE_STANDARD; + + phost->Control.setup.b.bRequest = USB_REQ_SET_INTERFACE; + phost->Control.setup.b.wValue.w = altSetting; + phost->Control.setup.b.wIndex.w = ep_num; + phost->Control.setup.b.wLength.w = 0; + } + return USBH_CtlReq(phost, 0 , 0 ); +} + +/** + * @brief USBH_ClrFeature + * This request is used to clear or disable a specific feature. + * @param phost: Host Handle + * @param ep_num: endpoint number + * @param hc_num: Host channel number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_ClrFeature(USBH_HandleTypeDef *phost, + uint8_t ep_num) +{ + if(phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_H2D | + USB_REQ_RECIPIENT_ENDPOINT | + USB_REQ_TYPE_STANDARD; + + phost->Control.setup.b.bRequest = USB_REQ_CLEAR_FEATURE; + phost->Control.setup.b.wValue.w = FEATURE_SELECTOR_ENDPOINT; + phost->Control.setup.b.wIndex.w = ep_num; + phost->Control.setup.b.wLength.w = 0; + } + return USBH_CtlReq(phost, 0 , 0 ); +} + +/** + * @brief USBH_ParseDevDesc + * This function Parses the device descriptor + * @param dev_desc: device_descriptor destinaton address + * @param buf: Buffer where the source descriptor is available + * @param length: Length of the descriptor + * @retval None + */ +static void USBH_ParseDevDesc (USBH_DevDescTypeDef* dev_desc, + uint8_t *buf, + uint16_t length) +{ + dev_desc->bLength = *(uint8_t *) (buf + 0); + dev_desc->bDescriptorType = *(uint8_t *) (buf + 1); + dev_desc->bcdUSB = LE16 (buf + 2); + dev_desc->bDeviceClass = *(uint8_t *) (buf + 4); + dev_desc->bDeviceSubClass = *(uint8_t *) (buf + 5); + dev_desc->bDeviceProtocol = *(uint8_t *) (buf + 6); + dev_desc->bMaxPacketSize = *(uint8_t *) (buf + 7); + + if (length > 8) + { /* For 1st time after device connection, Host may issue only 8 bytes for + Device Descriptor Length */ + dev_desc->idVendor = LE16 (buf + 8); + dev_desc->idProduct = LE16 (buf + 10); + dev_desc->bcdDevice = LE16 (buf + 12); + dev_desc->iManufacturer = *(uint8_t *) (buf + 14); + dev_desc->iProduct = *(uint8_t *) (buf + 15); + dev_desc->iSerialNumber = *(uint8_t *) (buf + 16); + dev_desc->bNumConfigurations = *(uint8_t *) (buf + 17); + } +} + +/** + * @brief USBH_ParseCfgDesc + * This function Parses the configuration descriptor + * @param cfg_desc: Configuration Descriptor address + * @param buf: Buffer where the source descriptor is available + * @param length: Length of the descriptor + * @retval None + */ +static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc, + uint8_t *buf, + uint16_t length) +{ + USBH_InterfaceDescTypeDef *pif ; + USBH_EpDescTypeDef *pep; + USBH_DescHeader_t *pdesc = (USBH_DescHeader_t *)buf; + uint16_t ptr; + int8_t if_ix = 0; + int8_t ep_ix = 0; + + pdesc = (USBH_DescHeader_t *)buf; + + /* Parse configuration descriptor */ + cfg_desc->bLength = *(uint8_t *) (buf + 0); + cfg_desc->bDescriptorType = *(uint8_t *) (buf + 1); + cfg_desc->wTotalLength = LE16 (buf + 2); + cfg_desc->bNumInterfaces = *(uint8_t *) (buf + 4); + cfg_desc->bConfigurationValue = *(uint8_t *) (buf + 5); + cfg_desc->iConfiguration = *(uint8_t *) (buf + 6); + cfg_desc->bmAttributes = *(uint8_t *) (buf + 7); + cfg_desc->bMaxPower = *(uint8_t *) (buf + 8); + + + if (length > USB_CONFIGURATION_DESC_SIZE) + { + ptr = USB_LEN_CFG_DESC; + pif = (USBH_InterfaceDescTypeDef *)0; + + + while ((if_ix < USBH_MAX_NUM_INTERFACES ) && (ptr < cfg_desc->wTotalLength)) + { + pdesc = USBH_GetNextDesc((uint8_t *)pdesc, &ptr); + if (pdesc->bDescriptorType == USB_DESC_TYPE_INTERFACE) + { + pif = &cfg_desc->Itf_Desc[if_ix]; + USBH_ParseInterfaceDesc (pif, (uint8_t *)pdesc); + + ep_ix = 0; + pep = (USBH_EpDescTypeDef *)0; + while ((ep_ix < pif->bNumEndpoints) && (ptr < cfg_desc->wTotalLength)) + { + pdesc = USBH_GetNextDesc((void* )pdesc, &ptr); + if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT) + { + pep = &cfg_desc->Itf_Desc[if_ix].Ep_Desc[ep_ix]; + USBH_ParseEPDesc (pep, (uint8_t *)pdesc); + ep_ix++; + } + } + if_ix++; + } + } + } +} + + + +/** + * @brief USBH_ParseInterfaceDesc + * This function Parses the interface descriptor + * @param if_descriptor : Interface descriptor destination + * @param buf: Buffer where the descriptor data is available + * @retval None + */ +static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor, + uint8_t *buf) +{ + if_descriptor->bLength = *(uint8_t *) (buf + 0); + if_descriptor->bDescriptorType = *(uint8_t *) (buf + 1); + if_descriptor->bInterfaceNumber = *(uint8_t *) (buf + 2); + if_descriptor->bAlternateSetting = *(uint8_t *) (buf + 3); + if_descriptor->bNumEndpoints = *(uint8_t *) (buf + 4); + if_descriptor->bInterfaceClass = *(uint8_t *) (buf + 5); + if_descriptor->bInterfaceSubClass = *(uint8_t *) (buf + 6); + if_descriptor->bInterfaceProtocol = *(uint8_t *) (buf + 7); + if_descriptor->iInterface = *(uint8_t *) (buf + 8); +} + +/** + * @brief USBH_ParseEPDesc + * This function Parses the endpoint descriptor + * @param ep_descriptor: Endpoint descriptor destination address + * @param buf: Buffer where the parsed descriptor stored + * @retval None + */ +static void USBH_ParseEPDesc (USBH_EpDescTypeDef *ep_descriptor, + uint8_t *buf) +{ + + ep_descriptor->bLength = *(uint8_t *) (buf + 0); + ep_descriptor->bDescriptorType = *(uint8_t *) (buf + 1); + ep_descriptor->bEndpointAddress = *(uint8_t *) (buf + 2); + ep_descriptor->bmAttributes = *(uint8_t *) (buf + 3); + ep_descriptor->wMaxPacketSize = LE16 (buf + 4); + ep_descriptor->bInterval = *(uint8_t *) (buf + 6); +} + +/** + * @brief USBH_ParseStringDesc + * This function Parses the string descriptor + * @param psrc: Source pointer containing the descriptor data + * @param pdest: Destination address pointer + * @param length: Length of the descriptor + * @retval None + */ +static void USBH_ParseStringDesc (uint8_t* psrc, + uint8_t* pdest, + uint16_t length) +{ + uint16_t strlength; + uint16_t idx; + + /* The UNICODE string descriptor is not NULL-terminated. The string length is + computed by substracting two from the value of the first byte of the descriptor. + */ + + /* Check which is lower size, the Size of string or the length of bytes read + from the device */ + + if ( psrc[1] == USB_DESC_TYPE_STRING) + { /* Make sure the Descriptor is String Type */ + + /* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */ + strlength = ( ( (psrc[0]-2) <= length) ? (psrc[0]-2) :length); + psrc += 2; /* Adjust the offset ignoring the String Len and Descriptor type */ + + for (idx = 0; idx < strlength; idx+=2 ) + {/* Copy Only the string and ignore the UNICODE ID, hence add the src */ + *pdest = psrc[idx]; + pdest++; + } + *pdest = 0; /* mark end of string */ + } +} + +/** + * @brief USBH_GetNextDesc + * This function return the next descriptor header + * @param buf: Buffer where the cfg descriptor is available + * @param ptr: data popinter inside the cfg descriptor + * @retval next header + */ +USBH_DescHeader_t *USBH_GetNextDesc (uint8_t *pbuf, uint16_t *ptr) +{ + USBH_DescHeader_t *pnext; + + *ptr += ((USBH_DescHeader_t *)pbuf)->bLength; + pnext = (USBH_DescHeader_t *)((uint8_t *)pbuf + \ + ((USBH_DescHeader_t *)pbuf)->bLength); + + return(pnext); +} + + +/** + * @brief USBH_CtlReq + * USBH_CtlReq sends a control request and provide the status after + * completion of the request + * @param phost: Host Handle + * @param req: Setup Request Structure + * @param buff: data buffer address to store the response + * @param length: length of the response + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_CtlReq (USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length) +{ + USBH_StatusTypeDef status; + status = USBH_BUSY; + + switch (phost->RequestState) + { + case CMD_SEND: + /* Start a SETUP transfer */ + phost->Control.buff = buff; + phost->Control.length = length; + phost->Control.state = CTRL_SETUP; + phost->RequestState = CMD_WAIT; + status = USBH_BUSY; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + break; + + case CMD_WAIT: + status = USBH_HandleControl(phost); + if (status == USBH_OK) + { + /* Commands successfully sent and Response Received */ + phost->RequestState = CMD_SEND; + phost->Control.state =CTRL_IDLE; + status = USBH_OK; + } + else if (status == USBH_FAIL) + { + /* Failure Mode */ + phost->RequestState = CMD_SEND; + status = USBH_FAIL; + } + break; + + default: + break; + } + return status; +} + +/** + * @brief USBH_HandleControl + * Handles the USB control transfer state machine + * @param phost: Host Handle + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_HandleControl (USBH_HandleTypeDef *phost) +{ + uint8_t direction; + USBH_StatusTypeDef status = USBH_BUSY; + USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE; + + switch (phost->Control.state) + { + case CTRL_SETUP: + /* send a SETUP packet */ + USBH_CtlSendSetup (phost, + (uint8_t *)phost->Control.setup.d8 , + phost->Control.pipe_out); + + phost->Control.state = CTRL_SETUP_WAIT; + break; + + case CTRL_SETUP_WAIT: + + URB_Status = USBH_LL_GetURBState(phost, phost->Control.pipe_out); + /* case SETUP packet sent successfully */ + if(URB_Status == USBH_URB_DONE) + { + direction = (phost->Control.setup.b.bmRequestType & USB_REQ_DIR_MASK); + + /* check if there is a data stage */ + if (phost->Control.setup.b.wLength.w != 0 ) + { + if (direction == USB_D2H) + { + /* Data Direction is IN */ + phost->Control.state = CTRL_DATA_IN; + } + else + { + /* Data Direction is OUT */ + phost->Control.state = CTRL_DATA_OUT; + } + } + /* No DATA stage */ + else + { + /* If there is No Data Transfer Stage */ + if (direction == USB_D2H) + { + /* Data Direction is IN */ + phost->Control.state = CTRL_STATUS_OUT; + } + else + { + /* Data Direction is OUT */ + phost->Control.state = CTRL_STATUS_IN; + } + } +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + else if(URB_Status == USBH_URB_ERROR) + { + phost->Control.state = CTRL_ERROR; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + break; + + case CTRL_DATA_IN: + /* Issue an IN token */ + phost->Control.timer = phost->Timer; + USBH_CtlReceiveData(phost, + phost->Control.buff, + phost->Control.length, + phost->Control.pipe_in); + + phost->Control.state = CTRL_DATA_IN_WAIT; + break; + + case CTRL_DATA_IN_WAIT: + + URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_in); + + /* check is DATA packet transfered successfully */ + if (URB_Status == USBH_URB_DONE) + { + phost->Control.state = CTRL_STATUS_OUT; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + + /* manage error cases*/ + if (URB_Status == USBH_URB_STALL) + { + /* In stall case, return to previous machine state*/ + status = USBH_NOT_SUPPORTED; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + else if (URB_Status == USBH_URB_ERROR) + { + /* Device error */ + phost->Control.state = CTRL_ERROR; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + break; + + case CTRL_DATA_OUT: + + USBH_CtlSendData (phost, + phost->Control.buff, + phost->Control.length , + phost->Control.pipe_out, + 1); + phost->Control.timer = phost->Timer; + phost->Control.state = CTRL_DATA_OUT_WAIT; + break; + + case CTRL_DATA_OUT_WAIT: + + URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_out); + + if (URB_Status == USBH_URB_DONE) + { /* If the Setup Pkt is sent successful, then change the state */ + phost->Control.state = CTRL_STATUS_IN; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + + /* handle error cases */ + else if (URB_Status == USBH_URB_STALL) + { + /* In stall case, return to previous machine state*/ + phost->Control.state = CTRL_STALLED; + status = USBH_NOT_SUPPORTED; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + else if (URB_Status == USBH_URB_NOTREADY) + { + /* Nack received from device */ + phost->Control.state = CTRL_DATA_OUT; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + else if (URB_Status == USBH_URB_ERROR) + { + /* device error */ + phost->Control.state = CTRL_ERROR; + status = USBH_FAIL; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + break; + + + case CTRL_STATUS_IN: + /* Send 0 bytes out packet */ + USBH_CtlReceiveData (phost, + 0, + 0, + phost->Control.pipe_in); + phost->Control.timer = phost->Timer; + phost->Control.state = CTRL_STATUS_IN_WAIT; + + break; + + case CTRL_STATUS_IN_WAIT: + + URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_in); + + if ( URB_Status == USBH_URB_DONE) + { /* Control transfers completed, Exit the State Machine */ + phost->Control.state = CTRL_COMPLETE; + status = USBH_OK; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + + else if (URB_Status == USBH_URB_ERROR) + { + phost->Control.state = CTRL_ERROR; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + else if(URB_Status == USBH_URB_STALL) + { + /* Control transfers completed, Exit the State Machine */ + status = USBH_NOT_SUPPORTED; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + break; + + case CTRL_STATUS_OUT: + USBH_CtlSendData (phost, + 0, + 0, + phost->Control.pipe_out, + 1); + phost->Control.timer = phost->Timer; + phost->Control.state = CTRL_STATUS_OUT_WAIT; + break; + + case CTRL_STATUS_OUT_WAIT: + + URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_out); + if (URB_Status == USBH_URB_DONE) + { + status = USBH_OK; + phost->Control.state = CTRL_COMPLETE; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + else if (URB_Status == USBH_URB_NOTREADY) + { + phost->Control.state = CTRL_STATUS_OUT; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + else if (URB_Status == USBH_URB_ERROR) + { + phost->Control.state = CTRL_ERROR; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + break; + + case CTRL_ERROR: + /* + After a halt condition is encountered or an error is detected by the + host, a control endpoint is allowed to recover by accepting the next Setup + PID; i.e., recovery actions via some other pipe are not required for control + endpoints. For the Default Control Pipe, a device reset will ultimately be + required to clear the halt or error condition if the next Setup PID is not + accepted. + */ + if (++ phost->Control.errorcount <= USBH_MAX_ERROR_COUNT) + { + /* try to recover control */ + USBH_LL_Stop(phost); + + /* Do the transmission again, starting from SETUP Packet */ + phost->Control.state = CTRL_SETUP; + phost->RequestState = CMD_SEND; + } + else + { + phost->Control.errorcount = 0; + USBH_ErrLog("Control error"); + status = USBH_FAIL; + + } + break; + + default: + break; + } + return status; +} + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + + diff --git a/ports/stm32/usbh_ioreq.c b/ports/stm32/usbh_ioreq.c new file mode 100644 index 000000000000..8c869eadb6a1 --- /dev/null +++ b/ports/stm32/usbh_ioreq.c @@ -0,0 +1,358 @@ +/** + ****************************************************************************** + * @file usbh_ioreq.c + * @author MCD Application Team + * @version V3.0.0 + * @date 18-February-2014 + * @brief This file handles the issuing of the USB transactions + ****************************************************************************** + * @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 "usbh_ioreq.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_IOREQ + * @brief This file handles the standard protocol processing (USB v2.0) + * @{ + */ + + +/** @defgroup USBH_IOREQ_Private_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + + +/** @defgroup USBH_IOREQ_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Private_Variables + * @{ + */ +/** + * @} + */ +/** @defgroup USBH_IOREQ_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Private_Functions + * @{ + */ + + + +/** + * @brief USBH_CtlSendSetup + * Sends the Setup Packet to the Device + * @param phost: Host Handle + * @param buff: Buffer pointer from which the Data will be send to Device + * @param pipe_num: Pipe Number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_CtlSendSetup (USBH_HandleTypeDef *phost, + uint8_t *buff, + uint8_t pipe_num) +{ + + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 0, /* Direction : OUT */ + USBH_EP_CONTROL, /* EP type */ + USBH_PID_SETUP, /* Type setup */ + buff, /* data buffer */ + USBH_SETUP_PKT_SIZE, /* data length */ + 0); + return USBH_OK; +} + + +/** + * @brief USBH_CtlSendData + * Sends a data Packet to the Device + * @param phost: Host Handle + * @param buff: Buffer pointer from which the Data will be sent to Device + * @param length: Length of the data to be sent + * @param pipe_num: Pipe Number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_CtlSendData (USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length, + uint8_t pipe_num, + uint8_t do_ping ) +{ + if(phost->device.speed != USBH_SPEED_HIGH) + { + do_ping = 0; + } + + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 0, /* Direction : OUT */ + USBH_EP_CONTROL, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + do_ping); /* do ping (HS Only)*/ + + return USBH_OK; +} + + +/** + * @brief USBH_CtlReceiveData + * Receives the Device Response to the Setup Packet + * @param phost: Host Handle + * @param buff: Buffer pointer in which the response needs to be copied + * @param length: Length of the data to be received + * @param pipe_num: Pipe Number + * @retval USBH Status. + */ +USBH_StatusTypeDef USBH_CtlReceiveData(USBH_HandleTypeDef *phost, + uint8_t* buff, + uint16_t length, + uint8_t pipe_num) +{ + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 1, /* Direction : IN */ + USBH_EP_CONTROL, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0); + return USBH_OK; + +} + + +/** + * @brief USBH_BulkSendData + * Sends the Bulk Packet to the device + * @param phost: Host Handle + * @param buff: Buffer pointer from which the Data will be sent to Device + * @param length: Length of the data to be sent + * @param pipe_num: Pipe Number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_BulkSendData (USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length, + uint8_t pipe_num, + uint8_t do_ping ) +{ + if(phost->device.speed != USBH_SPEED_HIGH) + { + do_ping = 0; + } + + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 0, /* Direction : IN */ + USBH_EP_BULK, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + do_ping); /* do ping (HS Only)*/ + return USBH_OK; +} + + +/** + * @brief USBH_BulkReceiveData + * Receives IN bulk packet from device + * @param phost: Host Handle + * @param buff: Buffer pointer in which the received data packet to be copied + * @param length: Length of the data to be received + * @param pipe_num: Pipe Number + * @retval USBH Status. + */ +USBH_StatusTypeDef USBH_BulkReceiveData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length, + uint8_t pipe_num) +{ + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 1, /* Direction : IN */ + USBH_EP_BULK, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0); + return USBH_OK; +} + + +/** + * @brief USBH_InterruptReceiveData + * Receives the Device Response to the Interrupt IN token + * @param phost: Host Handle + * @param buff: Buffer pointer in which the response needs to be copied + * @param length: Length of the data to be received + * @param pipe_num: Pipe Number + * @retval USBH Status. + */ +USBH_StatusTypeDef USBH_InterruptReceiveData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint8_t length, + uint8_t pipe_num) +{ + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 1, /* Direction : IN */ + USBH_EP_INTERRUPT, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0); + + return USBH_OK; +} + +/** + * @brief USBH_InterruptSendData + * Sends the data on Interrupt OUT Endpoint + * @param phost: Host Handle + * @param buff: Buffer pointer from where the data needs to be copied + * @param length: Length of the data to be sent + * @param pipe_num: Pipe Number + * @retval USBH Status. + */ +USBH_StatusTypeDef USBH_InterruptSendData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint8_t length, + uint8_t pipe_num) +{ + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 0, /* Direction : OUT */ + USBH_EP_INTERRUPT, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0); + + return USBH_OK; +} + +/** + * @brief USBH_IsocReceiveData + * Receives the Device Response to the Isochronous IN token + * @param phost: Host Handle + * @param buff: Buffer pointer in which the response needs to be copied + * @param length: Length of the data to be received + * @param pipe_num: Pipe Number + * @retval USBH Status. + */ +USBH_StatusTypeDef USBH_IsocReceiveData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint32_t length, + uint8_t pipe_num) +{ + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 1, /* Direction : IN */ + USBH_EP_ISO, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0); + + + return USBH_OK; +} + +/** + * @brief USBH_IsocSendData + * Sends the data on Isochronous OUT Endpoint + * @param phost: Host Handle + * @param buff: Buffer pointer from where the data needs to be copied + * @param length: Length of the data to be sent + * @param pipe_num: Pipe Number + * @retval USBH Status. + */ +USBH_StatusTypeDef USBH_IsocSendData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint32_t length, + uint8_t pipe_num) +{ + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 0, /* Direction : OUT */ + USBH_EP_ISO, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0); + + return USBH_OK; +} +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + diff --git a/ports/stm32/usbh_pipes.c b/ports/stm32/usbh_pipes.c new file mode 100644 index 000000000000..de20a0b3fd82 --- /dev/null +++ b/ports/stm32/usbh_pipes.c @@ -0,0 +1,204 @@ +/** + ****************************************************************************** + * @file usbh_pipes.c + * @author MCD Application Team + * @version V3.0.0 + * @date 18-February-2014 + * @brief This file implements functions for opening and closing Pipes + ****************************************************************************** + * @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 "usbh_pipes.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_PIPES + * @brief This file includes opening and closing Pipes + * @{ + */ + +/** @defgroup USBH_PIPES_Private_Defines + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_PIPES_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_PIPES_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_PIPES_Private_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBH_PIPES_Private_Functions + * @{ + */ +static uint16_t USBH_GetFreePipe (USBH_HandleTypeDef *phost); + + +/** + * @brief USBH_Open_Pipe + * Open a pipe + * @param phost: Host Handle + * @param pipe_num: Pipe Number + * @param dev_address: USB Device address allocated to attached device + * @param speed : USB device speed (Full/Low) + * @param ep_type: end point type (Bulk/int/ctl) + * @param mps: max pkt size + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_OpenPipe (USBH_HandleTypeDef *phost, + uint8_t pipe_num, + uint8_t epnum, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps) +{ + + USBH_LL_OpenPipe(phost, + pipe_num, + epnum, + dev_address, + speed, + ep_type, + mps); + + return USBH_OK; + +} + +/** + * @brief USBH_ClosePipe + * Close a pipe + * @param phost: Host Handle + * @param pipe_num: Pipe Number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_ClosePipe (USBH_HandleTypeDef *phost, + uint8_t pipe_num) +{ + + USBH_LL_ClosePipe(phost, pipe_num); + + return USBH_OK; + +} + +/** + * @brief USBH_Alloc_Pipe + * Allocate a new Pipe + * @param phost: Host Handle + * @param ep_addr: End point for which the Pipe to be allocated + * @retval Pipe number + */ +uint8_t USBH_AllocPipe (USBH_HandleTypeDef *phost, uint8_t ep_addr) +{ + uint16_t pipe; + + pipe = USBH_GetFreePipe(phost); + + if (pipe != 0xFFFF) + { + phost->Pipes[pipe] = 0x8000 | ep_addr; + } + return pipe; +} + +/** + * @brief USBH_Free_Pipe + * Free the USB Pipe + * @param phost: Host Handle + * @param idx: Pipe number to be freed + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_FreePipe (USBH_HandleTypeDef *phost, uint8_t idx) +{ + if(idx < 11) + { + phost->Pipes[idx] &= 0x7FFF; + } + return USBH_OK; +} + +/** + * @brief USBH_GetFreePipe + * @param phost: Host Handle + * Get a free Pipe number for allocation to a device endpoint + * @retval idx: Free Pipe number + */ +static uint16_t USBH_GetFreePipe (USBH_HandleTypeDef *phost) +{ + uint8_t idx = 0; + + for (idx = 0 ; idx < 11 ; idx++) + { + if ((phost->Pipes[idx] & 0x8000) == 0) + { + return idx; + } + } + return 0xFFFF; +} +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + diff --git a/ports/stm32/usbh_platform.c b/ports/stm32/usbh_platform.c new file mode 100644 index 000000000000..47c1d92d026c --- /dev/null +++ b/ports/stm32/usbh_platform.c @@ -0,0 +1,54 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : usbh_platform.c + + * @brief : This file implements the USB platform + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_platform.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/** + * @brief Drive VBUS. + * @param state : VBUS state + * This parameter can be one of the these values: + * - 1 : VBUS Active + * - 0 : VBUS Inactive + */ +void MX_DriverVbusFS(uint8_t state) +{ + uint8_t data = state; + /* USER CODE BEGIN PREPARE_GPIO_DATA_VBUS_FS */ + if(state == 0) + { + /* Drive high Charge pump */ + data = GPIO_PIN_SET; + } + else + { + /* Drive low Charge pump */ + data = GPIO_PIN_RESET; + } + /* USER CODE END PREPARE_GPIO_DATA_VBUS_FS */ + HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,(GPIO_PinState)data); +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbhost/Class/HID/Inc/usbh_hid.h b/ports/stm32/usbhost/Class/HID/Inc/usbh_hid.h index 38302ad0d44b..437700eed177 100644 --- a/ports/stm32/usbhost/Class/HID/Inc/usbh_hid.h +++ b/ports/stm32/usbhost/Class/HID/Inc/usbh_hid.h @@ -106,16 +106,16 @@ /* 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_INIT_HOST= 0, + HID_IDLE_HOST, + HID_SEND_DATA_HOST, + HID_BUSY_HOST, + HID_GET_DATA_HOST, + HID_SYNC_HOST, + HID_POLL_HOST, + HID_ERROR_HOST, } -HID_StateTypeDef; +HID_Host_StateTypeDef; typedef enum { @@ -213,7 +213,7 @@ typedef struct _HID_Process { uint8_t OutPipe; uint8_t InPipe; - HID_StateTypeDef state; + HID_Host_StateTypeDef state; uint8_t OutEp; uint8_t InEp; HID_CtlStateTypeDef ctl_state; diff --git a/ports/stm32/usbhost/Core/Inc/usb_host.h b/ports/stm32/usbhost/Core/Inc/usb_host.h new file mode 100644 index 000000000000..6f58f4034657 --- /dev/null +++ b/ports/stm32/usbhost/Core/Inc/usb_host.h @@ -0,0 +1,95 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : usb_host.h + * @version : v1.0_Cube + * @brief : Header for usb_host.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_HOST__H__ +#define __USB_HOST__H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" +#include "stm32f4xx_hal.h" +#include "usbh_def.h" +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/** @addtogroup USBH_OTG_DRIVER + * @{ + */ + +/** @defgroup USBH_HOST USBH_HOST + * @brief Host file for Usb otg low level driver. + * @{ + */ + +/** @defgroup USBH_HOST_Exported_Variables USBH_HOST_Exported_Variables + * @brief Public variables. + * @{ + */ + +/** + * @} + */ + +/** Status of the application. */ +typedef enum { + APPLICATION_IDLE = 0, + APPLICATION_START, + APPLICATION_READY, + APPLICATION_DISCONNECT +}ApplicationTypeDef; + +/** @defgroup USBH_HOST_Exported_FunctionsPrototype USBH_HOST_Exported_FunctionsPrototype + * @brief Declaration of public functions for Usb host. + * @{ + */ + +/* Exported functions -------------------------------------------------------*/ + +/** @brief USB Host initialization function. */ +void MX_USB_HOST_Init(void); +/* + * user callback declaration + */ +void USBH_UserProcess(USBH_HandleTypeDef *phost, uint8_t id); +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_HOST__H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbhost/Core/Inc/usbh_conf.h b/ports/stm32/usbhost/Core/Inc/usbh_conf.h new file mode 100644 index 000000000000..347015c7edc0 --- /dev/null +++ b/ports/stm32/usbhost/Core/Inc/usbh_conf.h @@ -0,0 +1,195 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : Target/usbh_conf.h + * @version : v1.0_Cube + * @brief : Header for usbh_conf.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBH_CONF__H__ +#define __USBH_CONF__H__ +#ifdef __cplusplus + extern "C" { +#endif +/* Includes ------------------------------------------------------------------*/ + +#include +#include +#include +#include "usbh_main.h" +#include "stm32f4xx.h" +#include "stm32f4xx_hal.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/** @addtogroup STM32_USB_HOST_LIBRARY + * @{ + */ + +/** @defgroup USBH_CONF + * @brief usb host low level driver configuration file + * @{ + */ + +/** @defgroup USBH_CONF_Exported_Variables USBH_CONF_Exported_Variables + * @brief Public variables. + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBH_CONF_Exported_Defines USBH_CONF_Exported_Defines + * @brief Defines for configuration of the Usb host. + * @{ + */ + +/*---------- -----------*/ +#define USBH_MAX_NUM_ENDPOINTS 2U + +/*---------- -----------*/ +#define USBH_MAX_NUM_INTERFACES 2U + +/*---------- -----------*/ +#define USBH_MAX_NUM_CONFIGURATION 1U + +/*---------- -----------*/ +#define USBH_KEEP_CFG_DESCRIPTOR 1U + +/*---------- -----------*/ +#define USBH_MAX_NUM_SUPPORTED_CLASS 1U + +/*---------- -----------*/ +#define USBH_MAX_SIZE_CONFIGURATION 256U + +/*---------- -----------*/ +#define USBH_MAX_DATA_BUFFER 512U + +/*---------- -----------*/ +#define USBH_DEBUG_LEVEL 0U + +/*---------- -----------*/ +#define USBH_USE_OS 0 + +/****************************************/ +/* #define for FS and HS identification */ +#define HOST_HS 0 +#define HOST_FS 1 + +#if (USBH_USE_OS == 1) + #include "cmsis_os.h" + #define USBH_PROCESS_PRIO osPriorityNormal + #define USBH_PROCESS_STACK_SIZE ((uint16_t)128) +#endif /* (USBH_USE_OS == 1) */ + +/** + * @} + */ + +/** @defgroup USBH_CONF_Exported_Macros USBH_CONF_Exported_Macros + * @brief Aliases. + * @{ + */ + +/* Memory management macros */ + +/** Alias for memory allocation. */ +#define USBH_malloc malloc + +/** Alias for memory release. */ +#define USBH_free free + +/** Alias for memory set. */ +#define USBH_memset memset + +/** Alias for memory copy. */ +#define USBH_memcpy memcpy + +/* DEBUG macros */ + +#if (USBH_DEBUG_LEVEL > 0U) +#define USBH_UsrLog(...) do { \ + printf(__VA_ARGS__); \ + printf("\n"); \ +} while (0) +#else +#define USBH_UsrLog(...) do {} while (0) +#endif + +#if (USBH_DEBUG_LEVEL > 1U) + +#define USBH_ErrLog(...) do { \ + printf("ERROR: ") ; \ + printf(__VA_ARGS__); \ + printf("\n"); \ +} while (0) +#else +#define USBH_ErrLog(...) do {} while (0) +#endif + +#if (USBH_DEBUG_LEVEL > 2U) +#define USBH_DbgLog(...) do { \ + printf("DEBUG : ") ; \ + printf(__VA_ARGS__); \ + printf("\n"); \ +} while (0) +#else +#define USBH_DbgLog(...) do {} while (0) +#endif + +/** + * @} + */ + +/** @defgroup USBH_CONF_Exported_Types USBH_CONF_Exported_Types + * @brief Types. + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBH_CONF_Exported_FunctionsPrototype USBH_CONF_Exported_FunctionsPrototype + * @brief Declaration of public functions for Usb host. + * @{ + */ + +/* Exported functions -------------------------------------------------------*/ +void Error_Handler(void); +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_CONF__H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbhost/Core/Inc/usbh_core.h b/ports/stm32/usbhost/Core/Inc/usbh_core.h index bc3da6d1fe90..5bafdf76b3e2 100644 --- a/ports/stm32/usbhost/Core/Inc/usbh_core.h +++ b/ports/stm32/usbhost/Core/Inc/usbh_core.h @@ -138,6 +138,8 @@ uint8_t USBH_LL_GetToggle (USBH_HandleTypeDef *phost, uint8_t ); void USBH_Delay (uint32_t Delay); void USBH_LL_SetTimer (USBH_HandleTypeDef *phost, uint32_t ); void USBH_LL_IncTimer (USBH_HandleTypeDef *phost); +void USBH_LL_PortDisabled(USBH_HandleTypeDef *phost); +void USBH_LL_PortEnabled(USBH_HandleTypeDef *phost); /** * @} */ diff --git a/ports/stm32/usbhost/Core/Inc/usbh_def.h b/ports/stm32/usbhost/Core/Inc/usbh_def.h index cf24d69f3702..9015d829713b 100644 --- a/ports/stm32/usbhost/Core/Inc/usbh_def.h +++ b/ports/stm32/usbhost/Core/Inc/usbh_def.h @@ -418,6 +418,7 @@ typedef struct uint8_t Data[USBH_MAX_DATA_BUFFER]; uint8_t address; uint8_t speed; + uint8_t PortEnabled; __IO uint8_t is_connected; uint8_t current_interface; USBH_DevDescTypeDef DevDesc; diff --git a/ports/stm32/usbhost/Core/Inc/usbh_main.h b/ports/stm32/usbhost/Core/Inc/usbh_main.h new file mode 100644 index 000000000000..9012d5f3dc99 --- /dev/null +++ b/ports/stm32/usbhost/Core/Inc/usbh_main.h @@ -0,0 +1,271 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.h + * @brief : Header for main.c file. + * This file contains the common defines of the application. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __MAIN_H +#define __MAIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ +/* USER CODE BEGIN EC */ + +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ + +/* USER CODE END EM */ + +/* Exported functions prototypes ---------------------------------------------*/ +//void Error_Handler(void); + +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +/* Private defines -----------------------------------------------------------*/ +#define SAI1_FSA_Pin GPIO_PIN_4 +#define SAI1_FSA_GPIO_Port GPIOE +#define SPKR_HP_Pin GPIO_PIN_3 +#define SPKR_HP_GPIO_Port GPIOE +#define AUDIO_RST_Pin GPIO_PIN_2 +#define AUDIO_RST_GPIO_Port GPIOE +#define ARDUINO_USART6_TX_Pin GPIO_PIN_14 +#define ARDUINO_USART6_TX_GPIO_Port GPIOG +#define FMC_NBL1_Pin GPIO_PIN_1 +#define FMC_NBL1_GPIO_Port GPIOE +#define FMC_NBL0_Pin GPIO_PIN_0 +#define FMC_NBL0_GPIO_Port GPIOE +#define I2C1_SCL_Pin GPIO_PIN_8 +#define I2C1_SCL_GPIO_Port GPIOB +#define I2S3_CK_Pin GPIO_PIN_3 +#define I2S3_CK_GPIO_Port GPIOB +#define uSD_CLK_Pin GPIO_PIN_12 +#define uSD_CLK_GPIO_Port GPIOC +#define SWCLK_Pin GPIO_PIN_14 +#define SWCLK_GPIO_Port GPIOA +#define SWDIO_Pin GPIO_PIN_13 +#define SWDIO_GPIO_Port GPIOA +#define SAI1_SCKA_Pin GPIO_PIN_5 +#define SAI1_SCKA_GPIO_Port GPIOE +#define I2C1_SDA_Pin GPIO_PIN_9 +#define I2C1_SDA_GPIO_Port GPIOB +#define OTG_FS1_OverCurrent_Pin GPIO_PIN_7 +#define OTG_FS1_OverCurrent_GPIO_Port GPIOB +#define QSPI_BK1_NCS_Pin GPIO_PIN_6 +#define QSPI_BK1_NCS_GPIO_Port GPIOB +#define SDNCAS_Pin GPIO_PIN_15 +#define SDNCAS_GPIO_Port GPIOG +#define MIC_DATA_Pin GPIO_PIN_6 +#define MIC_DATA_GPIO_Port GPIOD +#define D2_Pin GPIO_PIN_0 +#define D2_GPIO_Port GPIOD +#define uSD_D3_Pin GPIO_PIN_11 +#define uSD_D3_GPIO_Port GPIOC +#define uSD_D2_Pin GPIO_PIN_10 +#define uSD_D2_GPIO_Port GPIOC +#define USB_FS1_P_Pin GPIO_PIN_12 +#define USB_FS1_P_GPIO_Port GPIOA +#define FMC_NBL2_Pin GPIO_PIN_4 +#define FMC_NBL2_GPIO_Port GPIOI +#define LED3_Pin GPIO_PIN_5 +#define LED3_GPIO_Port GPIOD +#define D3_Pin GPIO_PIN_1 +#define D3_GPIO_Port GPIOD +#define D27_Pin GPIO_PIN_3 +#define D27_GPIO_Port GPIOI +#define D26_Pin GPIO_PIN_2 +#define D26_GPIO_Port GPIOI +#define USB_FS1_N_Pin GPIO_PIN_11 +#define USB_FS1_N_GPIO_Port GPIOA +#define A0_Pin GPIO_PIN_0 +#define A0_GPIO_Port GPIOF +#define FMC_NBL3_Pin GPIO_PIN_5 +#define FMC_NBL3_GPIO_Port GPIOI +#define D29_Pin GPIO_PIN_7 +#define D29_GPIO_Port GPIOI +#define D31_Pin GPIO_PIN_10 +#define D31_GPIO_Port GPIOI +#define D28_Pin GPIO_PIN_6 +#define D28_GPIO_Port GPIOI +#define LED4_Pin GPIO_PIN_3 +#define LED4_GPIO_Port GPIOK +#define USART6_RX_Pin GPIO_PIN_9 +#define USART6_RX_GPIO_Port GPIOG +#define LED2_Pin GPIO_PIN_4 +#define LED2_GPIO_Port GPIOD +#define uSD_CMD_Pin GPIO_PIN_2 +#define uSD_CMD_GPIO_Port GPIOD +#define D23_Pin GPIO_PIN_15 +#define D23_GPIO_Port GPIOH +#define D25_Pin GPIO_PIN_1 +#define D25_GPIO_Port GPIOI +#define USB_FS1_ID_Pin GPIO_PIN_10 +#define USB_FS1_ID_GPIO_Port GPIOA +#define A1_Pin GPIO_PIN_1 +#define A1_GPIO_Port GPIOF +#define D30_Pin GPIO_PIN_9 +#define D30_GPIO_Port GPIOI +#define D21_Pin GPIO_PIN_13 +#define D21_GPIO_Port GPIOH +#define D22_Pin GPIO_PIN_14 +#define D22_GPIO_Port GPIOH +#define D24_Pin GPIO_PIN_0 +#define D24_GPIO_Port GPIOI +#define VBUS_FS1_Pin GPIO_PIN_9 +#define VBUS_FS1_GPIO_Port GPIOA +#define uSD_D1_Pin GPIO_PIN_9 +#define uSD_D1_GPIO_Port GPIOC +#define A2_Pin GPIO_PIN_2 +#define A2_GPIO_Port GPIOF +#define uSD_D0_Pin GPIO_PIN_8 +#define uSD_D0_GPIO_Port GPIOC +#define A3_Pin GPIO_PIN_3 +#define A3_GPIO_Port GPIOF +#define I2C2_SCL_Pin GPIO_PIN_4 +#define I2C2_SCL_GPIO_Port GPIOH +#define SDCLK_Pin GPIO_PIN_8 +#define SDCLK_GPIO_Port GPIOG +#define A4_Pin GPIO_PIN_4 +#define A4_GPIO_Port GPIOF +#define I2C2_SDA_Pin GPIO_PIN_5 +#define I2C2_SDA_GPIO_Port GPIOH +#define SDNE0_Pin GPIO_PIN_3 +#define SDNE0_GPIO_Port GPIOH +#define SAI1_MCLKA_Pin GPIO_PIN_7 +#define SAI1_MCLKA_GPIO_Port GPIOG +#define LED1_Pin GPIO_PIN_6 +#define LED1_GPIO_Port GPIOG +#define QSPI_BK1_IO2_Pin GPIO_PIN_7 +#define QSPI_BK1_IO2_GPIO_Port GPIOF +#define QSPI_BK1_IO3_Pin GPIO_PIN_6 +#define QSPI_BK1_IO3_GPIO_Port GPIOF +#define A5_Pin GPIO_PIN_5 +#define A5_GPIO_Port GPIOF +#define SDCKE0_Pin GPIO_PIN_2 +#define SDCKE0_GPIO_Port GPIOH +#define D1_Pin GPIO_PIN_15 +#define D1_GPIO_Port GPIOD +#define D15_Pin GPIO_PIN_10 +#define D15_GPIO_Port GPIOD +#define QSPI_CLK_Pin GPIO_PIN_10 +#define QSPI_CLK_GPIO_Port GPIOF +#define QSPI_BK1_IO1_Pin GPIO_PIN_9 +#define QSPI_BK1_IO1_GPIO_Port GPIOF +#define QSPI_BK1_IO0_Pin GPIO_PIN_8 +#define QSPI_BK1_IO0_GPIO_Port GPIOF +#define D0_Pin GPIO_PIN_14 +#define D0_GPIO_Port GPIOD +#define D14_Pin GPIO_PIN_9 +#define D14_GPIO_Port GPIOD +#define D13_Pin GPIO_PIN_8 +#define D13_GPIO_Port GPIOD +#define SDNWE_Pin GPIO_PIN_0 +#define SDNWE_GPIO_Port GPIOC +#define OTG_FS1_PowerSwitchOn_Pin GPIO_PIN_2 +#define OTG_FS1_PowerSwitchOn_GPIO_Port GPIOB +#define A6_Pin GPIO_PIN_12 +#define A6_GPIO_Port GPIOF +#define A11_Pin GPIO_PIN_1 +#define A11_GPIO_Port GPIOG +#define A9_Pin GPIO_PIN_15 +#define A9_GPIO_Port GPIOF +#define MIC_CK_Pin GPIO_PIN_13 +#define MIC_CK_GPIO_Port GPIOD +#define uSD_Detect_Pin GPIO_PIN_2 +#define uSD_Detect_GPIO_Port GPIOG +#define LCD_INT_Pin GPIO_PIN_5 +#define LCD_INT_GPIO_Port GPIOJ +#define D20_Pin GPIO_PIN_12 +#define D20_GPIO_Port GPIOH +#define WAKEUP_Pin GPIO_PIN_0 +#define WAKEUP_GPIO_Port GPIOA +#define A7_Pin GPIO_PIN_13 +#define A7_GPIO_Port GPIOF +#define A10_Pin GPIO_PIN_0 +#define A10_GPIO_Port GPIOG +#define D5_Pin GPIO_PIN_8 +#define D5_GPIO_Port GPIOE +#define D17_Pin GPIO_PIN_9 +#define D17_GPIO_Port GPIOH +#define D19_Pin GPIO_PIN_11 +#define D19_GPIO_Port GPIOH +#define A8_Pin GPIO_PIN_14 +#define A8_GPIO_Port GPIOF +#define DSI_TE_Pin GPIO_PIN_2 +#define DSI_TE_GPIO_Port GPIOJ +#define SDNMT48LC4M32B2B5_6A_RAS_RAS___Pin GPIO_PIN_11 +#define SDNMT48LC4M32B2B5_6A_RAS_RAS___GPIO_Port GPIOF +#define D6_Pin GPIO_PIN_9 +#define D6_GPIO_Port GPIOE +#define D8_Pin GPIO_PIN_11 +#define D8_GPIO_Port GPIOE +#define D11_Pin GPIO_PIN_14 +#define D11_GPIO_Port GPIOE +#define STLK_RX_Pin GPIO_PIN_10 +#define STLK_RX_GPIO_Port GPIOB +#define D16_Pin GPIO_PIN_8 +#define D16_GPIO_Port GPIOH +#define D18_Pin GPIO_PIN_10 +#define D18_GPIO_Port GPIOH +#define LCD_BL_CTRL_Pin GPIO_PIN_3 +#define LCD_BL_CTRL_GPIO_Port GPIOA +#define EXT_RESET_Pin GPIO_PIN_0 +#define EXT_RESET_GPIO_Port GPIOB +#define D4_Pin GPIO_PIN_7 +#define D4_GPIO_Port GPIOE +#define D7_Pin GPIO_PIN_10 +#define D7_GPIO_Port GPIOE +#define D9_Pin GPIO_PIN_12 +#define D9_GPIO_Port GPIOE +#define D12_Pin GPIO_PIN_15 +#define D12_GPIO_Port GPIOE +#define D10_Pin GPIO_PIN_13 +#define D10_GPIO_Port GPIOE +#define STLK_TX_Pin GPIO_PIN_11 +#define STLK_TX_GPIO_Port GPIOB +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MAIN_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbhost/Core/Inc/usbh_platform.h b/ports/stm32/usbhost/Core/Inc/usbh_platform.h new file mode 100644 index 000000000000..f6a920370732 --- /dev/null +++ b/ports/stm32/usbhost/Core/Inc/usbh_platform.h @@ -0,0 +1,44 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : usbh_platform.h + * @brief : Header for usbh_platform.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBH_PLATFORM_H__ +#define __USBH_PLATFORM_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usb_host.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +void MX_DriverVbusFS(uint8_t state); + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_PLATFORM_H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbhost/Core/Src/usbh_conf.c b/ports/stm32/usbhost/Core/Src/usbh_conf.c new file mode 100644 index 000000000000..871495a1e497 --- /dev/null +++ b/ports/stm32/usbhost/Core/Src/usbh_conf.c @@ -0,0 +1,553 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : Target/usbh_conf.c + * @version : v1.0_Cube + * @brief : This file implements the board support package for the USB host library + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_core.h" +#include "usbh_platform.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +HCD_HandleTypeDef hhcd_USB_OTG_FS; + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* USER CODE BEGIN PFP */ +/* Private function prototypes -----------------------------------------------*/ +USBH_StatusTypeDef USBH_Get_USB_Status(HAL_StatusTypeDef hal_status); + +/* USER CODE END PFP */ + +/* Private functions ---------------------------------------------------------*/ + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ +void Error_Handler(void) +{ + return; +} +/******************************************************************************* + LL Driver Callbacks (HCD -> USB Host Library) +*******************************************************************************/ +/* MSP Init */ + +void HAL_HCD_MspInit(HCD_HandleTypeDef* hcdHandle) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(hcdHandle->Instance==USB_OTG_FS) + { + /* USER CODE BEGIN USB_OTG_FS_MspInit 0 */ + + /* USER CODE END USB_OTG_FS_MspInit 0 */ + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**USB_OTG_FS GPIO Configuration + PA12 ------> USB_OTG_FS_DP + PA11 ------> USB_OTG_FS_DM + PA10 ------> USB_OTG_FS_ID + PA9 ------> USB_OTG_FS_VBUS + */ + GPIO_InitStruct.Pin = USB_FS1_P_Pin|USB_FS1_N_Pin|USB_FS1_ID_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = VBUS_FS1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(VBUS_FS1_GPIO_Port, &GPIO_InitStruct); + + /* Peripheral clock enable */ + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + + /* Peripheral interrupt init */ + HAL_NVIC_SetPriority(OTG_FS_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(OTG_FS_IRQn); + /* USER CODE BEGIN USB_OTG_FS_MspInit 1 */ + + /* USER CODE END USB_OTG_FS_MspInit 1 */ + } +} + +void HAL_HCD_MspDeInit(HCD_HandleTypeDef* hcdHandle) +{ + if(hcdHandle->Instance==USB_OTG_FS) + { + /* USER CODE BEGIN USB_OTG_FS_MspDeInit 0 */ + + /* USER CODE END USB_OTG_FS_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); + + /**USB_OTG_FS GPIO Configuration + PA12 ------> USB_OTG_FS_DP + PA11 ------> USB_OTG_FS_DM + PA10 ------> USB_OTG_FS_ID + PA9 ------> USB_OTG_FS_VBUS + */ + HAL_GPIO_DeInit(GPIOA, USB_FS1_P_Pin|USB_FS1_N_Pin|USB_FS1_ID_Pin|VBUS_FS1_Pin); + + /* Peripheral interrupt Deinit*/ + HAL_NVIC_DisableIRQ(OTG_FS_IRQn); + + /* USER CODE BEGIN USB_OTG_FS_MspDeInit 1 */ + + /* USER CODE END USB_OTG_FS_MspDeInit 1 */ + } +} + +/** + * @brief SOF callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_IncTimer(hhcd->pData); +} + +/** + * @brief SOF callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_Connect(hhcd->pData); +} + +/** + * @brief SOF callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_Disconnect(hhcd->pData); +} + +/** + * @brief Notify URB state change callback. + * @param hhcd: HCD handle + * @param chnum: channel number + * @param urb_state: state + * @retval None + */ +void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state) +{ + /* To be used with OS to sync URB state with the global state machine */ +#if (USBH_USE_OS == 1) + USBH_LL_NotifyURBChange(hhcd->pData); +#endif +} +/** +* @brief Port Port Enabled callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_PortEnabled(hhcd->pData); +} + +/** + * @brief Port Port Disabled callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_PortDisabled(hhcd->pData); +} + +/******************************************************************************* + LL Driver Interface (USB Host Library --> HCD) +*******************************************************************************/ + +/** + * @brief Initialize the low level portion of the host driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_Init(USBH_HandleTypeDef *phost) +{ + /* Init USB_IP */ + if (phost->id == HOST_FS) { + /* Link the driver to the stack. */ + hhcd_USB_OTG_FS.pData = phost; + phost->pData = &hhcd_USB_OTG_FS; + + hhcd_USB_OTG_FS.Instance = USB_OTG_FS; + hhcd_USB_OTG_FS.Init.Host_channels = 8; + hhcd_USB_OTG_FS.Init.speed = HCD_SPEED_FULL; + hhcd_USB_OTG_FS.Init.dma_enable = DISABLE; + hhcd_USB_OTG_FS.Init.phy_itface = HCD_PHY_EMBEDDED; + hhcd_USB_OTG_FS.Init.Sof_enable = DISABLE; + if (HAL_HCD_Init(&hhcd_USB_OTG_FS) != HAL_OK) + { + //Error_Handler( ); //ololo + return USBH_FAIL; + } + + USBH_LL_SetTimer(phost, HAL_HCD_GetCurrentFrame(&hhcd_USB_OTG_FS)); + } + return USBH_OK; +} + +/** + * @brief De-Initialize the low level portion of the host driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_DeInit(USBH_HandleTypeDef *phost) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_DeInit(phost->pData); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Start the low level portion of the host driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_Start(USBH_HandleTypeDef *phost) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_Start(phost->pData); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Stop the low level portion of the host driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_Stop(USBH_HandleTypeDef *phost) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_Stop(phost->pData); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Return the USB host speed from the low level driver. + * @param phost: Host handle + * @retval USBH speeds + */ +USBH_SpeedTypeDef USBH_LL_GetSpeed(USBH_HandleTypeDef *phost) +{ + USBH_SpeedTypeDef speed = USBH_SPEED_FULL; + + switch (HAL_HCD_GetCurrentSpeed(phost->pData)) + { + case 0 : + speed = USBH_SPEED_HIGH; + break; + + case 1 : + speed = USBH_SPEED_FULL; + break; + + case 2 : + speed = USBH_SPEED_LOW; + break; + + default: + speed = USBH_SPEED_FULL; + break; + } + return speed; +} + +/** + * @brief Reset the Host port of the low level driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_ResetPort(USBH_HandleTypeDef *phost) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_ResetPort(phost->pData); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Return the last transfered packet size. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval Packet size + */ +uint32_t USBH_LL_GetLastXferSize(USBH_HandleTypeDef *phost, uint8_t pipe) +{ + return HAL_HCD_HC_GetXferCount(phost->pData, pipe); +} + +/** + * @brief Open a pipe of the low level driver. + * @param phost: Host handle + * @param pipe_num: Pipe index + * @param epnum: Endpoint number + * @param dev_address: Device USB address + * @param speed: Device Speed + * @param ep_type: Endpoint type + * @param mps: Endpoint max packet size + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_OpenPipe(USBH_HandleTypeDef *phost, uint8_t pipe_num, uint8_t epnum, + uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_HC_Init(phost->pData, pipe_num, epnum, + dev_address, speed, ep_type, mps); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Close a pipe of the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_ClosePipe(USBH_HandleTypeDef *phost, uint8_t pipe) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_HC_Halt(phost->pData, pipe); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Submit a new URB to the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * This parameter can be a value from 1 to 15 + * @param direction : Channel number + * This parameter can be one of the these values: + * 0 : Output + * 1 : Input + * @param ep_type : Endpoint Type + * This parameter can be one of the these values: + * @arg EP_TYPE_CTRL: Control type + * @arg EP_TYPE_ISOC: Isochrounous type + * @arg EP_TYPE_BULK: Bulk type + * @arg EP_TYPE_INTR: Interrupt type + * @param token : Endpoint Type + * This parameter can be one of the these values: + * @arg 0: PID_SETUP + * @arg 1: PID_DATA + * @param pbuff : pointer to URB data + * @param length : Length of URB data + * @param do_ping : activate do ping protocol (for high speed only) + * This parameter can be one of the these values: + * 0 : do ping inactive + * 1 : do ping active + * @retval Status + */ +USBH_StatusTypeDef USBH_LL_SubmitURB(USBH_HandleTypeDef *phost, uint8_t pipe, uint8_t direction, + uint8_t ep_type, uint8_t token, uint8_t *pbuff, uint16_t length, + uint8_t do_ping) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_HC_SubmitRequest(phost->pData, pipe, direction , + ep_type, token, pbuff, length, + do_ping); + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Get a URB state from the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * This parameter can be a value from 1 to 15 + * @retval URB state + * This parameter can be one of the these values: + * @arg URB_IDLE + * @arg URB_DONE + * @arg URB_NOTREADY + * @arg URB_NYET + * @arg URB_ERROR + * @arg URB_STALL + */ +USBH_URBStateTypeDef USBH_LL_GetURBState(USBH_HandleTypeDef *phost, uint8_t pipe) +{ + return (USBH_URBStateTypeDef)HAL_HCD_HC_GetURBState (phost->pData, pipe); +} + +/** + * @brief Drive VBUS. + * @param phost: Host handle + * @param state : VBUS state + * This parameter can be one of the these values: + * 0 : VBUS Inactive + * 1 : VBUS Active + * @retval Status + */ +USBH_StatusTypeDef USBH_LL_DriverVBUS(USBH_HandleTypeDef *phost, uint8_t state) +{ + if (phost->id == HOST_FS) { + MX_DriverVbusFS(state); + } + + /* USER CODE BEGIN 0 */ + + /* USER CODE END 0*/ + + HAL_Delay(200); + return USBH_OK; +} + +/** + * @brief Set toggle for a pipe. + * @param phost: Host handle + * @param pipe: Pipe index + * @param toggle: toggle (0/1) + * @retval Status + */ +USBH_StatusTypeDef USBH_LL_SetToggle(USBH_HandleTypeDef *phost, uint8_t pipe, uint8_t toggle) +{ + HCD_HandleTypeDef *pHandle; + pHandle = phost->pData; + + if(pHandle->hc[pipe].ep_is_in) + { + pHandle->hc[pipe].toggle_in = toggle; + } + else + { + pHandle->hc[pipe].toggle_out = toggle; + } + + return USBH_OK; +} + +/** + * @brief Return the current toggle of a pipe. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval toggle (0/1) + */ +uint8_t USBH_LL_GetToggle(USBH_HandleTypeDef *phost, uint8_t pipe) +{ + uint8_t toggle = 0; + HCD_HandleTypeDef *pHandle; + pHandle = phost->pData; + + if(pHandle->hc[pipe].ep_is_in) + { + toggle = pHandle->hc[pipe].toggle_in; + } + else + { + toggle = pHandle->hc[pipe].toggle_out; + } + return toggle; +} + +/** + * @brief Delay routine for the USB Host Library + * @param Delay: Delay in ms + * @retval None + */ +void USBH_Delay(uint32_t Delay) +{ + HAL_Delay(Delay); +} + +/** + * @brief Retuns the USB status depending on the HAL status: + * @param hal_status: HAL status + * @retval USB status + */ +USBH_StatusTypeDef USBH_Get_USB_Status(HAL_StatusTypeDef hal_status) +{ + USBH_StatusTypeDef usb_status = USBH_OK; + + switch (hal_status) + { + case HAL_OK : + usb_status = USBH_OK; + break; + case HAL_ERROR : + usb_status = USBH_FAIL; + break; + case HAL_BUSY : + usb_status = USBH_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBH_FAIL; + break; + default : + usb_status = USBH_FAIL; + break; + } + return usb_status; +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbhost/Core/Src/usbh_core.c b/ports/stm32/usbhost/Core/Src/usbh_core.c index 9d2727a89f92..96484f9d2183 100644 --- a/ports/stm32/usbhost/Core/Src/usbh_core.c +++ b/ports/stm32/usbhost/Core/Src/usbh_core.c @@ -806,6 +806,39 @@ void USBH_LL_IncTimer (USBH_HandleTypeDef *phost) USBH_HandleSof(phost); } +/** + * @brief USBH_PortEnabled + * Port Enabled + * @param phost: Host Handle + * @retval None + */ +void USBH_LL_PortEnabled(USBH_HandleTypeDef *phost) +{ + phost->device.PortEnabled = 1U; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_PORT_EVENT; +#if (osCMSIS < 0x20000U) + (void)osMessagePut(phost->os_event, phost->os_msg, 0U); +#else + (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL); +#endif +#endif + + return; +} +/** + * @brief USBH_LL_PortDisabled + * Port Disabled + * @param phost: Host Handle + * @retval None + */ +void USBH_LL_PortDisabled(USBH_HandleTypeDef *phost) +{ + phost->device.PortEnabled = 0U; + + return; +} /** * @brief USBH_HandleSof * Call SOF process From 8379e30f6a75ae0a055b95f1d13fb7ce61c8b12c Mon Sep 17 00:00:00 2001 From: hemi454 Date: Sun, 30 May 2021 17:50:35 +0300 Subject: [PATCH 02/13] Add usb host support --- ports/stm32/Makefile | 19 +- .../boards/STM32F469DISC/mpconfigboard.h | 2 +- ports/stm32/main.c | 3 +- ports/stm32/mphalport.c | 7 +- ports/stm32/usb.c | 31 +- ports/stm32/usb.h | 1 - ports/stm32/usb_host.c | 128 +++ .../stm32/usbdev/class/inc/usbd_cdc_msc_hid.h | 6 +- .../stm32/usbdev/class/src/usbd_cdc_msc_hid.c | 10 +- ports/stm32/usbh_conf.c | 551 +++++++++++ ports/stm32/usbh_conf_template.c | 270 +++++ ports/stm32/usbh_core.c | 936 ++++++++++++++++++ ports/stm32/usbh_ctlreq.c | 881 +++++++++++++++++ ports/stm32/usbh_hid.c | 799 +++++++++++++++ ports/stm32/usbh_hid_keybd.c | 418 ++++++++ ports/stm32/usbh_hid_mouse.c | 267 +++++ ports/stm32/usbh_hid_parser.c | 235 +++++ ports/stm32/usbh_ioreq.c | 358 +++++++ ports/stm32/usbh_pipes.c | 204 ++++ ports/stm32/usbh_platform.c | 54 + ports/stm32/usbhost/Class/HID/Inc/usbh_hid.h | 20 +- ports/stm32/usbhost/Class/HID/Src/usbh_hid.c | 18 +- ports/stm32/usbhost/Core/Inc/usb_host.h | 95 ++ ports/stm32/usbhost/Core/Inc/usbh_conf.h | 195 ++++ ports/stm32/usbhost/Core/Inc/usbh_core.h | 2 + ports/stm32/usbhost/Core/Inc/usbh_def.h | 1 + ports/stm32/usbhost/Core/Inc/usbh_main.h | 271 +++++ ports/stm32/usbhost/Core/Inc/usbh_platform.h | 44 + ports/stm32/usbhost/Core/Src/usbh_conf.c | 553 +++++++++++ ports/stm32/usbhost/Core/Src/usbh_core.c | 33 + 30 files changed, 6362 insertions(+), 50 deletions(-) create mode 100644 ports/stm32/usb_host.c create mode 100644 ports/stm32/usbh_conf.c create mode 100644 ports/stm32/usbh_conf_template.c create mode 100644 ports/stm32/usbh_core.c create mode 100644 ports/stm32/usbh_ctlreq.c create mode 100644 ports/stm32/usbh_hid.c create mode 100644 ports/stm32/usbh_hid_keybd.c create mode 100644 ports/stm32/usbh_hid_mouse.c create mode 100644 ports/stm32/usbh_hid_parser.c create mode 100644 ports/stm32/usbh_ioreq.c create mode 100644 ports/stm32/usbh_pipes.c create mode 100644 ports/stm32/usbh_platform.c create mode 100644 ports/stm32/usbhost/Core/Inc/usb_host.h create mode 100644 ports/stm32/usbhost/Core/Inc/usbh_conf.h create mode 100644 ports/stm32/usbhost/Core/Inc/usbh_main.h create mode 100644 ports/stm32/usbhost/Core/Inc/usbh_platform.h create mode 100644 ports/stm32/usbhost/Core/Src/usbh_conf.c diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index d7f6e3e71ee5..37c60e66c6dd 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -36,7 +36,7 @@ LD_DIR=boards CMSIS_DIR=$(TOP)/lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Include HAL_DIR=lib/stm32lib/STM32$(MCU_SERIES_UPPER)xx_HAL_Driver USBDEV_DIR=usbdev -#USBHOST_DIR=usbhost +USBHOST_DIR=usbhost DFU=$(TOP)/tools/dfu.py # may need to prefix dfu-util with sudo USE_PYDFU ?= 1 @@ -48,7 +48,6 @@ OPENOCD ?= openocd OPENOCD_CONFIG ?= boards/openocd_stm32f4.cfg STARTUP_FILE ?= lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Source/Templates/gcc/startup_$(CMSIS_MCU_LOWER).o SYSTEM_FILE ?= lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Source/Templates/system_stm32$(MCU_SERIES)xx.o - # Select the cross compile prefix CROSS_COMPILE ?= arm-none-eabi- @@ -59,7 +58,7 @@ INC += -I$(TOP)/lib/cmsis/inc INC += -I$(CMSIS_DIR)/ INC += -I$(TOP)/$(HAL_DIR)/Inc INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/inc -#INC += -I$(USBHOST_DIR) +INC += -I$(USBHOST_DIR)/Core/Inc -I$(USBHOST_DIR)/Class/HID/Inc INC += -Ilwip_inc # Basic Cortex-M flags @@ -101,7 +100,7 @@ ifeq ($(SKIP_USBINIT),1) CFLAGS += -DSKIP_USBINIT=$(SKIP_USBINIT) endif CFLAGS += -DMICROPY_HW_SDCARD_MOUNT_AT_BOOT=$(MICROPY_HW_SDCARD_MOUNT_AT_BOOT) - +CFLAGS += -lcrt -lc # Configure for nan-boxing object model if requested ifeq ($(NANBOX),1) CFLAGS += -DMP_CONFIGFILE='"mpconfigport_nanbox.h"' @@ -257,6 +256,17 @@ SRC_C = \ usbd_cdc_interface.c \ usbd_hid_interface.c \ usbd_msc_interface.c \ + usbh_conf.c \ + usbh_core.c \ + usbh_hid.c \ + usbh_hid_keybd.c \ + usbh_hid_mouse.c \ + usbh_hid_parser.c \ + usb_host.c \ + usbh_platform.c \ + usbh_pipes.c \ + usbh_ctlreq.c\ + usbh_ioreq.c \ mphalport.c \ mpthreadport.c \ irq.c \ @@ -364,6 +374,7 @@ SRC_HAL = $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ hal_tim.c \ hal_tim_ex.c \ hal_uart.c \ + hal_hcd.c \ ) ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7 l0 l4 wb)) diff --git a/ports/stm32/boards/STM32F469DISC/mpconfigboard.h b/ports/stm32/boards/STM32F469DISC/mpconfigboard.h index d9424e9b5fda..fb939d63e4be 100644 --- a/ports/stm32/boards/STM32F469DISC/mpconfigboard.h +++ b/ports/stm32/boards/STM32F469DISC/mpconfigboard.h @@ -139,4 +139,4 @@ extern struct _spi_bdev_t spi_bdev; #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) - +#define USE_HOST_MODE (1) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index aa245da8db4d..709d53036829 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -770,7 +770,7 @@ void stm32_main(uint32_t reset_mode) { // Now we initialise sub-systems that need configuration from boot.py, // or whose initialisation can be safely deferred until after running // boot.py. - + #ifndef USE_HOST_MODE #ifndef SKIP_USBINIT #if MICROPY_HW_ENABLE_USB // init USB device to default setting if it was not already configured @@ -786,6 +786,7 @@ void stm32_main(uint32_t reset_mode) { } #endif #endif + #endif #if MICROPY_HW_HAS_MMA7660 // MMA accel: init and reset diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index c8d83be0a140..d89e1e587b26 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -33,15 +33,16 @@ MP_WEAK uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { MP_WEAK int mp_hal_stdin_rx_chr(void) { for (;;) { -#if 0 #ifdef USE_HOST_MODE pyb_usb_host_process(); +/* int c = pyb_usb_host_get_keyboard(); if (c != 0) { return c; } +*/ #endif -#endif +/* if (MP_STATE_PORT(pyb_stdio_uart) != NULL && uart_rx_any(MP_STATE_PORT(pyb_stdio_uart))) { return uart_rx_char(MP_STATE_PORT(pyb_stdio_uart)); } @@ -50,7 +51,9 @@ MP_WEAK int mp_hal_stdin_rx_chr(void) { return dupterm_c; } MICROPY_EVENT_POLL_HOOK +*/ } + } void mp_hal_stdout_tx_str(const char *str) { diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 8a4b7485bb79..c50d913c78f2 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -26,14 +26,12 @@ #include #include - #include "usbd_core.h" #include "usbd_desc.h" #include "usbd_cdc_msc_hid.h" #include "usbd_cdc_interface.h" #include "usbd_msc_interface.h" #include "usbd_hid_interface.h" - #include "py/objstr.h" #include "py/runtime.h" #include "py/stream.h" @@ -440,15 +438,14 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * const char *mode_str = mp_obj_str_get_str(args[ARG_mode].u_obj); #if defined(USE_HOST_MODE) - + //pyb_usb_host_init(); // hardware configured for USB host mode - + if (strcmp(mode_str, "host") == 0) { pyb_usb_host_init(); } else { goto bad_mode; } - #else // hardware configured for USB device mode @@ -1007,28 +1004,34 @@ const mp_obj_type_t pyb_usb_hid_type = { #include "led.h" #include "usbh_core.h" -#include "usbh_usr.h" -#include "usbh_hid_core.h" +//#include "usbh_usr.h" +//#include "usbh_hid_core.h" #include "usbh_hid_keybd.h" #include "usbh_hid_mouse.h" - -__ALIGN_BEGIN USBH_HOST USB_Host __ALIGN_END ; - +#include "usbh_hid.h" +#include "usb_host.h" +//__ALIGN_BEGIN USBH_HOST USB_Host __ALIGN_END ; +/* USB Host core handle declaration */ +USBH_HandleTypeDef hUsbHostFS; +//ApplicationTypeDef Appli_state = APPLICATION_IDLE; static int host_is_enabled = 0; void pyb_usb_host_init(void) { if (!host_is_enabled) { // only init USBH once in the device's power-lifetime /* Init Host Library */ - USBH_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USB_Host, &HID_cb, &USR_Callbacks); + //USBH_Init(&hUsbHostFS, USB_OTG_FS_CORE_ID, &USB_Host, &HID_cb, &USR_Callbacks); + USBH_Init(&hUsbHostFS, USBH_UserProcess, HOST_FS); + USBH_RegisterClass(&hUsbHostFS, USBH_HID_CLASS); + USBH_Start(&hUsbHostFS); } host_is_enabled = 1; } void pyb_usb_host_process(void) { - USBH_Process(&USB_OTG_Core, &USB_Host); + USBH_Process(&hUsbHostFS); } - +/* uint8_t usb_keyboard_key = 0; // TODO this is an ugly hack to get key presses @@ -1062,7 +1065,7 @@ void USR_KEYBRD_ProcessData(uint8_t pbuf) { led_state(4, 0); usb_keyboard_key = pbuf; } - +*/ #endif // USE_HOST_MODE #endif // MICROPY_HW_ENABLE_USB diff --git a/ports/stm32/usb.h b/ports/stm32/usb.h index 457c7313c4d5..93b7a1271d88 100644 --- a/ports/stm32/usb.h +++ b/ports/stm32/usb.h @@ -27,7 +27,6 @@ #define MICROPY_INCLUDED_STM32_USB_H #include "usbd_cdc_msc_hid0.h" - #define PYB_USB_FLAG_USB_MODE_CALLED (0x0002) // Windows needs a different PID to distinguish different device configurations diff --git a/ports/stm32/usb_host.c b/ports/stm32/usb_host.c new file mode 100644 index 000000000000..db59bd63bb83 --- /dev/null +++ b/ports/stm32/usb_host.c @@ -0,0 +1,128 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : usb_host.c + * @version : v1.0_Cube + * @brief : This file implements the USB Host + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ + +#include "usb_host.h" +#include "usbh_core.h" +#include "usbh_hid.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +/* USER CODE BEGIN PFP */ +/* Private function prototypes -----------------------------------------------*/ + +/* USER CODE END PFP */ + +/* USB Host core handle declaration */ +USBH_HandleTypeDef hUsbHostFS; +ApplicationTypeDef Appli_state = APPLICATION_IDLE; + +/* + * -- Insert your variables declaration here -- + */ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* + * -- Insert your external function declaration here -- + */ +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/** + * Init USB host library, add supported class and start the library + * @retval None + */ +void MX_USB_HOST_Init(void) +{ + /* USER CODE BEGIN USB_HOST_Init_PreTreatment */ + + /* USER CODE END USB_HOST_Init_PreTreatment */ + + /* Init host Library, add supported class and start the library. */ + if (USBH_Init(&hUsbHostFS, USBH_UserProcess, HOST_FS) != USBH_OK) + { + //Error_Handler(); + return; + } + if (USBH_RegisterClass(&hUsbHostFS, USBH_HID_CLASS) != USBH_OK) + { + //Error_Handler(); + return; + } + if (USBH_Start(&hUsbHostFS) != USBH_OK) + { + //Error_Handler(); + return; + } + /* USER CODE BEGIN USB_HOST_Init_PostTreatment */ + + /* USER CODE END USB_HOST_Init_PostTreatment */ +} + +/* + * user callback definition + */ +void USBH_UserProcess (USBH_HandleTypeDef *phost, uint8_t id) +{ + /* USER CODE BEGIN CALL_BACK_1 */ + switch(id) + { + case HOST_USER_SELECT_CONFIGURATION: + break; + + case HOST_USER_DISCONNECTION: + Appli_state = APPLICATION_DISCONNECT; + break; + + case HOST_USER_CLASS_ACTIVE: + Appli_state = APPLICATION_READY; + break; + + case HOST_USER_CONNECTION: + Appli_state = APPLICATION_START; + break; + + default: + break; + } + /* USER CODE END CALL_BACK_1 */ +} + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h index d934f4676c4d..1d1ee89a8373 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h @@ -89,9 +89,9 @@ typedef struct { } USBD_MSC_BOT_HandleTypeDef; typedef enum { - HID_IDLE = 0, - HID_BUSY, -} HID_StateTypeDef; + HID_IDLE_DEV = 0, + HID_BUSY_DEV, +} HID_Device_StateTypeDef; typedef struct { struct _usbd_cdc_msc_hid_state_t *usbd; // The parent USB device diff --git a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c index 5e24730a0fac..3978c254a30a 100644 --- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c +++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c @@ -754,7 +754,7 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { // Prepare Out endpoint to receive next packet USBD_LL_PrepareReceive(pdev, usbd->hid->out_ep, buf, mps_out); - usbd->hid->state = HID_IDLE; + usbd->hid->state = HID_IDLE_DEV; } #endif @@ -1061,7 +1061,7 @@ static uint8_t USBD_CDC_MSC_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) if ((usbd->usbd_mode & USBD_MODE_IFACE_HID) && epnum == (usbd->hid->in_ep & 0x7f)) { /* 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->hid->state = HID_IDLE; + usbd->hid->state = HID_IDLE_DEV; return USBD_OK; } #endif @@ -1257,13 +1257,13 @@ uint8_t USBD_HID_ReceivePacket(usbd_hid_state_t *hid, uint8_t *buf) { } int USBD_HID_CanSendReport(usbd_hid_state_t *hid) { - return hid->usbd->pdev->dev_state == USBD_STATE_CONFIGURED && hid->state == HID_IDLE; + return hid->usbd->pdev->dev_state == USBD_STATE_CONFIGURED && hid->state == HID_IDLE_DEV; } uint8_t USBD_HID_SendReport(usbd_hid_state_t *hid, uint8_t *report, uint16_t len) { if (hid->usbd->pdev->dev_state == USBD_STATE_CONFIGURED) { - if (hid->state == HID_IDLE) { - hid->state = HID_BUSY; + if (hid->state == HID_IDLE_DEV) { + hid->state = HID_BUSY_DEV; USBD_LL_Transmit(hid->usbd->pdev, hid->in_ep, report, len); return USBD_OK; } diff --git a/ports/stm32/usbh_conf.c b/ports/stm32/usbh_conf.c new file mode 100644 index 000000000000..8a761f946839 --- /dev/null +++ b/ports/stm32/usbh_conf.c @@ -0,0 +1,551 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : Target/usbh_conf.c + * @version : v1.0_Cube + * @brief : This file implements the board support package for the USB host library + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_core.h" +#include "usbh_platform.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +HCD_HandleTypeDef hhcd_USB_OTG_FS; +void Error_Handler(void); + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* USER CODE BEGIN PFP */ +/* Private function prototypes -----------------------------------------------*/ +USBH_StatusTypeDef USBH_Get_USB_Status(HAL_StatusTypeDef hal_status); + +/* USER CODE END PFP */ + +/* Private functions ---------------------------------------------------------*/ + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/******************************************************************************* + LL Driver Callbacks (HCD -> USB Host Library) +*******************************************************************************/ +/* MSP Init */ + +void HAL_HCD_MspInit(HCD_HandleTypeDef* hcdHandle) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(hcdHandle->Instance==USB_OTG_FS) + { + /* USER CODE BEGIN USB_OTG_FS_MspInit 0 */ + + /* USER CODE END USB_OTG_FS_MspInit 0 */ + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**USB_OTG_FS GPIO Configuration + PA12 ------> USB_OTG_FS_DP + PA11 ------> USB_OTG_FS_DM + PA10 ------> USB_OTG_FS_ID + PA9 ------> USB_OTG_FS_VBUS + */ + GPIO_InitStruct.Pin = USB_FS1_P_Pin|USB_FS1_N_Pin|USB_FS1_ID_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = VBUS_FS1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(VBUS_FS1_GPIO_Port, &GPIO_InitStruct); + + /* Peripheral clock enable */ + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + + /* Peripheral interrupt init */ + HAL_NVIC_SetPriority(OTG_FS_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(OTG_FS_IRQn); + /* USER CODE BEGIN USB_OTG_FS_MspInit 1 */ + + /* USER CODE END USB_OTG_FS_MspInit 1 */ + } +} + +void HAL_HCD_MspDeInit(HCD_HandleTypeDef* hcdHandle) +{ + if(hcdHandle->Instance==USB_OTG_FS) + { + /* USER CODE BEGIN USB_OTG_FS_MspDeInit 0 */ + + /* USER CODE END USB_OTG_FS_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); + + /**USB_OTG_FS GPIO Configuration + PA12 ------> USB_OTG_FS_DP + PA11 ------> USB_OTG_FS_DM + PA10 ------> USB_OTG_FS_ID + PA9 ------> USB_OTG_FS_VBUS + */ + HAL_GPIO_DeInit(GPIOA, USB_FS1_P_Pin|USB_FS1_N_Pin|USB_FS1_ID_Pin|VBUS_FS1_Pin); + + /* Peripheral interrupt Deinit*/ + HAL_NVIC_DisableIRQ(OTG_FS_IRQn); + + /* USER CODE BEGIN USB_OTG_FS_MspDeInit 1 */ + + /* USER CODE END USB_OTG_FS_MspDeInit 1 */ + } +} + +/** + * @brief SOF callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_IncTimer(hhcd->pData); +} + +/** + * @brief SOF callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_Connect(hhcd->pData); +} + +/** + * @brief SOF callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_Disconnect(hhcd->pData); +} + +/** + * @brief Notify URB state change callback. + * @param hhcd: HCD handle + * @param chnum: channel number + * @param urb_state: state + * @retval None + */ +void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state) +{ + /* To be used with OS to sync URB state with the global state machine */ +#if (USBH_USE_OS == 1) + USBH_LL_NotifyURBChange(hhcd->pData); +#endif +} +/** +* @brief Port Port Enabled callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_PortEnabled(hhcd->pData); +} + +/** + * @brief Port Port Disabled callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_PortDisabled(hhcd->pData); +} + +/******************************************************************************* + LL Driver Interface (USB Host Library --> HCD) +*******************************************************************************/ + +/** + * @brief Initialize the low level portion of the host driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_Init(USBH_HandleTypeDef *phost) +{ + /* Init USB_IP */ + if (phost->id == HOST_FS) { + /* Link the driver to the stack. */ + hhcd_USB_OTG_FS.pData = phost; + phost->pData = &hhcd_USB_OTG_FS; + + hhcd_USB_OTG_FS.Instance = USB_OTG_FS; + hhcd_USB_OTG_FS.Init.Host_channels = 8; + hhcd_USB_OTG_FS.Init.speed = HCD_SPEED_FULL; + hhcd_USB_OTG_FS.Init.dma_enable = DISABLE; + hhcd_USB_OTG_FS.Init.phy_itface = HCD_PHY_EMBEDDED; + hhcd_USB_OTG_FS.Init.Sof_enable = DISABLE; + if (HAL_HCD_Init(&hhcd_USB_OTG_FS) != HAL_OK) + { + //Error_Handler( ); + return USBH_FAIL; + } + + USBH_LL_SetTimer(phost, HAL_HCD_GetCurrentFrame(&hhcd_USB_OTG_FS)); + } + return USBH_OK; +} + +/** + * @brief De-Initialize the low level portion of the host driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_DeInit(USBH_HandleTypeDef *phost) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_DeInit(phost->pData); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Start the low level portion of the host driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_Start(USBH_HandleTypeDef *phost) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_Start(phost->pData); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Stop the low level portion of the host driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_Stop(USBH_HandleTypeDef *phost) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_Stop(phost->pData); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Return the USB host speed from the low level driver. + * @param phost: Host handle + * @retval USBH speeds + */ +USBH_SpeedTypeDef USBH_LL_GetSpeed(USBH_HandleTypeDef *phost) +{ + USBH_SpeedTypeDef speed = USBH_SPEED_FULL; + + switch (HAL_HCD_GetCurrentSpeed(phost->pData)) + { + case 0 : + speed = USBH_SPEED_HIGH; + break; + + case 1 : + speed = USBH_SPEED_FULL; + break; + + case 2 : + speed = USBH_SPEED_LOW; + break; + + default: + speed = USBH_SPEED_FULL; + break; + } + return speed; +} + +/** + * @brief Reset the Host port of the low level driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_ResetPort(USBH_HandleTypeDef *phost) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_ResetPort(phost->pData); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Return the last transfered packet size. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval Packet size + */ +uint32_t USBH_LL_GetLastXferSize(USBH_HandleTypeDef *phost, uint8_t pipe) +{ + return HAL_HCD_HC_GetXferCount(phost->pData, pipe); +} + +/** + * @brief Open a pipe of the low level driver. + * @param phost: Host handle + * @param pipe_num: Pipe index + * @param epnum: Endpoint number + * @param dev_address: Device USB address + * @param speed: Device Speed + * @param ep_type: Endpoint type + * @param mps: Endpoint max packet size + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_OpenPipe(USBH_HandleTypeDef *phost, uint8_t pipe_num, uint8_t epnum, + uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_HC_Init(phost->pData, pipe_num, epnum, + dev_address, speed, ep_type, mps); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Close a pipe of the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_ClosePipe(USBH_HandleTypeDef *phost, uint8_t pipe) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_HC_Halt(phost->pData, pipe); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Submit a new URB to the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * This parameter can be a value from 1 to 15 + * @param direction : Channel number + * This parameter can be one of the these values: + * 0 : Output + * 1 : Input + * @param ep_type : Endpoint Type + * This parameter can be one of the these values: + * @arg EP_TYPE_CTRL: Control type + * @arg EP_TYPE_ISOC: Isochrounous type + * @arg EP_TYPE_BULK: Bulk type + * @arg EP_TYPE_INTR: Interrupt type + * @param token : Endpoint Type + * This parameter can be one of the these values: + * @arg 0: PID_SETUP + * @arg 1: PID_DATA + * @param pbuff : pointer to URB data + * @param length : Length of URB data + * @param do_ping : activate do ping protocol (for high speed only) + * This parameter can be one of the these values: + * 0 : do ping inactive + * 1 : do ping active + * @retval Status + */ +USBH_StatusTypeDef USBH_LL_SubmitURB(USBH_HandleTypeDef *phost, uint8_t pipe, uint8_t direction, + uint8_t ep_type, uint8_t token, uint8_t *pbuff, uint16_t length, + uint8_t do_ping) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_HC_SubmitRequest(phost->pData, pipe, direction , + ep_type, token, pbuff, length, + do_ping); + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Get a URB state from the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * This parameter can be a value from 1 to 15 + * @retval URB state + * This parameter can be one of the these values: + * @arg URB_IDLE + * @arg URB_DONE + * @arg URB_NOTREADY + * @arg URB_NYET + * @arg URB_ERROR + * @arg URB_STALL + */ +USBH_URBStateTypeDef USBH_LL_GetURBState(USBH_HandleTypeDef *phost, uint8_t pipe) +{ + return (USBH_URBStateTypeDef)HAL_HCD_HC_GetURBState (phost->pData, pipe); +} + +/** + * @brief Drive VBUS. + * @param phost: Host handle + * @param state : VBUS state + * This parameter can be one of the these values: + * 0 : VBUS Inactive + * 1 : VBUS Active + * @retval Status + */ +USBH_StatusTypeDef USBH_LL_DriverVBUS(USBH_HandleTypeDef *phost, uint8_t state) +{ + if (phost->id == HOST_FS) { + MX_DriverVbusFS(state); + } + + /* USER CODE BEGIN 0 */ + + /* USER CODE END 0*/ + + HAL_Delay(200); + return USBH_OK; +} + +/** + * @brief Set toggle for a pipe. + * @param phost: Host handle + * @param pipe: Pipe index + * @param toggle: toggle (0/1) + * @retval Status + */ +USBH_StatusTypeDef USBH_LL_SetToggle(USBH_HandleTypeDef *phost, uint8_t pipe, uint8_t toggle) +{ + HCD_HandleTypeDef *pHandle; + pHandle = phost->pData; + + if(pHandle->hc[pipe].ep_is_in) + { + pHandle->hc[pipe].toggle_in = toggle; + } + else + { + pHandle->hc[pipe].toggle_out = toggle; + } + + return USBH_OK; +} + +/** + * @brief Return the current toggle of a pipe. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval toggle (0/1) + */ +uint8_t USBH_LL_GetToggle(USBH_HandleTypeDef *phost, uint8_t pipe) +{ + uint8_t toggle = 0; + HCD_HandleTypeDef *pHandle; + pHandle = phost->pData; + + if(pHandle->hc[pipe].ep_is_in) + { + toggle = pHandle->hc[pipe].toggle_in; + } + else + { + toggle = pHandle->hc[pipe].toggle_out; + } + return toggle; +} + +/** + * @brief Delay routine for the USB Host Library + * @param Delay: Delay in ms + * @retval None + */ +void USBH_Delay(uint32_t Delay) +{ + HAL_Delay(Delay); +} + +/** + * @brief Retuns the USB status depending on the HAL status: + * @param hal_status: HAL status + * @retval USB status + */ +USBH_StatusTypeDef USBH_Get_USB_Status(HAL_StatusTypeDef hal_status) +{ + USBH_StatusTypeDef usb_status = USBH_OK; + + switch (hal_status) + { + case HAL_OK : + usb_status = USBH_OK; + break; + case HAL_ERROR : + usb_status = USBH_FAIL; + break; + case HAL_BUSY : + usb_status = USBH_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBH_FAIL; + break; + default : + usb_status = USBH_FAIL; + break; + } + return usb_status; +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbh_conf_template.c b/ports/stm32/usbh_conf_template.c new file mode 100644 index 000000000000..de689ec0a119 --- /dev/null +++ b/ports/stm32/usbh_conf_template.c @@ -0,0 +1,270 @@ +/** + ****************************************************************************** + * @file usb_bsp.c + * @author MCD Application Team + * @version V3.0.0 + * @date 18-February-2014 + * @brief This file implements the board support package for the USB host library + ****************************************************************************** + * @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 "usbh_core.h" + +/** + * @brief USBH_LL_Init + * Initialize the Low Level portion of the Host driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_Init (USBH_HandleTypeDef *phost) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_DeInit + * De-Initialize the Low Level portion of the Host driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_DeInit (USBH_HandleTypeDef *phost) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_Start + * Start the Low Level portion of the Host driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_Start(USBH_HandleTypeDef *phost) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_Stop + * Stop the Low Level portion of the Host driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_Stop (USBH_HandleTypeDef *phost) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_GetSpeed + * Return the USB Host Speed from the Low Level Driver. + * @param phost: Host handle + * @retval USBH Speeds + */ +USBH_SpeedTypeDef USBH_LL_GetSpeed (USBH_HandleTypeDef *phost) +{ + USBH_SpeedTypeDef speed = 0; + + + return speed; +} + +/** + * @brief USBH_LL_ResetPort + * Reset the Host Port of the Low Level Driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_ResetPort (USBH_HandleTypeDef *phost) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_GetLastXferSize + * Return the last transfered packet size. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval Packet Size + */ +uint32_t USBH_LL_GetLastXferSize (USBH_HandleTypeDef *phost, uint8_t pipe) +{ + +} + +/** + * @brief USBH_LL_OpenPipe + * Open a pipe of the Low Level Driver. + * @param phost: Host handle + * @param pipe_num: Pipe index + * @param epnum: Endpoint Number + * @param dev_address: Device USB address + * @param speed: Device Speed + * @param ep_type: Endpoint Type + * @param mps: Endpoint Max Packet Size + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_OpenPipe (USBH_HandleTypeDef *phost, + uint8_t pipe_num, + uint8_t epnum, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_ClosePipe + * Close a pipe of the Low Level Driver. + * @param phost: Host handle + * @param pipe_num: Pipe index + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_ClosePipe (USBH_HandleTypeDef *phost, uint8_t pipe) +{ + +} +/** + * @brief USBH_LL_SubmitURB + * Submit a new URB to the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * This parameter can be a value from 1 to 15 + * @param direction : Channel number + * This parameter can be one of the these values: + * 0 : Output + * 1 : Input + * @param ep_type : Endpoint Type + * This parameter can be one of the these values: + * @arg EP_TYPE_CTRL: Control type + * @arg EP_TYPE_ISOC: Isochrounous type + * @arg EP_TYPE_BULK: Bulk type + * @arg EP_TYPE_INTR: Interrupt type + * @param token : Endpoint Type + * This parameter can be one of the these values: + * @arg 0: PID_SETUP + * @arg 1: PID_DATA + * @param pbuff : pointer to URB data + * @param length : Length of URB data + * @param do_ping : activate do ping protocol (for high speed only) + * This parameter can be one of the these values: + * 0 : do ping inactive + * 1 : do ping active + * @retval Status + */ + +USBH_StatusTypeDef USBH_LL_SubmitURB (USBH_HandleTypeDef *phost, + uint8_t pipe, + uint8_t direction , + uint8_t ep_type, + uint8_t token, + uint8_t* pbuff, + uint16_t length, + uint8_t do_ping ) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_GetURBState + * Get a URB state from the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * This parameter can be a value from 1 to 15 + * @retval URB state + * This parameter can be one of the these values: + * @arg URB_IDLE + * @arg URB_DONE + * @arg URB_NOTREADY + * @arg URB_NYET + * @arg URB_ERROR + * @arg URB_STALL + */ +USBH_URBStateTypeDef USBH_LL_GetURBState (USBH_HandleTypeDef *phost, uint8_t pipe) +{ + +} + +/** + * @brief USBH_LL_DriverVBUS + * Drive VBUS. + * @param phost: Host handle + * @param state : VBUS state + * This parameter can be one of the these values: + * 0 : VBUS Active + * 1 : VBUS Inactive + * @retval Status + */ + +USBH_StatusTypeDef USBH_LL_DriverVBUS (USBH_HandleTypeDef *phost, uint8_t state) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_SetToggle + * Set toggle for a pipe. + * @param phost: Host handle + * @param pipe: Pipe index + * @param pipe_num: Pipe index + * @param toggle: toggle (0/1) + * @retval Status + */ +USBH_StatusTypeDef USBH_LL_SetToggle (USBH_HandleTypeDef *phost, uint8_t pipe, uint8_t toggle) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_GetToggle + * Return the current toggle of a pipe. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval toggle (0/1) + */ +uint8_t USBH_LL_GetToggle (USBH_HandleTypeDef *phost, uint8_t pipe) +{ + uint8_t toggle = 0; + + + return toggle; +} +/** + * @brief USBH_Delay + * Delay routine for the USB Host Library + * @param Delay: Delay in ms + * @retval None + */ +void USBH_Delay (uint32_t Delay) +{ + +} +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbh_core.c b/ports/stm32/usbh_core.c new file mode 100644 index 000000000000..a363f968fbed --- /dev/null +++ b/ports/stm32/usbh_core.c @@ -0,0 +1,936 @@ +/** + ****************************************************************************** + * @file usbh_core.c + * @author MCD Application Team + * @version V3.0.0 + * @date 18-February-2014 + * @brief This file implements the functions for the core state machine process + * the enumeration and the control transfer process + ****************************************************************************** + * @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 "usbh_core.h" + + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE + * @{ + */ + +/** @defgroup USBH_CORE + * @brief TThis file handles the basic enumaration when a device is connected + * to the host. + * @{ + */ + + +/** @defgroup USBH_CORE_Private_Defines + * @{ + */ +#define USBH_ADDRESS_DEFAULT 0 +#define USBH_ADDRESS_ASSIGNED 1 +#define USBH_MPS_DEFAULT 0x40 +/** + * @} + */ + +/** @defgroup USBH_CORE_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_CORE_Private_Variables + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_CORE_Private_Functions + * @{ + */ +static USBH_StatusTypeDef USBH_HandleEnum (USBH_HandleTypeDef *phost); +static void USBH_HandleSof (USBH_HandleTypeDef *phost); +static USBH_StatusTypeDef DeInitStateMachine(USBH_HandleTypeDef *phost); + +#if (USBH_USE_OS == 1) +static void USBH_Process_OS(void const * argument); +#endif + +/** + * @brief HCD_Init + * Initialize the HOST Core. + * @param phost: Host Handle + * @param pUsrFunc: User Callback + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Init(USBH_HandleTypeDef *phost, void (*pUsrFunc)(USBH_HandleTypeDef *phost, uint8_t ), uint8_t id) +{ + /* Check whether the USB Host handle is valid */ + if(phost == NULL) + { + USBH_ErrLog("Invalid Host handle"); + return USBH_FAIL; + } + + /* Set DRiver ID */ + phost->id = id; + + /* Unlink class*/ + phost->pActiveClass = NULL; + phost->ClassNumber = 0; + + /* Restore default states and prepare EP0 */ + DeInitStateMachine(phost); + + /* Assign User process */ + if(pUsrFunc != NULL) + { + phost->pUser = pUsrFunc; + } + +#if (USBH_USE_OS == 1) + + /* Create USB Host Queue */ + osMessageQDef(USBH_Queue, 10, uint16_t); + phost->os_event = osMessageCreate (osMessageQ(USBH_Queue), NULL); + + /*Create USB Host Task */ + osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0, 8 * configMINIMAL_STACK_SIZE); + phost->thread = osThreadCreate (osThread(USBH_Thread), phost); +#endif + + /* Initialize low level driver */ + USBH_LL_Init(phost); + return USBH_OK; +} + +/** + * @brief HCD_Init + * De-Initialize the Host portion of the driver. + * @param phost: Host Handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_DeInit(USBH_HandleTypeDef *phost) +{ + DeInitStateMachine(phost); + + if(phost->pData != NULL) + { + phost->pActiveClass->pData = NULL; + USBH_LL_Stop(phost); + } + + return USBH_OK; +} + +/** + * @brief DeInitStateMachine + * De-Initialize the Host state machine. + * @param phost: Host Handle + * @retval USBH Status + */ +static USBH_StatusTypeDef DeInitStateMachine(USBH_HandleTypeDef *phost) +{ + uint32_t i = 0; + + /* Clear Pipes flags*/ + for ( ; i < USBH_MAX_PIPES_NBR; i++) + { + phost->Pipes[i] = 0; + } + + for(i = 0; i< USBH_MAX_DATA_BUFFER; i++) + { + phost->device.Data[i] = 0; + } + + phost->gState = HOST_IDLE; + phost->EnumState = ENUM_IDLE; + phost->RequestState = CMD_SEND; + phost->Timer = 0; + + phost->Control.state = CTRL_SETUP; + phost->Control.pipe_size = USBH_MPS_DEFAULT; + phost->Control.errorcount = 0; + + phost->device.address = USBH_ADDRESS_DEFAULT; + phost->device.speed = USBH_SPEED_FULL; + + return USBH_OK; +} + +/** + * @brief USBH_RegisterClass + * Link class driver to Host Core. + * @param phost : Host Handle + * @param pclass: Class handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_RegisterClass(USBH_HandleTypeDef *phost, USBH_ClassTypeDef *pclass) +{ + USBH_StatusTypeDef status = USBH_OK; + + if(pclass != 0) + { + if(phost->ClassNumber < USBH_MAX_NUM_SUPPORTED_CLASS) + { + /* link the class tgo the USB Host handle */ + phost->pClass[phost->ClassNumber++] = pclass; + status = USBH_OK; + } + else + { + USBH_ErrLog("Max Class Number reached"); + status = USBH_FAIL; + } + } + else + { + USBH_ErrLog("Invalid Class handle"); + status = USBH_FAIL; + } + + return status; +} + +/** + * @brief USBH_SelectInterface + * Select current interface. + * @param phost: Host Handle + * @param interface: Interface number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_SelectInterface(USBH_HandleTypeDef *phost, uint8_t interface) +{ + USBH_StatusTypeDef status = USBH_OK; + + if(interface < phost->device.CfgDesc.bNumInterfaces) + { + phost->device.current_interface = interface; + USBH_UsrLog ("Switching to Interface (#%d)", interface); + USBH_UsrLog ("Class : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass ); + USBH_UsrLog ("SubClass : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceSubClass ); + USBH_UsrLog ("Protocol : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol ); + } + else + { + USBH_ErrLog ("Cannot Select This Interface."); + status = USBH_FAIL; + } + return status; +} + +/** + * @brief USBH_GetActiveClass + * Return Device Class. + * @param phost: Host Handle + * @param interface: Interface index + * @retval Class Code + */ +uint8_t USBH_GetActiveClass(USBH_HandleTypeDef *phost) +{ + return (phost->device.CfgDesc.Itf_Desc[0].bInterfaceClass); +} +/** + * @brief USBH_FindInterface + * Find the interface index for a specific class. + * @param phost: Host Handle + * @param Class: Class code + * @param SubClass: SubClass code + * @param Protocol: Protocol code + * @retval interface index in the configuration structure + * @note : (1)interface index 0xFF means interface index not found + */ +uint8_t USBH_FindInterface(USBH_HandleTypeDef *phost, uint8_t Class, uint8_t SubClass, uint8_t Protocol) +{ + USBH_InterfaceDescTypeDef *pif ; + USBH_CfgDescTypeDef *pcfg ; + int8_t if_ix = 0; + + pif = (USBH_InterfaceDescTypeDef *)0; + pcfg = &phost->device.CfgDesc; + + if((pif->bInterfaceClass == 0xFF) &&(pif->bInterfaceSubClass == 0xFF) && (pif->bInterfaceProtocol == 0xFF)) + { + return 0xFF; + } + + while (if_ix < USBH_MAX_NUM_INTERFACES) + { + pif = &pcfg->Itf_Desc[if_ix]; + if(((pif->bInterfaceClass == Class) || (Class == 0xFF))&& + ((pif->bInterfaceSubClass == SubClass) || (SubClass == 0xFF))&& + ((pif->bInterfaceProtocol == Protocol) || (Protocol == 0xFF))) + { + return if_ix; + } + if_ix++; + } + return 0xFF; +} + +/** + * @brief USBH_FindInterfaceIndex + * Find the interface index for a specific class interface and alternate setting number. + * @param phost: Host Handle + * @param interface_number: interface number + * @param alt_settings : alaternate setting number + * @retval interface index in the configuration structure + * @note : (1)interface index 0xFF means interface index not found + */ +uint8_t USBH_FindInterfaceIndex(USBH_HandleTypeDef *phost, uint8_t interface_number, uint8_t alt_settings) +{ + USBH_InterfaceDescTypeDef *pif ; + USBH_CfgDescTypeDef *pcfg ; + int8_t if_ix = 0; + + pif = (USBH_InterfaceDescTypeDef *)0; + pcfg = &phost->device.CfgDesc; + + while (if_ix < USBH_MAX_NUM_INTERFACES) + { + pif = &pcfg->Itf_Desc[if_ix]; + if((pif->bInterfaceNumber == interface_number) && (pif->bAlternateSetting == alt_settings)) + { + return if_ix; + } + if_ix++; + } + return 0xFF; +} + +/** + * @brief USBH_Start + * Start the USB Host Core. + * @param phost: Host Handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Start (USBH_HandleTypeDef *phost) +{ + /* Start the low level driver */ + USBH_LL_Start(phost); + + /* Activate VBUS on the port */ + USBH_LL_DriverVBUS (phost, TRUE); + + return USBH_OK; +} + +/** + * @brief USBH_Stop + * Stop the USB Host Core. + * @param phost: Host Handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Stop (USBH_HandleTypeDef *phost) +{ + /* Stop and cleanup the low level driver */ + USBH_LL_Stop(phost); + + /* DeActivate VBUS on the port */ + USBH_LL_DriverVBUS (phost, FALSE); + + /* FRee Control Pipes */ + USBH_FreePipe (phost, phost->Control.pipe_in); + USBH_FreePipe (phost, phost->Control.pipe_out); + + return USBH_OK; +} + +/** + * @brief HCD_ReEnumerate + * Perform a new Enumeration phase. + * @param phost: Host Handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_ReEnumerate (USBH_HandleTypeDef *phost) +{ + /*Stop Host */ + USBH_Stop(phost); + + /*Device has disconnected, so wait for 200 ms */ + USBH_Delay(200); + + /* Set State machines in default state */ + DeInitStateMachine(phost); + + /* Start again the host */ + USBH_Start(phost); + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); +#endif + return USBH_OK; +} + +/** + * @brief USBH_Process + * Background process of the USB Core. + * @param phost: Host Handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Process(USBH_HandleTypeDef *phost) +{ + __IO USBH_StatusTypeDef status = USBH_FAIL; + uint8_t idx = 0; + + switch (phost->gState) + { + case HOST_IDLE : + + if (phost->device.is_connected) + { + /* Wait for 200 ms after connection */ + phost->gState = HOST_DEV_WAIT_FOR_ATTACHMENT; + USBH_Delay(200); + USBH_LL_ResetPort(phost); +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); +#endif + } + break; + + case HOST_DEV_WAIT_FOR_ATTACHMENT: + break; + + case HOST_DEV_ATTACHED : + + USBH_UsrLog("USB Device Attached"); + + /* Wait for 100 ms after Reset */ + USBH_Delay(100); + + phost->device.speed = USBH_LL_GetSpeed(phost); + + phost->gState = HOST_ENUMERATION; + + phost->Control.pipe_out = USBH_AllocPipe (phost, 0x00); + phost->Control.pipe_in = USBH_AllocPipe (phost, 0x80); + + + /* Open Control pipes */ + USBH_OpenPipe (phost, + phost->Control.pipe_in, + 0x80, + phost->device.address, + phost->device.speed, + USBH_EP_CONTROL, + phost->Control.pipe_size); + + /* Open Control pipes */ + USBH_OpenPipe (phost, + phost->Control.pipe_out, + 0x00, + phost->device.address, + phost->device.speed, + USBH_EP_CONTROL, + phost->Control.pipe_size); + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); +#endif + + break; + + case HOST_ENUMERATION: + /* Check for enumeration status */ + if ( USBH_HandleEnum(phost) == USBH_OK) + { + /* The function shall return USBH_OK when full enumeration is complete */ + USBH_UsrLog ("Enumeration done."); + phost->device.current_interface = 0; + if(phost->device.DevDesc.bNumConfigurations == 1) + { + USBH_UsrLog ("This device has only 1 configuration."); + phost->gState = HOST_SET_CONFIGURATION; + + } + else + { + phost->gState = HOST_INPUT; + } + + } + break; + + case HOST_INPUT: + { + /* user callback for end of device basic enumeration */ + if(phost->pUser != NULL) + { + phost->pUser(phost, HOST_USER_SELECT_CONFIGURATION); + phost->gState = HOST_SET_CONFIGURATION; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + } + } + break; + + case HOST_SET_CONFIGURATION: + /* set configuration */ + if (USBH_SetCfg(phost, phost->device.CfgDesc.bConfigurationValue) == USBH_OK) + { + phost->gState = HOST_CHECK_CLASS; + USBH_UsrLog ("Default configuration set."); + + } + + break; + + case HOST_CHECK_CLASS: + + if(phost->ClassNumber == 0) + { + USBH_UsrLog ("No Class has been registered."); + } + else + { + phost->pActiveClass = NULL; + + for (idx = 0; idx < USBH_MAX_NUM_SUPPORTED_CLASS ; idx ++) + { + if(phost->pClass[idx]->ClassCode == phost->device.CfgDesc.Itf_Desc[0].bInterfaceClass) + { + phost->pActiveClass = phost->pClass[idx]; + } + } + + if(phost->pActiveClass != NULL) + { + if(phost->pActiveClass->Init(phost)== USBH_OK) + { + phost->gState = HOST_CLASS_REQUEST; + USBH_UsrLog ("%s class started.", phost->pActiveClass->Name); + + /* Inform user that a class has been activated */ + phost->pUser(phost, HOST_USER_CLASS_SELECTED); + } + else + { + phost->gState = HOST_ABORT_STATE; + USBH_UsrLog ("Device not supporting %s class.", phost->pActiveClass->Name); + } + } + else + { + phost->gState = HOST_ABORT_STATE; + USBH_UsrLog ("No registered class for this device."); + } + } + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + break; + + case HOST_CLASS_REQUEST: + /* process class standard contol requests state machine */ + + if(phost->pActiveClass != NULL) + { + status = phost->pActiveClass->Requests(phost); + + if(status == USBH_OK) + { + phost->gState = HOST_CLASS; + } + } + else + { + phost->gState = HOST_ABORT_STATE; + USBH_ErrLog ("Invalid Class Driver."); + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + } + + break; + case HOST_CLASS: + /* process class state machine */ + if(phost->pActiveClass != NULL) + { + phost->pActiveClass->BgndProcess(phost); + } + break; + + case HOST_DEV_DISCONNECTED : + + DeInitStateMachine(phost); + + /* Re-Initilaize Host for new Enumeration */ + if(phost->pActiveClass != NULL) + { + phost->pActiveClass->DeInit(phost); + phost->pActiveClass = NULL; + } + break; + + case HOST_ABORT_STATE: + default : + break; + } + return USBH_OK; +} + + +/** + * @brief USBH_HandleEnum + * This function includes the complete enumeration process + * @param phost: Host Handle + * @retval USBH_Status + */ +static USBH_StatusTypeDef USBH_HandleEnum (USBH_HandleTypeDef *phost) +{ + USBH_StatusTypeDef Status = USBH_BUSY; + + switch (phost->EnumState) + { + case ENUM_IDLE: + /* Get Device Desc for only 1st 8 bytes : To get EP0 MaxPacketSize */ + if ( USBH_Get_DevDesc(phost, 8) == USBH_OK) + { + phost->Control.pipe_size = phost->device.DevDesc.bMaxPacketSize; + + phost->EnumState = ENUM_GET_FULL_DEV_DESC; + + /* modify control channels configuration for MaxPacket size */ + USBH_OpenPipe (phost, + phost->Control.pipe_in, + 0x80, + phost->device.address, + phost->device.speed, + USBH_EP_CONTROL, + phost->Control.pipe_size); + + /* Open Control pipes */ + USBH_OpenPipe (phost, + phost->Control.pipe_out, + 0x00, + phost->device.address, + phost->device.speed, + USBH_EP_CONTROL, + phost->Control.pipe_size); + + } + break; + + case ENUM_GET_FULL_DEV_DESC: + /* Get FULL Device Desc */ + if ( USBH_Get_DevDesc(phost, USB_DEVICE_DESC_SIZE)== USBH_OK) + { + USBH_UsrLog("PID: %xh", phost->device.DevDesc.idProduct ); + USBH_UsrLog("VID: %xh", phost->device.DevDesc.idVendor ); + + phost->EnumState = ENUM_SET_ADDR; + + } + break; + + case ENUM_SET_ADDR: + /* set address */ + if ( USBH_SetAddress(phost, USBH_DEVICE_ADDRESS) == USBH_OK) + { + USBH_Delay(2); + phost->device.address = USBH_DEVICE_ADDRESS; + + /* user callback for device address assigned */ + USBH_UsrLog("Address (#%d) assigned.", phost->device.address); + phost->EnumState = ENUM_GET_CFG_DESC; + + /* modify control channels to update device address */ + USBH_OpenPipe (phost, + phost->Control.pipe_in, + 0x80, + phost->device.address, + phost->device.speed, + USBH_EP_CONTROL, + phost->Control.pipe_size); + + /* Open Control pipes */ + USBH_OpenPipe (phost, + phost->Control.pipe_out, + 0x00, + phost->device.address, + phost->device.speed, + USBH_EP_CONTROL, + phost->Control.pipe_size); + } + break; + + case ENUM_GET_CFG_DESC: + /* get standard configuration descriptor */ + if ( USBH_Get_CfgDesc(phost, + USB_CONFIGURATION_DESC_SIZE) == USBH_OK) + { + phost->EnumState = ENUM_GET_FULL_CFG_DESC; + } + break; + + case ENUM_GET_FULL_CFG_DESC: + /* get FULL config descriptor (config, interface, endpoints) */ + if (USBH_Get_CfgDesc(phost, + phost->device.CfgDesc.wTotalLength) == USBH_OK) + { + phost->EnumState = ENUM_GET_MFC_STRING_DESC; + } + break; + + case ENUM_GET_MFC_STRING_DESC: + if (phost->device.DevDesc.iManufacturer != 0) + { /* Check that Manufacturer String is available */ + + if ( USBH_Get_StringDesc(phost, + phost->device.DevDesc.iManufacturer, + phost->device.Data , + 0xff) == USBH_OK) + { + /* User callback for Manufacturing string */ + USBH_UsrLog("Manufacturer : %s", (char *)phost->device.Data); + phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + } + } + else + { + USBH_UsrLog("Manufacturer : N/A"); + phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + } + break; + + case ENUM_GET_PRODUCT_STRING_DESC: + if (phost->device.DevDesc.iProduct != 0) + { /* Check that Product string is available */ + if ( USBH_Get_StringDesc(phost, + phost->device.DevDesc.iProduct, + phost->device.Data, + 0xff) == USBH_OK) + { + /* User callback for Product string */ + USBH_UsrLog("Product : %s", (char *)phost->device.Data); + phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC; + } + } + else + { + USBH_UsrLog("Product : N/A"); + phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + } + break; + + case ENUM_GET_SERIALNUM_STRING_DESC: + if (phost->device.DevDesc.iSerialNumber != 0) + { /* Check that Serial number string is available */ + if ( USBH_Get_StringDesc(phost, + phost->device.DevDesc.iSerialNumber, + phost->device.Data, + 0xff) == USBH_OK) + { + /* User callback for Serial number string */ + USBH_UsrLog("Serial Number : %s", (char *)phost->device.Data); + Status = USBH_OK; + } + } + else + { + USBH_UsrLog("Serial Number : N/A"); + Status = USBH_OK; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + } + break; + + default: + break; + } + return Status; +} + +/** + * @brief USBH_LL_SetTimer + * Set the initial Host Timer tick + * @param phost: Host Handle + * @retval None + */ +void USBH_LL_SetTimer (USBH_HandleTypeDef *phost, uint32_t time) +{ + phost->Timer = time; +} +/** + * @brief USBH_LL_IncTimer + * Increment Host Timer tick + * @param phost: Host Handle + * @retval None + */ +void USBH_LL_IncTimer (USBH_HandleTypeDef *phost) +{ + phost->Timer ++; + USBH_HandleSof(phost); +} + +/** + * @brief USBH_HandleSof + * Call SOF process + * @param phost: Host Handle + * @retval None + */ +void USBH_HandleSof (USBH_HandleTypeDef *phost) +{ + if((phost->gState == HOST_CLASS)&&(phost->pActiveClass != NULL)) + { + phost->pActiveClass->SOFProcess(phost); + } +} +/** + * @brief USBH_LL_Connect + * Handle USB Host connexion event + * @param phost: Host Handle + * @retval USBH_Status + */ +USBH_StatusTypeDef USBH_LL_Connect (USBH_HandleTypeDef *phost) +{ + if(phost->gState == HOST_IDLE ) + { + phost->device.is_connected = 1; + phost->gState = HOST_IDLE ; + + if(phost->pUser != NULL) + { + phost->pUser(phost, HOST_USER_CONNECTION); + } + } + else if(phost->gState == HOST_DEV_WAIT_FOR_ATTACHMENT ) + { + phost->gState = HOST_DEV_ATTACHED ; + } +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); +#endif + + return USBH_OK; +} + +/** + * @brief USBH_LL_Disconnect + * Handle USB Host disconnexion event + * @param phost: Host Handle + * @retval USBH_Status + */ +USBH_StatusTypeDef USBH_LL_Disconnect (USBH_HandleTypeDef *phost) +{ + /*Stop Host */ + USBH_LL_Stop(phost); + + /* FRee Control Pipes */ + USBH_FreePipe (phost, phost->Control.pipe_in); + USBH_FreePipe (phost, phost->Control.pipe_out); + + phost->device.is_connected = 0; + + if(phost->pUser != NULL) + { + phost->pUser(phost, HOST_USER_DISCONNECTION); + } + USBH_UsrLog("USB Device disconnected"); + + /* Start the low level driver */ + USBH_LL_Start(phost); + + phost->gState = HOST_DEV_DISCONNECTED; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); +#endif + + return USBH_OK; +} + + +#if (USBH_USE_OS == 1) +/** + * @brief USB Host Thread task + * @param pvParameters not used + * @retval None + */ +static void USBH_Process_OS(void const * argument) +{ + osEvent event; + + for(;;) + { + event = osMessageGet(((USBH_HandleTypeDef *)argument)->os_event, osWaitForever ); + + if( event.status == osEventMessage ) + { + USBH_Process((USBH_HandleTypeDef *)argument); + } + } +} + +/** +* @brief USBH_LL_NotifyURBChange +* Notify URB state Change +* @param phost: Host handle +* @retval USBH Status +*/ +USBH_StatusTypeDef USBH_LL_NotifyURBChange (USBH_HandleTypeDef *phost) +{ + osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); + return USBH_OK; +} +#endif +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbh_ctlreq.c b/ports/stm32/usbh_ctlreq.c new file mode 100644 index 000000000000..90dca7ffef12 --- /dev/null +++ b/ports/stm32/usbh_ctlreq.c @@ -0,0 +1,881 @@ +/** + ****************************************************************************** + * @file usbh_ctlreq.c + * @author MCD Application Team + * @version V3.0.0 + * @date 18-February-2014 + * @brief This file implements the control requests for device enumeration + ****************************************************************************** + * @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 "usbh_ctlreq.h" + +/** @addtogroup USBH_LIB +* @{ +*/ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_CTLREQ +* @brief This file implements the standard requests for device enumeration +* @{ +*/ + + +/** @defgroup USBH_CTLREQ_Private_Defines +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_CTLREQ_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + + +/** @defgroup USBH_CTLREQ_Private_Macros +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_CTLREQ_Private_Variables +* @{ +*/ +/** +* @} +*/ + +/** @defgroup USBH_CTLREQ_Private_FunctionPrototypes +* @{ +*/ +static USBH_StatusTypeDef USBH_HandleControl (USBH_HandleTypeDef *phost); + +static void USBH_ParseDevDesc (USBH_DevDescTypeDef* , uint8_t *buf, uint16_t length); + +static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc, + uint8_t *buf, + uint16_t length); + + +static void USBH_ParseEPDesc (USBH_EpDescTypeDef *ep_descriptor, uint8_t *buf); +static void USBH_ParseStringDesc (uint8_t* psrc, uint8_t* pdest, uint16_t length); +static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor, uint8_t *buf); + + +/** +* @} +*/ + + +/** @defgroup USBH_CTLREQ_Private_Functions +* @{ +*/ + + +/** + * @brief USBH_Get_DevDesc + * Issue Get Device Descriptor command to the device. Once the response + * received, it parses the device descriptor and updates the status. + * @param phost: Host Handle + * @param length: Length of the descriptor + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Get_DevDesc(USBH_HandleTypeDef *phost, uint8_t length) +{ + USBH_StatusTypeDef status; + + if((status = USBH_GetDescriptor(phost, + USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD, + USB_DESC_DEVICE, + phost->device.Data, + length)) == USBH_OK) + { + /* Commands successfully sent and Response Received */ + USBH_ParseDevDesc(&phost->device.DevDesc, phost->device.Data, length); + } + return status; +} + +/** + * @brief USBH_Get_CfgDesc + * Issues Configuration Descriptor to the device. Once the response + * received, it parses the configuartion descriptor and updates the + * status. + * @param phost: Host Handle + * @param length: Length of the descriptor + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Get_CfgDesc(USBH_HandleTypeDef *phost, + uint16_t length) + +{ + USBH_StatusTypeDef status; + uint8_t *pData; +#if (USBH_KEEP_CFG_DESCRIPTOR == 1) + pData = phost->device.CfgDesc_Raw; +#else + pData = phost->device.Data; +#endif + if((status = USBH_GetDescriptor(phost, + USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD, + USB_DESC_CONFIGURATION, + pData, + length)) == USBH_OK) + { + + /* Commands successfully sent and Response Received */ + USBH_ParseCfgDesc (&phost->device.CfgDesc, + pData, + length); + + } + return status; +} + + +/** + * @brief USBH_Get_StringDesc + * Issues string Descriptor command to the device. Once the response + * received, it parses the string descriptor and updates the status. + * @param phost: Host Handle + * @param string_index: String index for the descriptor + * @param buff: Buffer address for the descriptor + * @param length: Length of the descriptor + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Get_StringDesc(USBH_HandleTypeDef *phost, + uint8_t string_index, + uint8_t *buff, + uint16_t length) +{ + USBH_StatusTypeDef status; + if((status = USBH_GetDescriptor(phost, + USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD, + USB_DESC_STRING | string_index, + phost->device.Data, + length)) == USBH_OK) + { + /* Commands successfully sent and Response Received */ + USBH_ParseStringDesc(phost->device.Data,buff, length); + } + return status; +} + +/** + * @brief USBH_GetDescriptor + * Issues Descriptor command to the device. Once the response received, + * it parses the descriptor and updates the status. + * @param phost: Host Handle + * @param req_type: Descriptor type + * @param value_idx: wValue for the GetDescriptr request + * @param buff: Buffer to store the descriptor + * @param length: Length of the descriptor + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_GetDescriptor(USBH_HandleTypeDef *phost, + uint8_t req_type, + uint16_t value_idx, + uint8_t* buff, + uint16_t length ) +{ + if(phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_D2H | req_type; + phost->Control.setup.b.bRequest = USB_REQ_GET_DESCRIPTOR; + phost->Control.setup.b.wValue.w = value_idx; + + if ((value_idx & 0xff00) == USB_DESC_STRING) + { + phost->Control.setup.b.wIndex.w = 0x0409; + } + else + { + phost->Control.setup.b.wIndex.w = 0; + } + phost->Control.setup.b.wLength.w = length; + } + return USBH_CtlReq(phost, buff , length ); +} + +/** + * @brief USBH_SetAddress + * This command sets the address to the connected device + * @param phost: Host Handle + * @param DeviceAddress: Device address to assign + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_SetAddress(USBH_HandleTypeDef *phost, + uint8_t DeviceAddress) +{ + if(phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE | \ + USB_REQ_TYPE_STANDARD; + + phost->Control.setup.b.bRequest = USB_REQ_SET_ADDRESS; + + phost->Control.setup.b.wValue.w = (uint16_t)DeviceAddress; + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = 0; + } + return USBH_CtlReq(phost, 0 , 0 ); +} + +/** + * @brief USBH_SetCfg + * The command sets the configuration value to the connected device + * @param phost: Host Handle + * @param cfg_idx: Configuration value + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_SetCfg(USBH_HandleTypeDef *phost, + uint16_t cfg_idx) +{ + if(phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE |\ + USB_REQ_TYPE_STANDARD; + phost->Control.setup.b.bRequest = USB_REQ_SET_CONFIGURATION; + phost->Control.setup.b.wValue.w = cfg_idx; + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = 0; + } + + return USBH_CtlReq(phost, 0 , 0 ); +} + +/** + * @brief USBH_SetInterface + * The command sets the Interface value to the connected device + * @param phost: Host Handle + * @param altSetting: Interface value + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_SetInterface(USBH_HandleTypeDef *phost, + uint8_t ep_num, uint8_t altSetting) +{ + + if(phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE | \ + USB_REQ_TYPE_STANDARD; + + phost->Control.setup.b.bRequest = USB_REQ_SET_INTERFACE; + phost->Control.setup.b.wValue.w = altSetting; + phost->Control.setup.b.wIndex.w = ep_num; + phost->Control.setup.b.wLength.w = 0; + } + return USBH_CtlReq(phost, 0 , 0 ); +} + +/** + * @brief USBH_ClrFeature + * This request is used to clear or disable a specific feature. + * @param phost: Host Handle + * @param ep_num: endpoint number + * @param hc_num: Host channel number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_ClrFeature(USBH_HandleTypeDef *phost, + uint8_t ep_num) +{ + if(phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_H2D | + USB_REQ_RECIPIENT_ENDPOINT | + USB_REQ_TYPE_STANDARD; + + phost->Control.setup.b.bRequest = USB_REQ_CLEAR_FEATURE; + phost->Control.setup.b.wValue.w = FEATURE_SELECTOR_ENDPOINT; + phost->Control.setup.b.wIndex.w = ep_num; + phost->Control.setup.b.wLength.w = 0; + } + return USBH_CtlReq(phost, 0 , 0 ); +} + +/** + * @brief USBH_ParseDevDesc + * This function Parses the device descriptor + * @param dev_desc: device_descriptor destinaton address + * @param buf: Buffer where the source descriptor is available + * @param length: Length of the descriptor + * @retval None + */ +static void USBH_ParseDevDesc (USBH_DevDescTypeDef* dev_desc, + uint8_t *buf, + uint16_t length) +{ + dev_desc->bLength = *(uint8_t *) (buf + 0); + dev_desc->bDescriptorType = *(uint8_t *) (buf + 1); + dev_desc->bcdUSB = LE16 (buf + 2); + dev_desc->bDeviceClass = *(uint8_t *) (buf + 4); + dev_desc->bDeviceSubClass = *(uint8_t *) (buf + 5); + dev_desc->bDeviceProtocol = *(uint8_t *) (buf + 6); + dev_desc->bMaxPacketSize = *(uint8_t *) (buf + 7); + + if (length > 8) + { /* For 1st time after device connection, Host may issue only 8 bytes for + Device Descriptor Length */ + dev_desc->idVendor = LE16 (buf + 8); + dev_desc->idProduct = LE16 (buf + 10); + dev_desc->bcdDevice = LE16 (buf + 12); + dev_desc->iManufacturer = *(uint8_t *) (buf + 14); + dev_desc->iProduct = *(uint8_t *) (buf + 15); + dev_desc->iSerialNumber = *(uint8_t *) (buf + 16); + dev_desc->bNumConfigurations = *(uint8_t *) (buf + 17); + } +} + +/** + * @brief USBH_ParseCfgDesc + * This function Parses the configuration descriptor + * @param cfg_desc: Configuration Descriptor address + * @param buf: Buffer where the source descriptor is available + * @param length: Length of the descriptor + * @retval None + */ +static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc, + uint8_t *buf, + uint16_t length) +{ + USBH_InterfaceDescTypeDef *pif ; + USBH_EpDescTypeDef *pep; + USBH_DescHeader_t *pdesc = (USBH_DescHeader_t *)buf; + uint16_t ptr; + int8_t if_ix = 0; + int8_t ep_ix = 0; + + pdesc = (USBH_DescHeader_t *)buf; + + /* Parse configuration descriptor */ + cfg_desc->bLength = *(uint8_t *) (buf + 0); + cfg_desc->bDescriptorType = *(uint8_t *) (buf + 1); + cfg_desc->wTotalLength = LE16 (buf + 2); + cfg_desc->bNumInterfaces = *(uint8_t *) (buf + 4); + cfg_desc->bConfigurationValue = *(uint8_t *) (buf + 5); + cfg_desc->iConfiguration = *(uint8_t *) (buf + 6); + cfg_desc->bmAttributes = *(uint8_t *) (buf + 7); + cfg_desc->bMaxPower = *(uint8_t *) (buf + 8); + + + if (length > USB_CONFIGURATION_DESC_SIZE) + { + ptr = USB_LEN_CFG_DESC; + pif = (USBH_InterfaceDescTypeDef *)0; + + + while ((if_ix < USBH_MAX_NUM_INTERFACES ) && (ptr < cfg_desc->wTotalLength)) + { + pdesc = USBH_GetNextDesc((uint8_t *)pdesc, &ptr); + if (pdesc->bDescriptorType == USB_DESC_TYPE_INTERFACE) + { + pif = &cfg_desc->Itf_Desc[if_ix]; + USBH_ParseInterfaceDesc (pif, (uint8_t *)pdesc); + + ep_ix = 0; + pep = (USBH_EpDescTypeDef *)0; + while ((ep_ix < pif->bNumEndpoints) && (ptr < cfg_desc->wTotalLength)) + { + pdesc = USBH_GetNextDesc((void* )pdesc, &ptr); + if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT) + { + pep = &cfg_desc->Itf_Desc[if_ix].Ep_Desc[ep_ix]; + USBH_ParseEPDesc (pep, (uint8_t *)pdesc); + ep_ix++; + } + } + if_ix++; + } + } + } +} + + + +/** + * @brief USBH_ParseInterfaceDesc + * This function Parses the interface descriptor + * @param if_descriptor : Interface descriptor destination + * @param buf: Buffer where the descriptor data is available + * @retval None + */ +static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor, + uint8_t *buf) +{ + if_descriptor->bLength = *(uint8_t *) (buf + 0); + if_descriptor->bDescriptorType = *(uint8_t *) (buf + 1); + if_descriptor->bInterfaceNumber = *(uint8_t *) (buf + 2); + if_descriptor->bAlternateSetting = *(uint8_t *) (buf + 3); + if_descriptor->bNumEndpoints = *(uint8_t *) (buf + 4); + if_descriptor->bInterfaceClass = *(uint8_t *) (buf + 5); + if_descriptor->bInterfaceSubClass = *(uint8_t *) (buf + 6); + if_descriptor->bInterfaceProtocol = *(uint8_t *) (buf + 7); + if_descriptor->iInterface = *(uint8_t *) (buf + 8); +} + +/** + * @brief USBH_ParseEPDesc + * This function Parses the endpoint descriptor + * @param ep_descriptor: Endpoint descriptor destination address + * @param buf: Buffer where the parsed descriptor stored + * @retval None + */ +static void USBH_ParseEPDesc (USBH_EpDescTypeDef *ep_descriptor, + uint8_t *buf) +{ + + ep_descriptor->bLength = *(uint8_t *) (buf + 0); + ep_descriptor->bDescriptorType = *(uint8_t *) (buf + 1); + ep_descriptor->bEndpointAddress = *(uint8_t *) (buf + 2); + ep_descriptor->bmAttributes = *(uint8_t *) (buf + 3); + ep_descriptor->wMaxPacketSize = LE16 (buf + 4); + ep_descriptor->bInterval = *(uint8_t *) (buf + 6); +} + +/** + * @brief USBH_ParseStringDesc + * This function Parses the string descriptor + * @param psrc: Source pointer containing the descriptor data + * @param pdest: Destination address pointer + * @param length: Length of the descriptor + * @retval None + */ +static void USBH_ParseStringDesc (uint8_t* psrc, + uint8_t* pdest, + uint16_t length) +{ + uint16_t strlength; + uint16_t idx; + + /* The UNICODE string descriptor is not NULL-terminated. The string length is + computed by substracting two from the value of the first byte of the descriptor. + */ + + /* Check which is lower size, the Size of string or the length of bytes read + from the device */ + + if ( psrc[1] == USB_DESC_TYPE_STRING) + { /* Make sure the Descriptor is String Type */ + + /* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */ + strlength = ( ( (psrc[0]-2) <= length) ? (psrc[0]-2) :length); + psrc += 2; /* Adjust the offset ignoring the String Len and Descriptor type */ + + for (idx = 0; idx < strlength; idx+=2 ) + {/* Copy Only the string and ignore the UNICODE ID, hence add the src */ + *pdest = psrc[idx]; + pdest++; + } + *pdest = 0; /* mark end of string */ + } +} + +/** + * @brief USBH_GetNextDesc + * This function return the next descriptor header + * @param buf: Buffer where the cfg descriptor is available + * @param ptr: data popinter inside the cfg descriptor + * @retval next header + */ +USBH_DescHeader_t *USBH_GetNextDesc (uint8_t *pbuf, uint16_t *ptr) +{ + USBH_DescHeader_t *pnext; + + *ptr += ((USBH_DescHeader_t *)pbuf)->bLength; + pnext = (USBH_DescHeader_t *)((uint8_t *)pbuf + \ + ((USBH_DescHeader_t *)pbuf)->bLength); + + return(pnext); +} + + +/** + * @brief USBH_CtlReq + * USBH_CtlReq sends a control request and provide the status after + * completion of the request + * @param phost: Host Handle + * @param req: Setup Request Structure + * @param buff: data buffer address to store the response + * @param length: length of the response + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_CtlReq (USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length) +{ + USBH_StatusTypeDef status; + status = USBH_BUSY; + + switch (phost->RequestState) + { + case CMD_SEND: + /* Start a SETUP transfer */ + phost->Control.buff = buff; + phost->Control.length = length; + phost->Control.state = CTRL_SETUP; + phost->RequestState = CMD_WAIT; + status = USBH_BUSY; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + break; + + case CMD_WAIT: + status = USBH_HandleControl(phost); + if (status == USBH_OK) + { + /* Commands successfully sent and Response Received */ + phost->RequestState = CMD_SEND; + phost->Control.state =CTRL_IDLE; + status = USBH_OK; + } + else if (status == USBH_FAIL) + { + /* Failure Mode */ + phost->RequestState = CMD_SEND; + status = USBH_FAIL; + } + break; + + default: + break; + } + return status; +} + +/** + * @brief USBH_HandleControl + * Handles the USB control transfer state machine + * @param phost: Host Handle + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_HandleControl (USBH_HandleTypeDef *phost) +{ + uint8_t direction; + USBH_StatusTypeDef status = USBH_BUSY; + USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE; + + switch (phost->Control.state) + { + case CTRL_SETUP: + /* send a SETUP packet */ + USBH_CtlSendSetup (phost, + (uint8_t *)phost->Control.setup.d8 , + phost->Control.pipe_out); + + phost->Control.state = CTRL_SETUP_WAIT; + break; + + case CTRL_SETUP_WAIT: + + URB_Status = USBH_LL_GetURBState(phost, phost->Control.pipe_out); + /* case SETUP packet sent successfully */ + if(URB_Status == USBH_URB_DONE) + { + direction = (phost->Control.setup.b.bmRequestType & USB_REQ_DIR_MASK); + + /* check if there is a data stage */ + if (phost->Control.setup.b.wLength.w != 0 ) + { + if (direction == USB_D2H) + { + /* Data Direction is IN */ + phost->Control.state = CTRL_DATA_IN; + } + else + { + /* Data Direction is OUT */ + phost->Control.state = CTRL_DATA_OUT; + } + } + /* No DATA stage */ + else + { + /* If there is No Data Transfer Stage */ + if (direction == USB_D2H) + { + /* Data Direction is IN */ + phost->Control.state = CTRL_STATUS_OUT; + } + else + { + /* Data Direction is OUT */ + phost->Control.state = CTRL_STATUS_IN; + } + } +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + else if(URB_Status == USBH_URB_ERROR) + { + phost->Control.state = CTRL_ERROR; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + break; + + case CTRL_DATA_IN: + /* Issue an IN token */ + phost->Control.timer = phost->Timer; + USBH_CtlReceiveData(phost, + phost->Control.buff, + phost->Control.length, + phost->Control.pipe_in); + + phost->Control.state = CTRL_DATA_IN_WAIT; + break; + + case CTRL_DATA_IN_WAIT: + + URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_in); + + /* check is DATA packet transfered successfully */ + if (URB_Status == USBH_URB_DONE) + { + phost->Control.state = CTRL_STATUS_OUT; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + + /* manage error cases*/ + if (URB_Status == USBH_URB_STALL) + { + /* In stall case, return to previous machine state*/ + status = USBH_NOT_SUPPORTED; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + else if (URB_Status == USBH_URB_ERROR) + { + /* Device error */ + phost->Control.state = CTRL_ERROR; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + break; + + case CTRL_DATA_OUT: + + USBH_CtlSendData (phost, + phost->Control.buff, + phost->Control.length , + phost->Control.pipe_out, + 1); + phost->Control.timer = phost->Timer; + phost->Control.state = CTRL_DATA_OUT_WAIT; + break; + + case CTRL_DATA_OUT_WAIT: + + URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_out); + + if (URB_Status == USBH_URB_DONE) + { /* If the Setup Pkt is sent successful, then change the state */ + phost->Control.state = CTRL_STATUS_IN; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + + /* handle error cases */ + else if (URB_Status == USBH_URB_STALL) + { + /* In stall case, return to previous machine state*/ + phost->Control.state = CTRL_STALLED; + status = USBH_NOT_SUPPORTED; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + else if (URB_Status == USBH_URB_NOTREADY) + { + /* Nack received from device */ + phost->Control.state = CTRL_DATA_OUT; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + else if (URB_Status == USBH_URB_ERROR) + { + /* device error */ + phost->Control.state = CTRL_ERROR; + status = USBH_FAIL; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + break; + + + case CTRL_STATUS_IN: + /* Send 0 bytes out packet */ + USBH_CtlReceiveData (phost, + 0, + 0, + phost->Control.pipe_in); + phost->Control.timer = phost->Timer; + phost->Control.state = CTRL_STATUS_IN_WAIT; + + break; + + case CTRL_STATUS_IN_WAIT: + + URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_in); + + if ( URB_Status == USBH_URB_DONE) + { /* Control transfers completed, Exit the State Machine */ + phost->Control.state = CTRL_COMPLETE; + status = USBH_OK; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + + else if (URB_Status == USBH_URB_ERROR) + { + phost->Control.state = CTRL_ERROR; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + else if(URB_Status == USBH_URB_STALL) + { + /* Control transfers completed, Exit the State Machine */ + status = USBH_NOT_SUPPORTED; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + break; + + case CTRL_STATUS_OUT: + USBH_CtlSendData (phost, + 0, + 0, + phost->Control.pipe_out, + 1); + phost->Control.timer = phost->Timer; + phost->Control.state = CTRL_STATUS_OUT_WAIT; + break; + + case CTRL_STATUS_OUT_WAIT: + + URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_out); + if (URB_Status == USBH_URB_DONE) + { + status = USBH_OK; + phost->Control.state = CTRL_COMPLETE; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + else if (URB_Status == USBH_URB_NOTREADY) + { + phost->Control.state = CTRL_STATUS_OUT; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + else if (URB_Status == USBH_URB_ERROR) + { + phost->Control.state = CTRL_ERROR; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + } + break; + + case CTRL_ERROR: + /* + After a halt condition is encountered or an error is detected by the + host, a control endpoint is allowed to recover by accepting the next Setup + PID; i.e., recovery actions via some other pipe are not required for control + endpoints. For the Default Control Pipe, a device reset will ultimately be + required to clear the halt or error condition if the next Setup PID is not + accepted. + */ + if (++ phost->Control.errorcount <= USBH_MAX_ERROR_COUNT) + { + /* try to recover control */ + USBH_LL_Stop(phost); + + /* Do the transmission again, starting from SETUP Packet */ + phost->Control.state = CTRL_SETUP; + phost->RequestState = CMD_SEND; + } + else + { + phost->Control.errorcount = 0; + USBH_ErrLog("Control error"); + status = USBH_FAIL; + + } + break; + + default: + break; + } + return status; +} + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + + diff --git a/ports/stm32/usbh_hid.c b/ports/stm32/usbh_hid.c new file mode 100644 index 000000000000..ae388f4fe7b8 --- /dev/null +++ b/ports/stm32/usbh_hid.c @@ -0,0 +1,799 @@ +/** + ****************************************************************************** + * @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 + * + *

© 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 "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 *) m_new(HID_HandleTypeDef, 1); + HID_Handle = phost->pActiveClass->pData; + HID_Handle->state = HID_ERROR_HOST; + + /*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_HOST; + 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) + { + m_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_HOST: + HID_Handle->Init(phost); + case HID_IDLE_HOST: + 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_HOST; + } + + break; + + case HID_SYNC_HOST: + + /* Sync with start of Even Frame */ + if(phost->Timer & 1) + { + HID_Handle->state = HID_GET_DATA_HOST; + } +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); +#endif + break; + + case HID_GET_DATA_HOST: + + USBH_InterruptReceiveData(phost, + HID_Handle->pData, + HID_Handle->length, + HID_Handle->InPipe); + + HID_Handle->state = HID_POLL_HOST; + HID_Handle->timer = phost->Timer; + HID_Handle->DataReady = 0; + break; + + case HID_POLL_HOST: + + 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_HOST; + } + } + + + 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_HOST) + { + if(( phost->Timer - HID_Handle->timer) >= HID_Handle->poll) + { + HID_Handle->state = HID_GET_DATA_HOST; +#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****/ \ No newline at end of file diff --git a/ports/stm32/usbh_hid_keybd.c b/ports/stm32/usbh_hid_keybd.c new file mode 100644 index 000000000000..d2a54aaecacf --- /dev/null +++ b/ports/stm32/usbh_hid_keybd.c @@ -0,0 +1,418 @@ +/** + ****************************************************************************** + * @file usbh_hid_keybd.c + * @author MCD Application Team + * @version V3.0.0 + * @date 18-February-2014 + * @brief This file is the application layer for USB Host HID Keyboard handling + * QWERTY and AZERTY Keyboard are supported as per the selection in + * usbh_hid_keybd.h + ****************************************************************************** + * @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 "usbh_hid_keybd.h" +#include "usbh_hid_parser.h" + +/** @addtogroup USBH_LIB +* @{ +*/ + +/** @addtogroup USBH_CLASS +* @{ +*/ + +/** @addtogroup USBH_HID_CLASS +* @{ +*/ + +/** @defgroup USBH_HID_KEYBD +* @brief This file includes HID Layer Handlers for USB Host HID class. +* @{ +*/ + +/** @defgroup USBH_HID_KEYBD_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_HID_KEYBD_Private_Defines +* @{ +*/ +/** +* @} +*/ +#ifndef AZERTY_KEYBOARD + #define QWERTY_KEYBOARD +#endif +#define KBD_LEFT_CTRL 0x01 +#define KBD_LEFT_SHIFT 0x02 +#define KBD_LEFT_ALT 0x04 +#define KBD_LEFT_GUI 0x08 +#define KBD_RIGHT_CTRL 0x10 +#define KBD_RIGHT_SHIFT 0x20 +#define KBD_RIGHT_ALT 0x40 +#define KBD_RIGHT_GUI 0x80 +#define KBR_MAX_NBR_PRESSED 6 + +/** @defgroup USBH_HID_KEYBD_Private_Macros +* @{ +*/ +/** +* @} +*/ + +/** @defgroup USBH_HID_KEYBD_Private_FunctionPrototypes +* @{ +*/ +static USBH_StatusTypeDef USBH_HID_KeybdDecode(USBH_HandleTypeDef *phost); +/** +* @} +*/ + +/** @defgroup USBH_HID_KEYBD_Private_Variables +* @{ +*/ + +HID_KEYBD_Info_TypeDef keybd_info; +uint32_t keybd_report_data[2]; + +static const HID_Report_ItemTypedef imp_0_lctrl={ + (uint8_t*)keybd_report_data+0, /*data*/ + 1, /*size*/ + 0, /*shift*/ + 0, /*count (only for array items)*/ + 0, /*signed?*/ + 0, /*min value read can return*/ + 1, /*max value read can return*/ + 0, /*min vale device can report*/ + 1, /*max value device can report*/ + 1 /*resolution*/ +}; +static const HID_Report_ItemTypedef imp_0_lshift={ + (uint8_t*)keybd_report_data+0, /*data*/ + 1, /*size*/ + 1, /*shift*/ + 0, /*count (only for array items)*/ + 0, /*signed?*/ + 0, /*min value read can return*/ + 1, /*max value read can return*/ + 0, /*min vale device can report*/ + 1, /*max value device can report*/ + 1 /*resolution*/ +}; +static const HID_Report_ItemTypedef imp_0_lalt={ + (uint8_t*)keybd_report_data+0, /*data*/ + 1, /*size*/ + 2, /*shift*/ + 0, /*count (only for array items)*/ + 0, /*signed?*/ + 0, /*min value read can return*/ + 1, /*max value read can return*/ + 0, /*min vale device can report*/ + 1, /*max value device can report*/ + 1 /*resolution*/ +}; +static const HID_Report_ItemTypedef imp_0_lgui={ + (uint8_t*)keybd_report_data+0, /*data*/ + 1, /*size*/ + 3, /*shift*/ + 0, /*count (only for array items)*/ + 0, /*signed?*/ + 0, /*min value read can return*/ + 1, /*max value read can return*/ + 0, /*min vale device can report*/ + 1, /*max value device can report*/ + 1 /*resolution*/ +}; +static const HID_Report_ItemTypedef imp_0_rctrl={ + (uint8_t*)keybd_report_data+0, /*data*/ + 1, /*size*/ + 4, /*shift*/ + 0, /*count (only for array items)*/ + 0, /*signed?*/ + 0, /*min value read can return*/ + 1, /*max value read can return*/ + 0, /*min vale device can report*/ + 1, /*max value device can report*/ + 1 /*resolution*/ +}; +static const HID_Report_ItemTypedef imp_0_rshift={ + (uint8_t*)keybd_report_data+0, /*data*/ + 1, /*size*/ + 5, /*shift*/ + 0, /*count (only for array items)*/ + 0, /*signed?*/ + 0, /*min value read can return*/ + 1, /*max value read can return*/ + 0, /*min vale device can report*/ + 1, /*max value device can report*/ + 1 /*resolution*/ +}; +static const HID_Report_ItemTypedef imp_0_ralt={ + (uint8_t*)keybd_report_data+0, /*data*/ + 1, /*size*/ + 6, /*shift*/ + 0, /*count (only for array items)*/ + 0, /*signed?*/ + 0, /*min value read can return*/ + 1, /*max value read can return*/ + 0, /*min vale device can report*/ + 1, /*max value device can report*/ + 1 /*resolution*/ +}; +static const HID_Report_ItemTypedef imp_0_rgui={ + (uint8_t*)keybd_report_data+0, /*data*/ + 1, /*size*/ + 7, /*shift*/ + 0, /*count (only for array items)*/ + 0, /*signed?*/ + 0, /*min value read can return*/ + 1, /*max value read can return*/ + 0, /*min vale device can report*/ + 1, /*max value device can report*/ + 1 /*resolution*/ +}; + +static const HID_Report_ItemTypedef imp_0_key_array={ + (uint8_t*)keybd_report_data+2, /*data*/ + 8, /*size*/ + 0, /*shift*/ + 6, /*count (only for array items)*/ + 0, /*signed?*/ + 0, /*min value read can return*/ + 101, /*max value read can return*/ + 0, /*min vale device can report*/ + 101, /*max value device can report*/ + 1 /*resolution*/ +}; + +#ifdef QWERTY_KEYBOARD +static const int8_t HID_KEYBRD_Key[] = { + '\0', '`', '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', '\0', '\r', + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', + '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', + 'k', 'l', ';', '\'', '\0', '\n', + '\0', '\0', 'z', 'x', 'c', 'v', 'b', 'n', + 'm', ',', '.', '/', '\0', '\0', + '\0', '\0', '\0', ' ', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '7', '4', '1', + '\0', '/', '8', '5', '2', + '0', '*', '9', '6', '3', + '.', '-', '+', '\0', '\n', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0' +}; + +static const int8_t HID_KEYBRD_ShiftKey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', + '_', '+', '\0', '\0', '\0', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', + 'I', 'O', 'P', '{', '}', '|', '\0', 'A', 'S', 'D', 'F', 'G', + 'H', 'J', 'K', 'L', ':', '"', '\0', '\n', '\0', '\0', 'Z', 'X', + 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#else + +static const int8_t HID_KEYBRD_Key[] = { + '\0', '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + '-', '=', '\0', '\r', '\t', 'a', 'z', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', '\0', 'q', 's', 'd', 'f', 'g', + 'h', 'j', 'k', 'l', 'm', '\0', '\0', '\n', '\0', '\0', 'w', 'x', + 'c', 'v', 'b', 'n', ',', ';', ':', '!', '\0', '\0', '\0', '\0', + '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '4', '1','\0', '/', + '8', '5', '2', '0', '*', '9', '6', '3', '.', '-', '+', '\0', + '\n', '\0', '\0', '\0', '\0', '\0', '\0','\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +static const int8_t HID_KEYBRD_ShiftKey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', + '+', '\0', '\0', '\0', 'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', + 'P', '{', '}', '*', '\0', 'Q', 'S', 'D', 'F', 'G', 'H', 'J', 'K', + 'L', 'M', '%', '\0', '\n', '\0', '\0', 'W', 'X', 'C', 'V', 'B', 'N', + '?', '.', '/', '\0', '\0', '\0','\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; +#endif + +static const uint8_t HID_KEYBRD_Codes[] = { + 0, 0, 0, 0, 31, 50, 48, 33, + 19, 34, 35, 36, 24, 37, 38, 39, /* 0x00 - 0x0F */ + 52, 51, 25, 26, 17, 20, 32, 21, + 23, 49, 18, 47, 22, 46, 2, 3, /* 0x10 - 0x1F */ + 4, 5, 6, 7, 8, 9, 10, 11, + 43, 110, 15, 16, 61, 12, 13, 27, /* 0x20 - 0x2F */ + 28, 29, 42, 40, 41, 1, 53, 54, + 55, 30, 112, 113, 114, 115, 116, 117, /* 0x30 - 0x3F */ + 118, 119, 120, 121, 122, 123, 124, 125, + 126, 75, 80, 85, 76, 81, 86, 89, /* 0x40 - 0x4F */ + 79, 84, 83, 90, 95, 100, 105, 106, + 108, 93, 98, 103, 92, 97, 102, 91, /* 0x50 - 0x5F */ + 96, 101, 99, 104, 45, 129, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7F */ + 0, 0, 0, 0, 0, 107, 0, 56, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xAF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 - 0xBF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xCF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xDF */ + 58, 44, 60, 127, 64, 57, 62, 128 /* 0xE0 - 0xE7 */ +}; + +/** + * @brief USBH_HID_KeybdInit + * The function init the HID keyboard. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_HID_KeybdInit(USBH_HandleTypeDef *phost) +{ + uint32_t x; + HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData; + + keybd_info.lctrl=keybd_info.lshift= 0; + keybd_info.lalt=keybd_info.lgui= 0; + keybd_info.rctrl=keybd_info.rshift= 0; + keybd_info.ralt=keybd_info.rgui=0; + + + for(x=0; x< (sizeof(keybd_report_data)/sizeof(uint32_t)); x++) + { + keybd_report_data[x]=0; + } + + if(HID_Handle->length > (sizeof(keybd_report_data)/sizeof(uint32_t))) + { + HID_Handle->length = (sizeof(keybd_report_data)/sizeof(uint32_t)); + } + HID_Handle->pData = (uint8_t*)keybd_report_data; + fifo_init(&HID_Handle->fifo, phost->device.Data, HID_QUEUE_SIZE * sizeof(keybd_report_data)); + + return USBH_OK; +} + +/** + * @brief USBH_HID_GetKeybdInfo + * The function return keyboard information. + * @param phost: Host handle + * @retval keyboard information + */ +HID_KEYBD_Info_TypeDef *USBH_HID_GetKeybdInfo(USBH_HandleTypeDef *phost) +{ + if(USBH_HID_KeybdDecode(phost) == USBH_OK) + { + return &keybd_info; + } + else + { + return NULL; + } +} + +/** + * @brief USBH_HID_KeybdDecode + * The function decode keyboard data. + * @param phost: Host handle + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_HID_KeybdDecode(USBH_HandleTypeDef *phost) +{ + uint8_t x; + + HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData; + if(HID_Handle->length == 0) + { + return USBH_FAIL; + } + /*Fill report */ + if(fifo_read(&HID_Handle->fifo, &keybd_report_data, HID_Handle->length) == HID_Handle->length) + { + + keybd_info.lctrl=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_lctrl, 0); + keybd_info.lshift=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_lshift, 0); + keybd_info.lalt=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_lalt, 0); + keybd_info.lgui=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_lgui, 0); + keybd_info.rctrl=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_rctrl, 0); + keybd_info.rshift=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_rshift, 0); + keybd_info.ralt=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_ralt, 0); + keybd_info.rgui=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_rgui, 0); + + for(x=0; x < sizeof(keybd_info.keys); x++) + { + keybd_info.keys[x]=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_key_array, x); + } + + return USBH_OK; + } + return USBH_FAIL; +} + +/** + * @brief USBH_HID_GetASCIICode + * The function decode keyboard data into ASCII characters. + * @param phost: Host handle + * @param info: Keyboard information + * @retval ASCII code + */ +uint8_t USBH_HID_GetASCIICode(HID_KEYBD_Info_TypeDef *info) +{ + uint8_t output; + if((info->lshift == 1) || (info->rshift)) + { + output = HID_KEYBRD_ShiftKey[HID_KEYBRD_Codes[info->keys[0]]]; + } + else + { + output = HID_KEYBRD_Key[HID_KEYBRD_Codes[info->keys[0]]]; + } + return output; +} +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/ports/stm32/usbh_hid_mouse.c b/ports/stm32/usbh_hid_mouse.c new file mode 100644 index 000000000000..cff7813c23c3 --- /dev/null +++ b/ports/stm32/usbh_hid_mouse.c @@ -0,0 +1,267 @@ +/** + ****************************************************************************** + * @file usbh_hid_mouse.c + * @author MCD Application Team + * @version V3.0.0 + * @date 18-February-2014 + * @brief This file is the application layer for USB Host HID Mouse Handling. + ****************************************************************************** + * @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 "usbh_hid_mouse.h" +#include "usbh_hid_parser.h" + + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_CLASS + * @{ + */ + +/** @addtogroup USBH_HID_CLASS + * @{ + */ + +/** @defgroup USBH_HID_MOUSE + * @brief This file includes HID Layer Handlers for USB Host HID class. + * @{ + */ + +/** @defgroup USBH_HID_MOUSE_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_HID_MOUSE_Private_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_HID_MOUSE_Private_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_HID_MOUSE_Private_FunctionPrototypes + * @{ + */ +static USBH_StatusTypeDef USBH_HID_MouseDecode(USBH_HandleTypeDef *phost); + +/** + * @} + */ + + +/** @defgroup USBH_HID_MOUSE_Private_Variables + * @{ + */ +HID_MOUSE_Info_TypeDef mouse_info; +uint32_t mouse_report_data[1]; + +/* Structures defining how to access items in a HID mouse report */ +/* Access button 1 state. */ +static const HID_Report_ItemTypedef prop_b1={ + (uint8_t *)mouse_report_data+0, /*data*/ + 1, /*size*/ + 0, /*shift*/ + 0, /*count (only for array items)*/ + 0, /*signed?*/ + 0, /*min value read can return*/ + 1, /*max value read can return*/ + 0, /*min value device can report*/ + 1, /*max value device can report*/ + 1 /*resolution*/ +}; + +/* Access button 2 state. */ +static const HID_Report_ItemTypedef prop_b2={ + (uint8_t *)mouse_report_data+0, /*data*/ + 1, /*size*/ + 1, /*shift*/ + 0, /*count (only for array items)*/ + 0, /*signed?*/ + 0, /*min value read can return*/ + 1, /*max value read can return*/ + 0, /*min value device can report*/ + 1, /*max value device can report*/ + 1 /*resolution*/ +}; + +/* Access button 3 state. */ +static const HID_Report_ItemTypedef prop_b3={ + (uint8_t *)mouse_report_data+0, /*data*/ + 1, /*size*/ + 2, /*shift*/ + 0, /*count (only for array items)*/ + 0, /*signed?*/ + 0, /*min value read can return*/ + 1, /*max value read can return*/ + 0, /*min vale device can report*/ + 1, /*max value device can report*/ + 1 /*resolution*/ +}; + +/* Access x coordinate change. */ +static const HID_Report_ItemTypedef prop_x={ + (uint8_t *)mouse_report_data+1, /*data*/ + 8, /*size*/ + 0, /*shift*/ + 0, /*count (only for array items)*/ + 1, /*signed?*/ + 0, /*min value read can return*/ + 0xFFFF,/*max value read can return*/ + 0, /*min vale device can report*/ + 0xFFFF,/*max value device can report*/ + 1 /*resolution*/ +}; + +/* Access y coordinate change. */ +static const HID_Report_ItemTypedef prop_y={ + (uint8_t *)mouse_report_data+2, /*data*/ + 8, /*size*/ + 0, /*shift*/ + 0, /*count (only for array items)*/ + 1, /*signed?*/ + 0, /*min value read can return*/ + 0xFFFF,/*max value read can return*/ + 0, /*min vale device can report*/ + 0xFFFF,/*max value device can report*/ + 1 /*resolution*/ +}; + + +/** + * @} + */ + + +/** @defgroup USBH_HID_MOUSE_Private_Functions + * @{ + */ + +/** + * @brief USBH_HID_MouseInit + * The function init the HID mouse. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_HID_MouseInit(USBH_HandleTypeDef *phost) +{ + HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData; + + mouse_info.x=0; + mouse_info.y=0; + mouse_info.buttons[0]=0; + mouse_info.buttons[1]=0; + mouse_info.buttons[2]=0; + + mouse_report_data[0]=0; + + if(HID_Handle->length > sizeof(mouse_report_data)) + { + HID_Handle->length = sizeof(mouse_report_data); + } + HID_Handle->pData = (uint8_t *)mouse_report_data; + fifo_init(&HID_Handle->fifo, phost->device.Data, HID_QUEUE_SIZE * sizeof(mouse_report_data)); + + return USBH_OK; +} + +/** + * @brief USBH_HID_GetMouseInfo + * The function return mouse information. + * @param phost: Host handle + * @retval mouse information + */ +HID_MOUSE_Info_TypeDef *USBH_HID_GetMouseInfo(USBH_HandleTypeDef *phost) +{ + if(USBH_HID_MouseDecode(phost)== USBH_OK) + { + return &mouse_info; + } + else + { + return NULL; + } +} + +/** + * @brief USBH_HID_MouseDecode + * The function decode mouse data. + * @param phost: Host handle + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_HID_MouseDecode(USBH_HandleTypeDef *phost) +{ + HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData; + + if(HID_Handle->length == 0) + { + return USBH_FAIL; + } + /*Fill report */ + if(fifo_read(&HID_Handle->fifo, &mouse_report_data, HID_Handle->length) == HID_Handle->length) + { + + /*Decode report */ + mouse_info.x = (int16_t )HID_ReadItem((HID_Report_ItemTypedef *) &prop_x, 0); + mouse_info.y = (int16_t )HID_ReadItem((HID_Report_ItemTypedef *) &prop_y, 0); + + mouse_info.buttons[0]=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &prop_b1, 0); + mouse_info.buttons[1]=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &prop_b2, 0); + mouse_info.buttons[2]=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &prop_b3, 0); + + return USBH_OK; + } + return USBH_FAIL; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbh_hid_parser.c b/ports/stm32/usbh_hid_parser.c new file mode 100644 index 000000000000..140473dce14d --- /dev/null +++ b/ports/stm32/usbh_hid_parser.c @@ -0,0 +1,235 @@ +/** + ****************************************************************************** + * @file usbh_hid_parser.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. + ****************************************************************************** + * @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 "usbh_hid_parser.h" + + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_CLASS + * @{ + */ + +/** @addtogroup USBH_HID_CLASS + * @{ + */ + +/** @defgroup USBH_HID_PARSER + * @brief This file includes HID parsers for USB Host HID class. + * @{ + */ + +/** @defgroup USBH_HID_PARSER_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_HID_PARSER_Private_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_HID_PARSER_Private_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_HID_PARSER_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBH_HID_PARSER_Private_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBH_HID_PARSER_Private_Functions + * @{ + */ + +/** + * @brief HID_ReadItem + * The function read a report item. + * @param ri: report item + * @param ndx: report index +* @retval status (0 : fail / otherwise: item value) + */ +uint32_t HID_ReadItem(HID_Report_ItemTypedef *ri, uint8_t ndx) +{ + uint32_t val=0; + uint32_t x=0; + uint32_t bofs; + uint8_t *data=ri->data; + uint8_t shift=ri->shift; + + /* get the logical value of the item */ + + /* if this is an array, wee may need to offset ri->data.*/ + if (ri->count > 0) + { + /* If app tries to read outside of the array. */ + if (ri->count <= ndx) + { + return(0); + } + + /* calculate bit offset */ + bofs = ndx*ri->size; + bofs += shift; + /* calculate byte offset + shift pair from bit offset. */ + data+=bofs/8; + shift=(uint8_t)(bofs%8); + } + /* read data bytes in little endian order */ + for(x=0; x < ((ri->size & 0x7) ? (ri->size/8)+1 : (ri->size/8)); x++) + { + val=(uint32_t)(*data << (x*8)); + } + val=(val >> shift) & ((1<size)-1); + + if (val < ri->logical_min || val > ri->logical_max) + { + return(0); + } + + /* convert logical value to physical value */ + /* See if the number is negative or not. */ + if ((ri->sign) && (val & (1<<(ri->size-1)))) + { + /* yes, so sign extend value to 32 bits. */ + int vs=(int)((-1 & ~((1<<(ri->size))-1)) | val); + + if(ri->resolution == 1) + { + return((uint32_t)vs); + } + return((uint32_t)(vs*ri->resolution)); + } + else + { + if(ri->resolution == 1) + { + return(val); + } + return(val*ri->resolution); + } +} + +/** + * @brief HID_WriteItem + * The function write a report item. + * @param ri: report item + * @param ndx: report index + * @retval status (1: fail/ 0 : Ok) + */ +uint32_t HID_WriteItem(HID_Report_ItemTypedef *ri, uint32_t value, uint8_t ndx) +{ + uint32_t x; + uint32_t mask; + uint32_t bofs; + uint8_t *data=ri->data; + uint8_t shift=ri->shift; + + if (value < ri->physical_min || value > ri->physical_max) + { + return(1); + } + + /* if this is an array, wee may need to offset ri->data.*/ + if (ri->count > 0) + { + /* If app tries to read outside of the array. */ + if (ri->count >= ndx) + { + return(0); + } + /* calculate bit offset */ + bofs = ndx*ri->size; + bofs += shift; + /* calculate byte offset + shift pair from bit offset. */ + data+=bofs/8; + shift=(uint8_t)(bofs%8); + + } + + /* Convert physical value to logical value. */ + if (ri->resolution != 1) + { + value=value/ri->resolution; + } + + /* Write logical value to report in little endian order. */ + mask=(uint32_t)((1<size)-1); + value = (value & mask) << shift; + + for(x=0; x < ((ri->size & 0x7) ? (ri->size/8)+1 : (ri->size/8)); x++) + { + *(ri->data+x)=(uint8_t)((*(ri->data+x) & ~(mask>>(x*8))) | ((value>>(x*8)) & (mask>>(x*8)))); + } + return(0); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbh_ioreq.c b/ports/stm32/usbh_ioreq.c new file mode 100644 index 000000000000..8c869eadb6a1 --- /dev/null +++ b/ports/stm32/usbh_ioreq.c @@ -0,0 +1,358 @@ +/** + ****************************************************************************** + * @file usbh_ioreq.c + * @author MCD Application Team + * @version V3.0.0 + * @date 18-February-2014 + * @brief This file handles the issuing of the USB transactions + ****************************************************************************** + * @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 "usbh_ioreq.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_IOREQ + * @brief This file handles the standard protocol processing (USB v2.0) + * @{ + */ + + +/** @defgroup USBH_IOREQ_Private_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + + +/** @defgroup USBH_IOREQ_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Private_Variables + * @{ + */ +/** + * @} + */ +/** @defgroup USBH_IOREQ_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Private_Functions + * @{ + */ + + + +/** + * @brief USBH_CtlSendSetup + * Sends the Setup Packet to the Device + * @param phost: Host Handle + * @param buff: Buffer pointer from which the Data will be send to Device + * @param pipe_num: Pipe Number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_CtlSendSetup (USBH_HandleTypeDef *phost, + uint8_t *buff, + uint8_t pipe_num) +{ + + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 0, /* Direction : OUT */ + USBH_EP_CONTROL, /* EP type */ + USBH_PID_SETUP, /* Type setup */ + buff, /* data buffer */ + USBH_SETUP_PKT_SIZE, /* data length */ + 0); + return USBH_OK; +} + + +/** + * @brief USBH_CtlSendData + * Sends a data Packet to the Device + * @param phost: Host Handle + * @param buff: Buffer pointer from which the Data will be sent to Device + * @param length: Length of the data to be sent + * @param pipe_num: Pipe Number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_CtlSendData (USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length, + uint8_t pipe_num, + uint8_t do_ping ) +{ + if(phost->device.speed != USBH_SPEED_HIGH) + { + do_ping = 0; + } + + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 0, /* Direction : OUT */ + USBH_EP_CONTROL, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + do_ping); /* do ping (HS Only)*/ + + return USBH_OK; +} + + +/** + * @brief USBH_CtlReceiveData + * Receives the Device Response to the Setup Packet + * @param phost: Host Handle + * @param buff: Buffer pointer in which the response needs to be copied + * @param length: Length of the data to be received + * @param pipe_num: Pipe Number + * @retval USBH Status. + */ +USBH_StatusTypeDef USBH_CtlReceiveData(USBH_HandleTypeDef *phost, + uint8_t* buff, + uint16_t length, + uint8_t pipe_num) +{ + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 1, /* Direction : IN */ + USBH_EP_CONTROL, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0); + return USBH_OK; + +} + + +/** + * @brief USBH_BulkSendData + * Sends the Bulk Packet to the device + * @param phost: Host Handle + * @param buff: Buffer pointer from which the Data will be sent to Device + * @param length: Length of the data to be sent + * @param pipe_num: Pipe Number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_BulkSendData (USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length, + uint8_t pipe_num, + uint8_t do_ping ) +{ + if(phost->device.speed != USBH_SPEED_HIGH) + { + do_ping = 0; + } + + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 0, /* Direction : IN */ + USBH_EP_BULK, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + do_ping); /* do ping (HS Only)*/ + return USBH_OK; +} + + +/** + * @brief USBH_BulkReceiveData + * Receives IN bulk packet from device + * @param phost: Host Handle + * @param buff: Buffer pointer in which the received data packet to be copied + * @param length: Length of the data to be received + * @param pipe_num: Pipe Number + * @retval USBH Status. + */ +USBH_StatusTypeDef USBH_BulkReceiveData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length, + uint8_t pipe_num) +{ + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 1, /* Direction : IN */ + USBH_EP_BULK, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0); + return USBH_OK; +} + + +/** + * @brief USBH_InterruptReceiveData + * Receives the Device Response to the Interrupt IN token + * @param phost: Host Handle + * @param buff: Buffer pointer in which the response needs to be copied + * @param length: Length of the data to be received + * @param pipe_num: Pipe Number + * @retval USBH Status. + */ +USBH_StatusTypeDef USBH_InterruptReceiveData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint8_t length, + uint8_t pipe_num) +{ + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 1, /* Direction : IN */ + USBH_EP_INTERRUPT, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0); + + return USBH_OK; +} + +/** + * @brief USBH_InterruptSendData + * Sends the data on Interrupt OUT Endpoint + * @param phost: Host Handle + * @param buff: Buffer pointer from where the data needs to be copied + * @param length: Length of the data to be sent + * @param pipe_num: Pipe Number + * @retval USBH Status. + */ +USBH_StatusTypeDef USBH_InterruptSendData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint8_t length, + uint8_t pipe_num) +{ + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 0, /* Direction : OUT */ + USBH_EP_INTERRUPT, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0); + + return USBH_OK; +} + +/** + * @brief USBH_IsocReceiveData + * Receives the Device Response to the Isochronous IN token + * @param phost: Host Handle + * @param buff: Buffer pointer in which the response needs to be copied + * @param length: Length of the data to be received + * @param pipe_num: Pipe Number + * @retval USBH Status. + */ +USBH_StatusTypeDef USBH_IsocReceiveData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint32_t length, + uint8_t pipe_num) +{ + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 1, /* Direction : IN */ + USBH_EP_ISO, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0); + + + return USBH_OK; +} + +/** + * @brief USBH_IsocSendData + * Sends the data on Isochronous OUT Endpoint + * @param phost: Host Handle + * @param buff: Buffer pointer from where the data needs to be copied + * @param length: Length of the data to be sent + * @param pipe_num: Pipe Number + * @retval USBH Status. + */ +USBH_StatusTypeDef USBH_IsocSendData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint32_t length, + uint8_t pipe_num) +{ + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 0, /* Direction : OUT */ + USBH_EP_ISO, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0); + + return USBH_OK; +} +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + diff --git a/ports/stm32/usbh_pipes.c b/ports/stm32/usbh_pipes.c new file mode 100644 index 000000000000..de20a0b3fd82 --- /dev/null +++ b/ports/stm32/usbh_pipes.c @@ -0,0 +1,204 @@ +/** + ****************************************************************************** + * @file usbh_pipes.c + * @author MCD Application Team + * @version V3.0.0 + * @date 18-February-2014 + * @brief This file implements functions for opening and closing Pipes + ****************************************************************************** + * @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 "usbh_pipes.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_PIPES + * @brief This file includes opening and closing Pipes + * @{ + */ + +/** @defgroup USBH_PIPES_Private_Defines + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_PIPES_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_PIPES_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_PIPES_Private_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBH_PIPES_Private_Functions + * @{ + */ +static uint16_t USBH_GetFreePipe (USBH_HandleTypeDef *phost); + + +/** + * @brief USBH_Open_Pipe + * Open a pipe + * @param phost: Host Handle + * @param pipe_num: Pipe Number + * @param dev_address: USB Device address allocated to attached device + * @param speed : USB device speed (Full/Low) + * @param ep_type: end point type (Bulk/int/ctl) + * @param mps: max pkt size + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_OpenPipe (USBH_HandleTypeDef *phost, + uint8_t pipe_num, + uint8_t epnum, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps) +{ + + USBH_LL_OpenPipe(phost, + pipe_num, + epnum, + dev_address, + speed, + ep_type, + mps); + + return USBH_OK; + +} + +/** + * @brief USBH_ClosePipe + * Close a pipe + * @param phost: Host Handle + * @param pipe_num: Pipe Number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_ClosePipe (USBH_HandleTypeDef *phost, + uint8_t pipe_num) +{ + + USBH_LL_ClosePipe(phost, pipe_num); + + return USBH_OK; + +} + +/** + * @brief USBH_Alloc_Pipe + * Allocate a new Pipe + * @param phost: Host Handle + * @param ep_addr: End point for which the Pipe to be allocated + * @retval Pipe number + */ +uint8_t USBH_AllocPipe (USBH_HandleTypeDef *phost, uint8_t ep_addr) +{ + uint16_t pipe; + + pipe = USBH_GetFreePipe(phost); + + if (pipe != 0xFFFF) + { + phost->Pipes[pipe] = 0x8000 | ep_addr; + } + return pipe; +} + +/** + * @brief USBH_Free_Pipe + * Free the USB Pipe + * @param phost: Host Handle + * @param idx: Pipe number to be freed + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_FreePipe (USBH_HandleTypeDef *phost, uint8_t idx) +{ + if(idx < 11) + { + phost->Pipes[idx] &= 0x7FFF; + } + return USBH_OK; +} + +/** + * @brief USBH_GetFreePipe + * @param phost: Host Handle + * Get a free Pipe number for allocation to a device endpoint + * @retval idx: Free Pipe number + */ +static uint16_t USBH_GetFreePipe (USBH_HandleTypeDef *phost) +{ + uint8_t idx = 0; + + for (idx = 0 ; idx < 11 ; idx++) + { + if ((phost->Pipes[idx] & 0x8000) == 0) + { + return idx; + } + } + return 0xFFFF; +} +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + diff --git a/ports/stm32/usbh_platform.c b/ports/stm32/usbh_platform.c new file mode 100644 index 000000000000..4e66eecd1299 --- /dev/null +++ b/ports/stm32/usbh_platform.c @@ -0,0 +1,54 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : usbh_platform.c + + * @brief : This file implements the USB platform + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_platform.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/** + * @brief Drive VBUS. + * @param state : VBUS state + * This parameter can be one of the these values: + * - 1 : VBUS Active + * - 0 : VBUS Inactive + */ +void MX_DriverVbusFS(uint8_t state) +{ + uint8_t data = state; + /* USER CODE BEGIN PREPARE_GPIO_DATA_VBUS_FS */ + if(state == 0) + { + /* Drive low Charge pump */ + data = GPIO_PIN_RESET; + } + else + { + /* Drive high Charge pump */ + data = GPIO_PIN_SET; + } + /* USER CODE END PREPARE_GPIO_DATA_VBUS_FS */ + HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,(GPIO_PinState)data); +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbhost/Class/HID/Inc/usbh_hid.h b/ports/stm32/usbhost/Class/HID/Inc/usbh_hid.h index 38302ad0d44b..437700eed177 100644 --- a/ports/stm32/usbhost/Class/HID/Inc/usbh_hid.h +++ b/ports/stm32/usbhost/Class/HID/Inc/usbh_hid.h @@ -106,16 +106,16 @@ /* 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_INIT_HOST= 0, + HID_IDLE_HOST, + HID_SEND_DATA_HOST, + HID_BUSY_HOST, + HID_GET_DATA_HOST, + HID_SYNC_HOST, + HID_POLL_HOST, + HID_ERROR_HOST, } -HID_StateTypeDef; +HID_Host_StateTypeDef; typedef enum { @@ -213,7 +213,7 @@ typedef struct _HID_Process { uint8_t OutPipe; uint8_t InPipe; - HID_StateTypeDef state; + HID_Host_StateTypeDef state; uint8_t OutEp; uint8_t InEp; HID_CtlStateTypeDef ctl_state; diff --git a/ports/stm32/usbhost/Class/HID/Src/usbh_hid.c b/ports/stm32/usbhost/Class/HID/Src/usbh_hid.c index a56f45c5c792..f52ee58d8368 100644 --- a/ports/stm32/usbhost/Class/HID/Src/usbh_hid.c +++ b/ports/stm32/usbhost/Class/HID/Src/usbh_hid.c @@ -156,7 +156,7 @@ static USBH_StatusTypeDef USBH_HID_InterfaceInit (USBH_HandleTypeDef *phost) USBH_SelectInterface (phost, interface); phost->pActiveClass->pData = (HID_HandleTypeDef *)USBH_malloc (sizeof(HID_HandleTypeDef)); HID_Handle = phost->pActiveClass->pData; - HID_Handle->state = HID_ERROR; + HID_Handle->state = HID_ERROR_HOST; /*Decode Bootclass Protocl: Mouse or Keyboard*/ if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol == HID_KEYBRD_BOOT_CODE) @@ -175,7 +175,7 @@ static USBH_StatusTypeDef USBH_HID_InterfaceInit (USBH_HandleTypeDef *phost) return USBH_FAIL; } - HID_Handle->state = HID_INIT; + HID_Handle->state = HID_INIT_HOST; 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; @@ -361,9 +361,9 @@ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost) switch (HID_Handle->state) { - case HID_INIT: + case HID_INIT_HOST: HID_Handle->Init(phost); - case HID_IDLE: + case HID_IDLE_HOST: if(USBH_HID_GetReport (phost, 0x01, 0, @@ -372,7 +372,7 @@ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost) { fifo_write(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length); - HID_Handle->state = HID_SYNC; + HID_Handle->state = HID_SYNC_HOST; } break; @@ -382,7 +382,7 @@ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost) /* Sync with start of Even Frame */ if(phost->Timer & 1) { - HID_Handle->state = HID_GET_DATA; + HID_Handle->state = HID_GET_DATA_HOST; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); @@ -396,7 +396,7 @@ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost) HID_Handle->length, HID_Handle->InPipe); - HID_Handle->state = HID_POLL; + HID_Handle->state = HID_POLL_HOST; HID_Handle->timer = phost->Timer; HID_Handle->DataReady = 0; break; @@ -446,11 +446,11 @@ static USBH_StatusTypeDef USBH_HID_SOFProcess(USBH_HandleTypeDef *phost) { HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData; - if(HID_Handle->state == HID_POLL) + if(HID_Handle->state == HID_POLL_HOST) { if(( phost->Timer - HID_Handle->timer) >= HID_Handle->poll) { - HID_Handle->state = HID_GET_DATA; + HID_Handle->state = HID_GET_DATA_HOST; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif diff --git a/ports/stm32/usbhost/Core/Inc/usb_host.h b/ports/stm32/usbhost/Core/Inc/usb_host.h new file mode 100644 index 000000000000..6f58f4034657 --- /dev/null +++ b/ports/stm32/usbhost/Core/Inc/usb_host.h @@ -0,0 +1,95 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : usb_host.h + * @version : v1.0_Cube + * @brief : Header for usb_host.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_HOST__H__ +#define __USB_HOST__H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" +#include "stm32f4xx_hal.h" +#include "usbh_def.h" +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/** @addtogroup USBH_OTG_DRIVER + * @{ + */ + +/** @defgroup USBH_HOST USBH_HOST + * @brief Host file for Usb otg low level driver. + * @{ + */ + +/** @defgroup USBH_HOST_Exported_Variables USBH_HOST_Exported_Variables + * @brief Public variables. + * @{ + */ + +/** + * @} + */ + +/** Status of the application. */ +typedef enum { + APPLICATION_IDLE = 0, + APPLICATION_START, + APPLICATION_READY, + APPLICATION_DISCONNECT +}ApplicationTypeDef; + +/** @defgroup USBH_HOST_Exported_FunctionsPrototype USBH_HOST_Exported_FunctionsPrototype + * @brief Declaration of public functions for Usb host. + * @{ + */ + +/* Exported functions -------------------------------------------------------*/ + +/** @brief USB Host initialization function. */ +void MX_USB_HOST_Init(void); +/* + * user callback declaration + */ +void USBH_UserProcess(USBH_HandleTypeDef *phost, uint8_t id); +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_HOST__H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbhost/Core/Inc/usbh_conf.h b/ports/stm32/usbhost/Core/Inc/usbh_conf.h new file mode 100644 index 000000000000..ef2aa0a5c2e6 --- /dev/null +++ b/ports/stm32/usbhost/Core/Inc/usbh_conf.h @@ -0,0 +1,195 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : Target/usbh_conf.h + * @version : v1.0_Cube + * @brief : Header for usbh_conf.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBH_CONF__H__ +#define __USBH_CONF__H__ +#ifdef __cplusplus + extern "C" { +#endif +/* Includes ------------------------------------------------------------------*/ + +#include +#include +#include +#include "usbh_main.h" +#include "stm32f4xx.h" +#include "stm32f4xx_hal.h" +#include "py/gc.h" +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/** @addtogroup STM32_USB_HOST_LIBRARY + * @{ + */ + +/** @defgroup USBH_CONF + * @brief usb host low level driver configuration file + * @{ + */ + +/** @defgroup USBH_CONF_Exported_Variables USBH_CONF_Exported_Variables + * @brief Public variables. + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBH_CONF_Exported_Defines USBH_CONF_Exported_Defines + * @brief Defines for configuration of the Usb host. + * @{ + */ + +/*---------- -----------*/ +#define USBH_MAX_NUM_ENDPOINTS 2U + +/*---------- -----------*/ +#define USBH_MAX_NUM_INTERFACES 2U + +/*---------- -----------*/ +#define USBH_MAX_NUM_CONFIGURATION 1U + +/*---------- -----------*/ +#define USBH_KEEP_CFG_DESCRIPTOR 1U + +/*---------- -----------*/ +#define USBH_MAX_NUM_SUPPORTED_CLASS 1U + +/*---------- -----------*/ +#define USBH_MAX_SIZE_CONFIGURATION 256U + +/*---------- -----------*/ +#define USBH_MAX_DATA_BUFFER 512U + +/*---------- -----------*/ +#define USBH_DEBUG_LEVEL 0U + +/*---------- -----------*/ +#define USBH_USE_OS 0 + +/****************************************/ +/* #define for FS and HS identification */ +#define HOST_HS 0 +#define HOST_FS 1 + +#if (USBH_USE_OS == 1) + #include "cmsis_os.h" + #define USBH_PROCESS_PRIO osPriorityNormal + #define USBH_PROCESS_STACK_SIZE ((uint16_t)128) +#endif /* (USBH_USE_OS == 1) */ + +/** + * @} + */ + +/** @defgroup USBH_CONF_Exported_Macros USBH_CONF_Exported_Macros + * @brief Aliases. + * @{ + */ + +/* Memory management macros */ + +/** Alias for memory allocation. */ +//#define USBH_malloc m_new + +/** Alias for memory release. */ +//#define USBH_free m_del + +/** Alias for memory set. */ +#define USBH_memset memset + +/** Alias for memory copy. */ +#define USBH_memcpy memcpy + +/* DEBUG macros */ + +#if (USBH_DEBUG_LEVEL > 0U) +#define USBH_UsrLog(...) do { \ + printf(__VA_ARGS__); \ + printf("\n"); \ +} while (0) +#else +#define USBH_UsrLog(...) do {} while (0) +#endif + +#if (USBH_DEBUG_LEVEL > 1U) + +#define USBH_ErrLog(...) do { \ + printf("ERROR: ") ; \ + printf(__VA_ARGS__); \ + printf("\n"); \ +} while (0) +#else +#define USBH_ErrLog(...) do {} while (0) +#endif + +#if (USBH_DEBUG_LEVEL > 2U) +#define USBH_DbgLog(...) do { \ + printf("DEBUG : ") ; \ + printf(__VA_ARGS__); \ + printf("\n"); \ +} while (0) +#else +#define USBH_DbgLog(...) do {} while (0) +#endif + +/** + * @} + */ + +/** @defgroup USBH_CONF_Exported_Types USBH_CONF_Exported_Types + * @brief Types. + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBH_CONF_Exported_FunctionsPrototype USBH_CONF_Exported_FunctionsPrototype + * @brief Declaration of public functions for Usb host. + * @{ + */ + +/* Exported functions -------------------------------------------------------*/ +void Error_Handler(void); +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_CONF__H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbhost/Core/Inc/usbh_core.h b/ports/stm32/usbhost/Core/Inc/usbh_core.h index bc3da6d1fe90..5bafdf76b3e2 100644 --- a/ports/stm32/usbhost/Core/Inc/usbh_core.h +++ b/ports/stm32/usbhost/Core/Inc/usbh_core.h @@ -138,6 +138,8 @@ uint8_t USBH_LL_GetToggle (USBH_HandleTypeDef *phost, uint8_t ); void USBH_Delay (uint32_t Delay); void USBH_LL_SetTimer (USBH_HandleTypeDef *phost, uint32_t ); void USBH_LL_IncTimer (USBH_HandleTypeDef *phost); +void USBH_LL_PortDisabled(USBH_HandleTypeDef *phost); +void USBH_LL_PortEnabled(USBH_HandleTypeDef *phost); /** * @} */ diff --git a/ports/stm32/usbhost/Core/Inc/usbh_def.h b/ports/stm32/usbhost/Core/Inc/usbh_def.h index cf24d69f3702..9015d829713b 100644 --- a/ports/stm32/usbhost/Core/Inc/usbh_def.h +++ b/ports/stm32/usbhost/Core/Inc/usbh_def.h @@ -418,6 +418,7 @@ typedef struct uint8_t Data[USBH_MAX_DATA_BUFFER]; uint8_t address; uint8_t speed; + uint8_t PortEnabled; __IO uint8_t is_connected; uint8_t current_interface; USBH_DevDescTypeDef DevDesc; diff --git a/ports/stm32/usbhost/Core/Inc/usbh_main.h b/ports/stm32/usbhost/Core/Inc/usbh_main.h new file mode 100644 index 000000000000..9012d5f3dc99 --- /dev/null +++ b/ports/stm32/usbhost/Core/Inc/usbh_main.h @@ -0,0 +1,271 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.h + * @brief : Header for main.c file. + * This file contains the common defines of the application. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __MAIN_H +#define __MAIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ +/* USER CODE BEGIN EC */ + +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ + +/* USER CODE END EM */ + +/* Exported functions prototypes ---------------------------------------------*/ +//void Error_Handler(void); + +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +/* Private defines -----------------------------------------------------------*/ +#define SAI1_FSA_Pin GPIO_PIN_4 +#define SAI1_FSA_GPIO_Port GPIOE +#define SPKR_HP_Pin GPIO_PIN_3 +#define SPKR_HP_GPIO_Port GPIOE +#define AUDIO_RST_Pin GPIO_PIN_2 +#define AUDIO_RST_GPIO_Port GPIOE +#define ARDUINO_USART6_TX_Pin GPIO_PIN_14 +#define ARDUINO_USART6_TX_GPIO_Port GPIOG +#define FMC_NBL1_Pin GPIO_PIN_1 +#define FMC_NBL1_GPIO_Port GPIOE +#define FMC_NBL0_Pin GPIO_PIN_0 +#define FMC_NBL0_GPIO_Port GPIOE +#define I2C1_SCL_Pin GPIO_PIN_8 +#define I2C1_SCL_GPIO_Port GPIOB +#define I2S3_CK_Pin GPIO_PIN_3 +#define I2S3_CK_GPIO_Port GPIOB +#define uSD_CLK_Pin GPIO_PIN_12 +#define uSD_CLK_GPIO_Port GPIOC +#define SWCLK_Pin GPIO_PIN_14 +#define SWCLK_GPIO_Port GPIOA +#define SWDIO_Pin GPIO_PIN_13 +#define SWDIO_GPIO_Port GPIOA +#define SAI1_SCKA_Pin GPIO_PIN_5 +#define SAI1_SCKA_GPIO_Port GPIOE +#define I2C1_SDA_Pin GPIO_PIN_9 +#define I2C1_SDA_GPIO_Port GPIOB +#define OTG_FS1_OverCurrent_Pin GPIO_PIN_7 +#define OTG_FS1_OverCurrent_GPIO_Port GPIOB +#define QSPI_BK1_NCS_Pin GPIO_PIN_6 +#define QSPI_BK1_NCS_GPIO_Port GPIOB +#define SDNCAS_Pin GPIO_PIN_15 +#define SDNCAS_GPIO_Port GPIOG +#define MIC_DATA_Pin GPIO_PIN_6 +#define MIC_DATA_GPIO_Port GPIOD +#define D2_Pin GPIO_PIN_0 +#define D2_GPIO_Port GPIOD +#define uSD_D3_Pin GPIO_PIN_11 +#define uSD_D3_GPIO_Port GPIOC +#define uSD_D2_Pin GPIO_PIN_10 +#define uSD_D2_GPIO_Port GPIOC +#define USB_FS1_P_Pin GPIO_PIN_12 +#define USB_FS1_P_GPIO_Port GPIOA +#define FMC_NBL2_Pin GPIO_PIN_4 +#define FMC_NBL2_GPIO_Port GPIOI +#define LED3_Pin GPIO_PIN_5 +#define LED3_GPIO_Port GPIOD +#define D3_Pin GPIO_PIN_1 +#define D3_GPIO_Port GPIOD +#define D27_Pin GPIO_PIN_3 +#define D27_GPIO_Port GPIOI +#define D26_Pin GPIO_PIN_2 +#define D26_GPIO_Port GPIOI +#define USB_FS1_N_Pin GPIO_PIN_11 +#define USB_FS1_N_GPIO_Port GPIOA +#define A0_Pin GPIO_PIN_0 +#define A0_GPIO_Port GPIOF +#define FMC_NBL3_Pin GPIO_PIN_5 +#define FMC_NBL3_GPIO_Port GPIOI +#define D29_Pin GPIO_PIN_7 +#define D29_GPIO_Port GPIOI +#define D31_Pin GPIO_PIN_10 +#define D31_GPIO_Port GPIOI +#define D28_Pin GPIO_PIN_6 +#define D28_GPIO_Port GPIOI +#define LED4_Pin GPIO_PIN_3 +#define LED4_GPIO_Port GPIOK +#define USART6_RX_Pin GPIO_PIN_9 +#define USART6_RX_GPIO_Port GPIOG +#define LED2_Pin GPIO_PIN_4 +#define LED2_GPIO_Port GPIOD +#define uSD_CMD_Pin GPIO_PIN_2 +#define uSD_CMD_GPIO_Port GPIOD +#define D23_Pin GPIO_PIN_15 +#define D23_GPIO_Port GPIOH +#define D25_Pin GPIO_PIN_1 +#define D25_GPIO_Port GPIOI +#define USB_FS1_ID_Pin GPIO_PIN_10 +#define USB_FS1_ID_GPIO_Port GPIOA +#define A1_Pin GPIO_PIN_1 +#define A1_GPIO_Port GPIOF +#define D30_Pin GPIO_PIN_9 +#define D30_GPIO_Port GPIOI +#define D21_Pin GPIO_PIN_13 +#define D21_GPIO_Port GPIOH +#define D22_Pin GPIO_PIN_14 +#define D22_GPIO_Port GPIOH +#define D24_Pin GPIO_PIN_0 +#define D24_GPIO_Port GPIOI +#define VBUS_FS1_Pin GPIO_PIN_9 +#define VBUS_FS1_GPIO_Port GPIOA +#define uSD_D1_Pin GPIO_PIN_9 +#define uSD_D1_GPIO_Port GPIOC +#define A2_Pin GPIO_PIN_2 +#define A2_GPIO_Port GPIOF +#define uSD_D0_Pin GPIO_PIN_8 +#define uSD_D0_GPIO_Port GPIOC +#define A3_Pin GPIO_PIN_3 +#define A3_GPIO_Port GPIOF +#define I2C2_SCL_Pin GPIO_PIN_4 +#define I2C2_SCL_GPIO_Port GPIOH +#define SDCLK_Pin GPIO_PIN_8 +#define SDCLK_GPIO_Port GPIOG +#define A4_Pin GPIO_PIN_4 +#define A4_GPIO_Port GPIOF +#define I2C2_SDA_Pin GPIO_PIN_5 +#define I2C2_SDA_GPIO_Port GPIOH +#define SDNE0_Pin GPIO_PIN_3 +#define SDNE0_GPIO_Port GPIOH +#define SAI1_MCLKA_Pin GPIO_PIN_7 +#define SAI1_MCLKA_GPIO_Port GPIOG +#define LED1_Pin GPIO_PIN_6 +#define LED1_GPIO_Port GPIOG +#define QSPI_BK1_IO2_Pin GPIO_PIN_7 +#define QSPI_BK1_IO2_GPIO_Port GPIOF +#define QSPI_BK1_IO3_Pin GPIO_PIN_6 +#define QSPI_BK1_IO3_GPIO_Port GPIOF +#define A5_Pin GPIO_PIN_5 +#define A5_GPIO_Port GPIOF +#define SDCKE0_Pin GPIO_PIN_2 +#define SDCKE0_GPIO_Port GPIOH +#define D1_Pin GPIO_PIN_15 +#define D1_GPIO_Port GPIOD +#define D15_Pin GPIO_PIN_10 +#define D15_GPIO_Port GPIOD +#define QSPI_CLK_Pin GPIO_PIN_10 +#define QSPI_CLK_GPIO_Port GPIOF +#define QSPI_BK1_IO1_Pin GPIO_PIN_9 +#define QSPI_BK1_IO1_GPIO_Port GPIOF +#define QSPI_BK1_IO0_Pin GPIO_PIN_8 +#define QSPI_BK1_IO0_GPIO_Port GPIOF +#define D0_Pin GPIO_PIN_14 +#define D0_GPIO_Port GPIOD +#define D14_Pin GPIO_PIN_9 +#define D14_GPIO_Port GPIOD +#define D13_Pin GPIO_PIN_8 +#define D13_GPIO_Port GPIOD +#define SDNWE_Pin GPIO_PIN_0 +#define SDNWE_GPIO_Port GPIOC +#define OTG_FS1_PowerSwitchOn_Pin GPIO_PIN_2 +#define OTG_FS1_PowerSwitchOn_GPIO_Port GPIOB +#define A6_Pin GPIO_PIN_12 +#define A6_GPIO_Port GPIOF +#define A11_Pin GPIO_PIN_1 +#define A11_GPIO_Port GPIOG +#define A9_Pin GPIO_PIN_15 +#define A9_GPIO_Port GPIOF +#define MIC_CK_Pin GPIO_PIN_13 +#define MIC_CK_GPIO_Port GPIOD +#define uSD_Detect_Pin GPIO_PIN_2 +#define uSD_Detect_GPIO_Port GPIOG +#define LCD_INT_Pin GPIO_PIN_5 +#define LCD_INT_GPIO_Port GPIOJ +#define D20_Pin GPIO_PIN_12 +#define D20_GPIO_Port GPIOH +#define WAKEUP_Pin GPIO_PIN_0 +#define WAKEUP_GPIO_Port GPIOA +#define A7_Pin GPIO_PIN_13 +#define A7_GPIO_Port GPIOF +#define A10_Pin GPIO_PIN_0 +#define A10_GPIO_Port GPIOG +#define D5_Pin GPIO_PIN_8 +#define D5_GPIO_Port GPIOE +#define D17_Pin GPIO_PIN_9 +#define D17_GPIO_Port GPIOH +#define D19_Pin GPIO_PIN_11 +#define D19_GPIO_Port GPIOH +#define A8_Pin GPIO_PIN_14 +#define A8_GPIO_Port GPIOF +#define DSI_TE_Pin GPIO_PIN_2 +#define DSI_TE_GPIO_Port GPIOJ +#define SDNMT48LC4M32B2B5_6A_RAS_RAS___Pin GPIO_PIN_11 +#define SDNMT48LC4M32B2B5_6A_RAS_RAS___GPIO_Port GPIOF +#define D6_Pin GPIO_PIN_9 +#define D6_GPIO_Port GPIOE +#define D8_Pin GPIO_PIN_11 +#define D8_GPIO_Port GPIOE +#define D11_Pin GPIO_PIN_14 +#define D11_GPIO_Port GPIOE +#define STLK_RX_Pin GPIO_PIN_10 +#define STLK_RX_GPIO_Port GPIOB +#define D16_Pin GPIO_PIN_8 +#define D16_GPIO_Port GPIOH +#define D18_Pin GPIO_PIN_10 +#define D18_GPIO_Port GPIOH +#define LCD_BL_CTRL_Pin GPIO_PIN_3 +#define LCD_BL_CTRL_GPIO_Port GPIOA +#define EXT_RESET_Pin GPIO_PIN_0 +#define EXT_RESET_GPIO_Port GPIOB +#define D4_Pin GPIO_PIN_7 +#define D4_GPIO_Port GPIOE +#define D7_Pin GPIO_PIN_10 +#define D7_GPIO_Port GPIOE +#define D9_Pin GPIO_PIN_12 +#define D9_GPIO_Port GPIOE +#define D12_Pin GPIO_PIN_15 +#define D12_GPIO_Port GPIOE +#define D10_Pin GPIO_PIN_13 +#define D10_GPIO_Port GPIOE +#define STLK_TX_Pin GPIO_PIN_11 +#define STLK_TX_GPIO_Port GPIOB +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MAIN_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbhost/Core/Inc/usbh_platform.h b/ports/stm32/usbhost/Core/Inc/usbh_platform.h new file mode 100644 index 000000000000..f6a920370732 --- /dev/null +++ b/ports/stm32/usbhost/Core/Inc/usbh_platform.h @@ -0,0 +1,44 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : usbh_platform.h + * @brief : Header for usbh_platform.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBH_PLATFORM_H__ +#define __USBH_PLATFORM_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usb_host.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +void MX_DriverVbusFS(uint8_t state); + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_PLATFORM_H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbhost/Core/Src/usbh_conf.c b/ports/stm32/usbhost/Core/Src/usbh_conf.c new file mode 100644 index 000000000000..871495a1e497 --- /dev/null +++ b/ports/stm32/usbhost/Core/Src/usbh_conf.c @@ -0,0 +1,553 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : Target/usbh_conf.c + * @version : v1.0_Cube + * @brief : This file implements the board support package for the USB host library + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_core.h" +#include "usbh_platform.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +HCD_HandleTypeDef hhcd_USB_OTG_FS; + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* USER CODE BEGIN PFP */ +/* Private function prototypes -----------------------------------------------*/ +USBH_StatusTypeDef USBH_Get_USB_Status(HAL_StatusTypeDef hal_status); + +/* USER CODE END PFP */ + +/* Private functions ---------------------------------------------------------*/ + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ +void Error_Handler(void) +{ + return; +} +/******************************************************************************* + LL Driver Callbacks (HCD -> USB Host Library) +*******************************************************************************/ +/* MSP Init */ + +void HAL_HCD_MspInit(HCD_HandleTypeDef* hcdHandle) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(hcdHandle->Instance==USB_OTG_FS) + { + /* USER CODE BEGIN USB_OTG_FS_MspInit 0 */ + + /* USER CODE END USB_OTG_FS_MspInit 0 */ + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**USB_OTG_FS GPIO Configuration + PA12 ------> USB_OTG_FS_DP + PA11 ------> USB_OTG_FS_DM + PA10 ------> USB_OTG_FS_ID + PA9 ------> USB_OTG_FS_VBUS + */ + GPIO_InitStruct.Pin = USB_FS1_P_Pin|USB_FS1_N_Pin|USB_FS1_ID_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = VBUS_FS1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(VBUS_FS1_GPIO_Port, &GPIO_InitStruct); + + /* Peripheral clock enable */ + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + + /* Peripheral interrupt init */ + HAL_NVIC_SetPriority(OTG_FS_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(OTG_FS_IRQn); + /* USER CODE BEGIN USB_OTG_FS_MspInit 1 */ + + /* USER CODE END USB_OTG_FS_MspInit 1 */ + } +} + +void HAL_HCD_MspDeInit(HCD_HandleTypeDef* hcdHandle) +{ + if(hcdHandle->Instance==USB_OTG_FS) + { + /* USER CODE BEGIN USB_OTG_FS_MspDeInit 0 */ + + /* USER CODE END USB_OTG_FS_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); + + /**USB_OTG_FS GPIO Configuration + PA12 ------> USB_OTG_FS_DP + PA11 ------> USB_OTG_FS_DM + PA10 ------> USB_OTG_FS_ID + PA9 ------> USB_OTG_FS_VBUS + */ + HAL_GPIO_DeInit(GPIOA, USB_FS1_P_Pin|USB_FS1_N_Pin|USB_FS1_ID_Pin|VBUS_FS1_Pin); + + /* Peripheral interrupt Deinit*/ + HAL_NVIC_DisableIRQ(OTG_FS_IRQn); + + /* USER CODE BEGIN USB_OTG_FS_MspDeInit 1 */ + + /* USER CODE END USB_OTG_FS_MspDeInit 1 */ + } +} + +/** + * @brief SOF callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_IncTimer(hhcd->pData); +} + +/** + * @brief SOF callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_Connect(hhcd->pData); +} + +/** + * @brief SOF callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_Disconnect(hhcd->pData); +} + +/** + * @brief Notify URB state change callback. + * @param hhcd: HCD handle + * @param chnum: channel number + * @param urb_state: state + * @retval None + */ +void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state) +{ + /* To be used with OS to sync URB state with the global state machine */ +#if (USBH_USE_OS == 1) + USBH_LL_NotifyURBChange(hhcd->pData); +#endif +} +/** +* @brief Port Port Enabled callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_PortEnabled(hhcd->pData); +} + +/** + * @brief Port Port Disabled callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_PortDisabled(hhcd->pData); +} + +/******************************************************************************* + LL Driver Interface (USB Host Library --> HCD) +*******************************************************************************/ + +/** + * @brief Initialize the low level portion of the host driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_Init(USBH_HandleTypeDef *phost) +{ + /* Init USB_IP */ + if (phost->id == HOST_FS) { + /* Link the driver to the stack. */ + hhcd_USB_OTG_FS.pData = phost; + phost->pData = &hhcd_USB_OTG_FS; + + hhcd_USB_OTG_FS.Instance = USB_OTG_FS; + hhcd_USB_OTG_FS.Init.Host_channels = 8; + hhcd_USB_OTG_FS.Init.speed = HCD_SPEED_FULL; + hhcd_USB_OTG_FS.Init.dma_enable = DISABLE; + hhcd_USB_OTG_FS.Init.phy_itface = HCD_PHY_EMBEDDED; + hhcd_USB_OTG_FS.Init.Sof_enable = DISABLE; + if (HAL_HCD_Init(&hhcd_USB_OTG_FS) != HAL_OK) + { + //Error_Handler( ); //ololo + return USBH_FAIL; + } + + USBH_LL_SetTimer(phost, HAL_HCD_GetCurrentFrame(&hhcd_USB_OTG_FS)); + } + return USBH_OK; +} + +/** + * @brief De-Initialize the low level portion of the host driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_DeInit(USBH_HandleTypeDef *phost) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_DeInit(phost->pData); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Start the low level portion of the host driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_Start(USBH_HandleTypeDef *phost) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_Start(phost->pData); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Stop the low level portion of the host driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_Stop(USBH_HandleTypeDef *phost) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_Stop(phost->pData); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Return the USB host speed from the low level driver. + * @param phost: Host handle + * @retval USBH speeds + */ +USBH_SpeedTypeDef USBH_LL_GetSpeed(USBH_HandleTypeDef *phost) +{ + USBH_SpeedTypeDef speed = USBH_SPEED_FULL; + + switch (HAL_HCD_GetCurrentSpeed(phost->pData)) + { + case 0 : + speed = USBH_SPEED_HIGH; + break; + + case 1 : + speed = USBH_SPEED_FULL; + break; + + case 2 : + speed = USBH_SPEED_LOW; + break; + + default: + speed = USBH_SPEED_FULL; + break; + } + return speed; +} + +/** + * @brief Reset the Host port of the low level driver. + * @param phost: Host handle + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_ResetPort(USBH_HandleTypeDef *phost) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_ResetPort(phost->pData); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Return the last transfered packet size. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval Packet size + */ +uint32_t USBH_LL_GetLastXferSize(USBH_HandleTypeDef *phost, uint8_t pipe) +{ + return HAL_HCD_HC_GetXferCount(phost->pData, pipe); +} + +/** + * @brief Open a pipe of the low level driver. + * @param phost: Host handle + * @param pipe_num: Pipe index + * @param epnum: Endpoint number + * @param dev_address: Device USB address + * @param speed: Device Speed + * @param ep_type: Endpoint type + * @param mps: Endpoint max packet size + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_OpenPipe(USBH_HandleTypeDef *phost, uint8_t pipe_num, uint8_t epnum, + uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_HC_Init(phost->pData, pipe_num, epnum, + dev_address, speed, ep_type, mps); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Close a pipe of the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval USBH status + */ +USBH_StatusTypeDef USBH_LL_ClosePipe(USBH_HandleTypeDef *phost, uint8_t pipe) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_HC_Halt(phost->pData, pipe); + + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Submit a new URB to the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * This parameter can be a value from 1 to 15 + * @param direction : Channel number + * This parameter can be one of the these values: + * 0 : Output + * 1 : Input + * @param ep_type : Endpoint Type + * This parameter can be one of the these values: + * @arg EP_TYPE_CTRL: Control type + * @arg EP_TYPE_ISOC: Isochrounous type + * @arg EP_TYPE_BULK: Bulk type + * @arg EP_TYPE_INTR: Interrupt type + * @param token : Endpoint Type + * This parameter can be one of the these values: + * @arg 0: PID_SETUP + * @arg 1: PID_DATA + * @param pbuff : pointer to URB data + * @param length : Length of URB data + * @param do_ping : activate do ping protocol (for high speed only) + * This parameter can be one of the these values: + * 0 : do ping inactive + * 1 : do ping active + * @retval Status + */ +USBH_StatusTypeDef USBH_LL_SubmitURB(USBH_HandleTypeDef *phost, uint8_t pipe, uint8_t direction, + uint8_t ep_type, uint8_t token, uint8_t *pbuff, uint16_t length, + uint8_t do_ping) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBH_StatusTypeDef usb_status = USBH_OK; + + hal_status = HAL_HCD_HC_SubmitRequest(phost->pData, pipe, direction , + ep_type, token, pbuff, length, + do_ping); + usb_status = USBH_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Get a URB state from the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * This parameter can be a value from 1 to 15 + * @retval URB state + * This parameter can be one of the these values: + * @arg URB_IDLE + * @arg URB_DONE + * @arg URB_NOTREADY + * @arg URB_NYET + * @arg URB_ERROR + * @arg URB_STALL + */ +USBH_URBStateTypeDef USBH_LL_GetURBState(USBH_HandleTypeDef *phost, uint8_t pipe) +{ + return (USBH_URBStateTypeDef)HAL_HCD_HC_GetURBState (phost->pData, pipe); +} + +/** + * @brief Drive VBUS. + * @param phost: Host handle + * @param state : VBUS state + * This parameter can be one of the these values: + * 0 : VBUS Inactive + * 1 : VBUS Active + * @retval Status + */ +USBH_StatusTypeDef USBH_LL_DriverVBUS(USBH_HandleTypeDef *phost, uint8_t state) +{ + if (phost->id == HOST_FS) { + MX_DriverVbusFS(state); + } + + /* USER CODE BEGIN 0 */ + + /* USER CODE END 0*/ + + HAL_Delay(200); + return USBH_OK; +} + +/** + * @brief Set toggle for a pipe. + * @param phost: Host handle + * @param pipe: Pipe index + * @param toggle: toggle (0/1) + * @retval Status + */ +USBH_StatusTypeDef USBH_LL_SetToggle(USBH_HandleTypeDef *phost, uint8_t pipe, uint8_t toggle) +{ + HCD_HandleTypeDef *pHandle; + pHandle = phost->pData; + + if(pHandle->hc[pipe].ep_is_in) + { + pHandle->hc[pipe].toggle_in = toggle; + } + else + { + pHandle->hc[pipe].toggle_out = toggle; + } + + return USBH_OK; +} + +/** + * @brief Return the current toggle of a pipe. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval toggle (0/1) + */ +uint8_t USBH_LL_GetToggle(USBH_HandleTypeDef *phost, uint8_t pipe) +{ + uint8_t toggle = 0; + HCD_HandleTypeDef *pHandle; + pHandle = phost->pData; + + if(pHandle->hc[pipe].ep_is_in) + { + toggle = pHandle->hc[pipe].toggle_in; + } + else + { + toggle = pHandle->hc[pipe].toggle_out; + } + return toggle; +} + +/** + * @brief Delay routine for the USB Host Library + * @param Delay: Delay in ms + * @retval None + */ +void USBH_Delay(uint32_t Delay) +{ + HAL_Delay(Delay); +} + +/** + * @brief Retuns the USB status depending on the HAL status: + * @param hal_status: HAL status + * @retval USB status + */ +USBH_StatusTypeDef USBH_Get_USB_Status(HAL_StatusTypeDef hal_status) +{ + USBH_StatusTypeDef usb_status = USBH_OK; + + switch (hal_status) + { + case HAL_OK : + usb_status = USBH_OK; + break; + case HAL_ERROR : + usb_status = USBH_FAIL; + break; + case HAL_BUSY : + usb_status = USBH_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBH_FAIL; + break; + default : + usb_status = USBH_FAIL; + break; + } + return usb_status; +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbhost/Core/Src/usbh_core.c b/ports/stm32/usbhost/Core/Src/usbh_core.c index 9d2727a89f92..96484f9d2183 100644 --- a/ports/stm32/usbhost/Core/Src/usbh_core.c +++ b/ports/stm32/usbhost/Core/Src/usbh_core.c @@ -806,6 +806,39 @@ void USBH_LL_IncTimer (USBH_HandleTypeDef *phost) USBH_HandleSof(phost); } +/** + * @brief USBH_PortEnabled + * Port Enabled + * @param phost: Host Handle + * @retval None + */ +void USBH_LL_PortEnabled(USBH_HandleTypeDef *phost) +{ + phost->device.PortEnabled = 1U; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_PORT_EVENT; +#if (osCMSIS < 0x20000U) + (void)osMessagePut(phost->os_event, phost->os_msg, 0U); +#else + (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL); +#endif +#endif + + return; +} +/** + * @brief USBH_LL_PortDisabled + * Port Disabled + * @param phost: Host Handle + * @retval None + */ +void USBH_LL_PortDisabled(USBH_HandleTypeDef *phost) +{ + phost->device.PortEnabled = 0U; + + return; +} /** * @brief USBH_HandleSof * Call SOF process From f89d71c95fe0d4e6c9fd6d4f63e62fb06d75ffbb Mon Sep 17 00:00:00 2001 From: hemi454 Date: Sun, 6 Jun 2021 13:30:23 +0300 Subject: [PATCH 03/13] Add keyboard events handling --- ports/stm32/usb.c | 35 ++++++++++++++++++++++++++++++++++- ports/stm32/usbh_core.c | 6 +++++- ports/stm32/usbh_hid.c | 6 ++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index ec1f8a13b61b..7c4315393f19 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -1019,11 +1019,44 @@ USBH_HandleTypeDef hUsbHostFS; //ApplicationTypeDef Appli_state = APPLICATION_IDLE; static int host_is_enabled = 0; +void INIT_TEST_LED_Usb() +{ + GPIO_InitTypeDef GPIO_InitStruct; + HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_RESET); + GPIO_InitStruct.Pin = GPIO_PIN_3; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOK, &GPIO_InitStruct); + +} + +void USBH_HID_EventCallback(USBH_HandleTypeDef *phost) +{ + HID_KEYBD_Info_TypeDef *keybd_info; + uint8_t keycode; + HID_HandleTypeDef *HID_Handle = + (HID_HandleTypeDef *) phost->pActiveClass->pData; + HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_RESET); + if (HID_Handle->Init == USBH_HID_KeybdInit) + { + keybd_info = USBH_HID_GetKeybdInfo(phost); + keycode = USBH_HID_GetASCIICode(keybd_info); + if(keycode != 0) + { + HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_SET); + } + } + else + { + USBH_HID_GetMouseInfo(phost); + } +} void pyb_usb_host_init(void) { if (!host_is_enabled) { // only init USBH once in the device's power-lifetime /* Init Host Library */ - //USBH_Init(&hUsbHostFS, USB_OTG_FS_CORE_ID, &USB_Host, &HID_cb, &USR_Callbacks); + INIT_TEST_LED_Usb(); USBH_Init(&hUsbHostFS, USBH_UserProcess, HOST_FS); USBH_RegisterClass(&hUsbHostFS, USBH_HID_CLASS); USBH_Start(&hUsbHostFS); diff --git a/ports/stm32/usbh_core.c b/ports/stm32/usbh_core.c index a363f968fbed..0aaab2f57f12 100644 --- a/ports/stm32/usbh_core.c +++ b/ports/stm32/usbh_core.c @@ -121,7 +121,11 @@ USBH_StatusTypeDef USBH_Init(USBH_HandleTypeDef *phost, void (*pUsrFunc)(USBH_H phost->os_event = osMessageCreate (osMessageQ(USBH_Queue), NULL); /*Create USB Host Task */ +#if defined (USBH_PROCESS_STACK_SIZE) + osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0, USBH_PROCESS_STACK_SIZE); +#else osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0, 8 * configMINIMAL_STACK_SIZE); +#endif phost->thread = osThreadCreate (osThread(USBH_Thread), phost); #endif @@ -830,7 +834,7 @@ USBH_StatusTypeDef USBH_LL_Connect (USBH_HandleTypeDef *phost) if(phost->gState == HOST_IDLE ) { phost->device.is_connected = 1; - phost->gState = HOST_IDLE ; +// phost->gState = HOST_IDLE ; if(phost->pUser != NULL) { diff --git a/ports/stm32/usbh_hid.c b/ports/stm32/usbh_hid.c index a80f6e36f56a..802a65b5ffec 100644 --- a/ports/stm32/usbh_hid.c +++ b/ports/stm32/usbh_hid.c @@ -770,6 +770,11 @@ uint16_t fifo_write(FIFO_TypeDef * f, const void * buf, uint16_t nbytes) * @param phost: Selected device * @retval None */ +__weak void USBH_HID_EventCallback(USBH_HandleTypeDef *phost) +{ + +} +/* void USBH_HID_EventCallback(USBH_HandleTypeDef *phost) { HID_KEYBD_Info_TypeDef *keybd_info; @@ -786,6 +791,7 @@ void USBH_HID_EventCallback(USBH_HandleTypeDef *phost) USBH_HID_GetMouseInfo(phost); } } +*/ /** * @} */ From e18ed46a7d4868c9da5c8ae53c8221bba6dda53b Mon Sep 17 00:00:00 2001 From: hemi454 Date: Sun, 6 Jun 2021 13:30:23 +0300 Subject: [PATCH 04/13] Add keyboard events handling --- ports/stm32/mphalport.c | 11 ++++----- ports/stm32/usb.c | 50 ++++++++++++++++++++++++++++++----------- ports/stm32/usb.h | 3 ++- ports/stm32/usbh_core.c | 6 ++++- ports/stm32/usbh_hid.c | 6 +++++ 5 files changed, 56 insertions(+), 20 deletions(-) diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index d2b2e275bf13..6fa57e4f970d 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -34,13 +34,14 @@ MP_WEAK uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { MP_WEAK int mp_hal_stdin_rx_chr(void) { for (;;) { #ifdef USE_HOST_MODE + keyboardKeyCode = 0; pyb_usb_host_process(); - int c = pyb_usb_host_get_keyboard(); - if (c != 0) { - return c; + if (keyboardKeyCode != 0) + { + return keyboardKeyCode; } #endif -/* + if (MP_STATE_PORT(pyb_stdio_uart) != NULL && uart_rx_any(MP_STATE_PORT(pyb_stdio_uart))) { return uart_rx_char(MP_STATE_PORT(pyb_stdio_uart)); } @@ -49,7 +50,7 @@ MP_WEAK int mp_hal_stdin_rx_chr(void) { return dupterm_c; } MICROPY_EVENT_POLL_HOOK -*/ + } } diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index ec1f8a13b61b..9ed75151c0df 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -1019,18 +1019,46 @@ USBH_HandleTypeDef hUsbHostFS; //ApplicationTypeDef Appli_state = APPLICATION_IDLE; static int host_is_enabled = 0; +void INIT_TEST_LED_Usb() +{ + GPIO_InitTypeDef GPIO_InitStruct; + HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_RESET); + GPIO_InitStruct.Pin = GPIO_PIN_3; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOK, &GPIO_InitStruct); + +} + +void USBH_HID_EventCallback(USBH_HandleTypeDef *phost) +{ + HID_KEYBD_Info_TypeDef *keybd_info; + HID_HandleTypeDef *HID_Handle = + (HID_HandleTypeDef *) phost->pActiveClass->pData; + HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_RESET); + if (HID_Handle->Init == USBH_HID_KeybdInit) + { + keybd_info = USBH_HID_GetKeybdInfo(phost); + keyboardKeyCode = USBH_HID_GetASCIICode(keybd_info); + if(keyboardKeyCode != 0) + { + HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_SET); + } + } + else + { + USBH_HID_GetMouseInfo(phost); + } +} void pyb_usb_host_init(void) { if (!host_is_enabled) { // only init USBH once in the device's power-lifetime /* Init Host Library */ - //USBH_Init(&hUsbHostFS, USB_OTG_FS_CORE_ID, &USB_Host, &HID_cb, &USR_Callbacks); + INIT_TEST_LED_Usb(); USBH_Init(&hUsbHostFS, USBH_UserProcess, HOST_FS); USBH_RegisterClass(&hUsbHostFS, USBH_HID_CLASS); USBH_Start(&hUsbHostFS); - while(1) - { - USBH_Process(&hUsbHostFS); - } } host_is_enabled = 1; } @@ -1038,15 +1066,11 @@ void pyb_usb_host_init(void) { void pyb_usb_host_process(void) { USBH_Process(&hUsbHostFS); } - -uint8_t usb_keyboard_key = 0; - -// TODO this is an ugly hack to get key presses -uint pyb_usb_host_get_keyboard(void) { - uint key = usb_keyboard_key; - usb_keyboard_key = 0; - return key; +/* +uint8_t pyb_usb_host_get_keyboard(void) { + return keyboardKeyCode; } +*/ /* void USR_MOUSE_Init(void) { led_state(4, 1); diff --git a/ports/stm32/usb.h b/ports/stm32/usb.h index 93b7a1271d88..08bffa026911 100644 --- a/ports/stm32/usb.h +++ b/ports/stm32/usb.h @@ -54,6 +54,7 @@ typedef enum { USB_PHY_HS_ID = 1, } USB_PHY_ID; +uint8_t keyboardKeyCode; typedef struct _pyb_usb_vcp_obj_t pyb_usb_vcp_obj_t; extern mp_uint_t pyb_usb_flags; @@ -78,6 +79,6 @@ void usb_vcp_attach_to_repl(const pyb_usb_vcp_obj_t *self, bool attached); void pyb_usb_host_init(void); void pyb_usb_host_process(void); -uint pyb_usb_host_get_keyboard(void); +uint8_t pyb_usb_host_get_keyboard(void); #endif // MICROPY_INCLUDED_STM32_USB_H diff --git a/ports/stm32/usbh_core.c b/ports/stm32/usbh_core.c index a363f968fbed..0aaab2f57f12 100644 --- a/ports/stm32/usbh_core.c +++ b/ports/stm32/usbh_core.c @@ -121,7 +121,11 @@ USBH_StatusTypeDef USBH_Init(USBH_HandleTypeDef *phost, void (*pUsrFunc)(USBH_H phost->os_event = osMessageCreate (osMessageQ(USBH_Queue), NULL); /*Create USB Host Task */ +#if defined (USBH_PROCESS_STACK_SIZE) + osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0, USBH_PROCESS_STACK_SIZE); +#else osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0, 8 * configMINIMAL_STACK_SIZE); +#endif phost->thread = osThreadCreate (osThread(USBH_Thread), phost); #endif @@ -830,7 +834,7 @@ USBH_StatusTypeDef USBH_LL_Connect (USBH_HandleTypeDef *phost) if(phost->gState == HOST_IDLE ) { phost->device.is_connected = 1; - phost->gState = HOST_IDLE ; +// phost->gState = HOST_IDLE ; if(phost->pUser != NULL) { diff --git a/ports/stm32/usbh_hid.c b/ports/stm32/usbh_hid.c index a80f6e36f56a..802a65b5ffec 100644 --- a/ports/stm32/usbh_hid.c +++ b/ports/stm32/usbh_hid.c @@ -770,6 +770,11 @@ uint16_t fifo_write(FIFO_TypeDef * f, const void * buf, uint16_t nbytes) * @param phost: Selected device * @retval None */ +__weak void USBH_HID_EventCallback(USBH_HandleTypeDef *phost) +{ + +} +/* void USBH_HID_EventCallback(USBH_HandleTypeDef *phost) { HID_KEYBD_Info_TypeDef *keybd_info; @@ -786,6 +791,7 @@ void USBH_HID_EventCallback(USBH_HandleTypeDef *phost) USBH_HID_GetMouseInfo(phost); } } +*/ /** * @} */ From 37ad1d8635bc12dbbb70ba9c2a6a46d282c93ce9 Mon Sep 17 00:00:00 2001 From: hemi454 Date: Thu, 10 Jun 2021 19:16:34 +0300 Subject: [PATCH 05/13] Enable UART REPL mode --- ports/stm32/main.c | 5 ++++- ports/stm32/usb.c | 6 +++--- ports/stm32/usb.h | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 709d53036829..2d7494391050 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -86,7 +86,10 @@ #if MICROPY_PY_THREAD STATIC pyb_thread_t pyb_thread_main; #endif - +#ifdef USE_HOST_MODE +#define MICROPY_HW_UART_REPL PYB_UART_3 +#define MICROPY_HW_UART_REPL_BAUD 115200 +#endif #if defined(MICROPY_HW_UART_REPL) #ifndef MICROPY_HW_UART_REPL_RXBUF #define MICROPY_HW_UART_REPL_RXBUF (260) diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 9ed75151c0df..a268d04474bb 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -441,9 +441,9 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * //pyb_usb_host_init(); // hardware configured for USB host mode - if (strcmp(mode_str, "host") == 0) + if (strcmp(mode_str, "HID_HOST") == 0) { - pyb_usb_host_init(); + pyb_usb_hid_host_init(); } else { @@ -1051,7 +1051,7 @@ void USBH_HID_EventCallback(USBH_HandleTypeDef *phost) USBH_HID_GetMouseInfo(phost); } } -void pyb_usb_host_init(void) { +void pyb_usb_hid_host_init(void) { if (!host_is_enabled) { // only init USBH once in the device's power-lifetime /* Init Host Library */ diff --git a/ports/stm32/usb.h b/ports/stm32/usb.h index 08bffa026911..25d027f339c0 100644 --- a/ports/stm32/usb.h +++ b/ports/stm32/usb.h @@ -77,7 +77,7 @@ int usb_vcp_recv_byte(uint8_t *c); // if a byte is available, return 1 and put t void usb_vcp_send_strn(const char* str, int len); void usb_vcp_attach_to_repl(const pyb_usb_vcp_obj_t *self, bool attached); -void pyb_usb_host_init(void); +void pyb_usb_hid_host_init(void); void pyb_usb_host_process(void); uint8_t pyb_usb_host_get_keyboard(void); From ddf158ce3ef748877c19aecb844fe3a19444ce2c Mon Sep 17 00:00:00 2001 From: hemi454 Date: Sat, 12 Jun 2021 00:37:32 +0300 Subject: [PATCH 06/13] Add cdc device support --- ports/stm32/Makefile | 3 +- ports/stm32/usb.c | 59 ++ ports/stm32/usb.h | 1 + ports/stm32/usbdev/class/inc/usbd_msc_scsi.h | 2 +- ports/stm32/usbh_cdc.c | 755 +++++++++++++++++++ ports/stm32/usbhost/Class/CDC/Src/usbh_cdc.c | 4 +- ports/stm32/usbhost/Class/HID/Inc/usbh_hid.h | 3 + 7 files changed, 823 insertions(+), 4 deletions(-) create mode 100644 ports/stm32/usbh_cdc.c diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 37c60e66c6dd..fd1fb997af8e 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -58,7 +58,7 @@ INC += -I$(TOP)/lib/cmsis/inc INC += -I$(CMSIS_DIR)/ INC += -I$(TOP)/$(HAL_DIR)/Inc INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/inc -INC += -I$(USBHOST_DIR)/Core/Inc -I$(USBHOST_DIR)/Class/HID/Inc +INC += -I$(USBHOST_DIR)/Core/Inc -I$(USBHOST_DIR)/Class/HID/Inc -I$(USBHOST_DIR)/Class/CDC/Inc INC += -Ilwip_inc # Basic Cortex-M flags @@ -267,6 +267,7 @@ SRC_C = \ usbh_pipes.c \ usbh_ctlreq.c\ usbh_ioreq.c \ + usbh_cdc.c \ mphalport.c \ mpthreadport.c \ irq.c \ diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index a268d04474bb..ce666e9b110f 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -444,6 +444,10 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * if (strcmp(mode_str, "HID_HOST") == 0) { pyb_usb_hid_host_init(); + } + else if (strcmp(mode_str, "CDC_HOST") == 0) + { + pyb_usb_cdc_host_init(); } else { @@ -1012,12 +1016,24 @@ const mp_obj_type_t pyb_usb_hid_type = { #include "usbh_hid_keybd.h" #include "usbh_hid_mouse.h" #include "usbh_hid.h" +#include "usbh_cdc.h" #include "usb_host.h" //__ALIGN_BEGIN USBH_HOST USB_Host __ALIGN_END ; /* USB Host core handle declaration */ USBH_HandleTypeDef hUsbHostFS; //ApplicationTypeDef Appli_state = APPLICATION_IDLE; static int host_is_enabled = 0; +#define BUFF_SIZE 64 +uint8_t CDC_RX_Buffer[BUFF_SIZE]; +uint8_t CDC_TX_Buffer[BUFF_SIZE]; + +typedef enum { + CDC_STATE_IDLE = 0, + CDC_SEND, + CDC_RECEIVE, +} CDC_StateTypedef; +CDC_StateTypedef CDC_STATE = CDC_STATE_IDLE; +extern USBH_StatusTypeDef usbResult; void INIT_TEST_LED_Usb() { @@ -1051,6 +1067,37 @@ void USBH_HID_EventCallback(USBH_HandleTypeDef *phost) USBH_HID_GetMouseInfo(phost); } } + +void USBH_CDC_Handle (void) +{ + uint8_t i = 0; + switch (CDC_STATE) + { + case CDC_STATE_IDLE: + { + USBH_CDC_Stop(&hUsbHostFS); + int len = sprintf ((char *)CDC_TX_Buffer, "DATA = %d", i); + if (USBH_CDC_Transmit (&hUsbHostFS, CDC_TX_Buffer, len) == USBH_OK) + { + CDC_STATE = CDC_RECEIVE; + } + i++; + break; + } + + case CDC_RECEIVE: + { + USBH_CDC_Stop(&hUsbHostFS); + usbResult = USBH_CDC_Receive(&hUsbHostFS, (uint8_t *) CDC_RX_Buffer, BUFF_SIZE); + HAL_Delay (1000); + CDC_STATE = CDC_IDLE; + } + + default: + break; + } +} + void pyb_usb_hid_host_init(void) { if (!host_is_enabled) { // only init USBH once in the device's power-lifetime @@ -1063,6 +1110,18 @@ void pyb_usb_hid_host_init(void) { host_is_enabled = 1; } +void pyb_usb_cdc_host_init(void) { + if (!host_is_enabled) { + // only init USBH once in the device's power-lifetime + /* Init Host Library */ + INIT_TEST_LED_Usb(); + USBH_Init(&hUsbHostFS, USBH_UserProcess, HOST_FS); + USBH_RegisterClass(&hUsbHostFS, USBH_CDC_CLASS); + USBH_Start(&hUsbHostFS); + } + host_is_enabled = 1; +} + void pyb_usb_host_process(void) { USBH_Process(&hUsbHostFS); } diff --git a/ports/stm32/usb.h b/ports/stm32/usb.h index 25d027f339c0..3554509fc60e 100644 --- a/ports/stm32/usb.h +++ b/ports/stm32/usb.h @@ -78,6 +78,7 @@ void usb_vcp_send_strn(const char* str, int len); void usb_vcp_attach_to_repl(const pyb_usb_vcp_obj_t *self, bool attached); void pyb_usb_hid_host_init(void); +void pyb_usb_cdc_host_init(void); void pyb_usb_host_process(void); uint8_t pyb_usb_host_get_keyboard(void); diff --git a/ports/stm32/usbdev/class/inc/usbd_msc_scsi.h b/ports/stm32/usbdev/class/inc/usbd_msc_scsi.h index b657cead09cb..f393afe5dc00 100644 --- a/ports/stm32/usbdev/class/inc/usbd_msc_scsi.h +++ b/ports/stm32/usbdev/class/inc/usbd_msc_scsi.h @@ -89,7 +89,7 @@ #define UNIT_ATTENTION 6 #define DATA_PROTECT 7 #define BLANK_CHECK 8 -#define VENDOR_SPECIFIC 9 +//#define VENDOR_SPECIFIC 9 #define COPY_ABORTED 10 #define ABORTED_COMMAND 11 #define VOLUME_OVERFLOW 13 diff --git a/ports/stm32/usbh_cdc.c b/ports/stm32/usbh_cdc.c new file mode 100644 index 000000000000..43ba4594377d --- /dev/null +++ b/ports/stm32/usbh_cdc.c @@ -0,0 +1,755 @@ +/** + ****************************************************************************** + * @file usbh_cdc.c + * @author MCD Application Team + * @version V3.0.0 + * @date 18-February-2014 + * @brief This file is the CDC Layer Handlers for USB Host CDC class. + * + * @verbatim + * + * =================================================================== + * CDC Class Description + * =================================================================== + * This module manages the MSC class V1.11 following the "Device Class Definition + * for Human Interface Devices (CDC) 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 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 "usbh_cdc.h" + +/** @addtogroup USBH_LIB +* @{ +*/ + +/** @addtogroup USBH_CLASS +* @{ +*/ + +/** @addtogroup USBH_CDC_CLASS +* @{ +*/ + +/** @defgroup USBH_CDC_CORE +* @brief This file includes CDC Layer Handlers for USB Host CDC class. +* @{ +*/ + +/** @defgroup USBH_CDC_CORE_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_CDC_CORE_Private_Defines +* @{ +*/ +#define USBH_CDC_BUFFER_SIZE 1024 +/** +* @} +*/ + + +/** @defgroup USBH_CDC_CORE_Private_Macros +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_CDC_CORE_Private_Variables +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_CDC_CORE_Private_FunctionPrototypes +* @{ +*/ + +static USBH_StatusTypeDef USBH_CDC_InterfaceInit (USBH_HandleTypeDef *phost); + +static USBH_StatusTypeDef USBH_CDC_InterfaceDeInit (USBH_HandleTypeDef *phost); + +static USBH_StatusTypeDef USBH_CDC_Process(USBH_HandleTypeDef *phost); + +static USBH_StatusTypeDef USBH_CDC_SOFProcess(USBH_HandleTypeDef *phost); + +static USBH_StatusTypeDef USBH_CDC_ClassRequest (USBH_HandleTypeDef *phost); + +static USBH_StatusTypeDef GetLineCoding(USBH_HandleTypeDef *phost, + CDC_LineCodingTypeDef *linecoding); + +static USBH_StatusTypeDef SetLineCoding(USBH_HandleTypeDef *phost, + CDC_LineCodingTypeDef *linecoding); + +static void CDC_ProcessTransmission(USBH_HandleTypeDef *phost); + +static void CDC_ProcessReception(USBH_HandleTypeDef *phost); + +USBH_ClassTypeDef CDC_Class = +{ + "CDC", + USB_CDC_CLASS, + USBH_CDC_InterfaceInit, + USBH_CDC_InterfaceDeInit, + USBH_CDC_ClassRequest, + USBH_CDC_Process, + USBH_CDC_SOFProcess, + NULL, +}; +/** +* @} +*/ + + +/** @defgroup USBH_CDC_CORE_Private_Functions +* @{ +*/ + +/** + * @brief USBH_CDC_InterfaceInit + * The function init the CDC class. + * @param phost: Host handle + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_CDC_InterfaceInit (USBH_HandleTypeDef *phost) +{ + + USBH_StatusTypeDef status = USBH_FAIL ; + uint8_t interface; + CDC_HandleTypeDef *CDC_Handle; + + interface = USBH_FindInterface(phost, + COMMUNICATION_INTERFACE_CLASS_CODE, + ABSTRACT_CONTROL_MODEL, + COMMON_AT_COMMAND); + + if(interface == 0xFF) /* No Valid Interface */ + { + USBH_DbgLog ("Cannot Find the interface for Communication Interface Class.", phost->pActiveClass->Name); + } + else + { + USBH_SelectInterface (phost, interface); + phost->pActiveClass->pData = (CDC_HandleTypeDef *)m_new (CDC_HandleTypeDef, 1); + CDC_Handle = phost->pActiveClass->pData; + + /*Collect the notification endpoint address and length*/ + if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80) + { + CDC_Handle->CommItf.NotifEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress; + CDC_Handle->CommItf.NotifEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; + } + + /*Allocate the length for host channel number in*/ + CDC_Handle->CommItf.NotifPipe = USBH_AllocPipe(phost, CDC_Handle->CommItf.NotifEp); + + /* Open pipe for Notification endpoint */ + USBH_OpenPipe (phost, + CDC_Handle->CommItf.NotifPipe, + CDC_Handle->CommItf.NotifEp, + phost->device.address, + phost->device.speed, + USB_EP_TYPE_INTR, + CDC_Handle->CommItf.NotifEpSize); + + USBH_LL_SetToggle (phost, CDC_Handle->CommItf.NotifPipe, 0); + + interface = USBH_FindInterface(phost, + DATA_INTERFACE_CLASS_CODE, + RESERVED, + NO_CLASS_SPECIFIC_PROTOCOL_CODE); + + if(interface == 0xFF) /* No Valid Interface */ + { + USBH_DbgLog ("Cannot Find the interface for Data Interface Class.", phost->pActiveClass->Name); + } + else + { + /*Collect the class specific endpoint address and length*/ + if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80) + { + CDC_Handle->DataItf.InEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress; + CDC_Handle->DataItf.InEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; + } + else + { + CDC_Handle->DataItf.OutEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress; + CDC_Handle->DataItf.OutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; + } + + if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress & 0x80) + { + CDC_Handle->DataItf.InEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress; + CDC_Handle->DataItf.InEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].wMaxPacketSize; + } + else + { + CDC_Handle->DataItf.OutEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress; + CDC_Handle->DataItf.OutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].wMaxPacketSize; + } + + /*Allocate the length for host channel number out*/ + CDC_Handle->DataItf.OutPipe = USBH_AllocPipe(phost, CDC_Handle->DataItf.OutEp); + + /*Allocate the length for host channel number in*/ + CDC_Handle->DataItf.InPipe = USBH_AllocPipe(phost, CDC_Handle->DataItf.InEp); + + /* Open channel for OUT endpoint */ + USBH_OpenPipe (phost, + CDC_Handle->DataItf.OutPipe, + CDC_Handle->DataItf.OutEp, + phost->device.address, + phost->device.speed, + USB_EP_TYPE_BULK, + CDC_Handle->DataItf.OutEpSize); + /* Open channel for IN endpoint */ + USBH_OpenPipe (phost, + CDC_Handle->DataItf.InPipe, + CDC_Handle->DataItf.InEp, + phost->device.address, + phost->device.speed, + USB_EP_TYPE_BULK, + CDC_Handle->DataItf.InEpSize); + + CDC_Handle->state = CDC_IDLE_STATE; + + USBH_LL_SetToggle (phost, CDC_Handle->DataItf.OutPipe,0); + USBH_LL_SetToggle (phost, CDC_Handle->DataItf.InPipe,0); + status = USBH_OK; + } + } + return status; +} + + + +/** + * @brief USBH_CDC_InterfaceDeInit + * The function DeInit the Pipes used for the CDC class. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_CDC_InterfaceDeInit (USBH_HandleTypeDef *phost) +{ + CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; + + if ( CDC_Handle->CommItf.NotifPipe) + { + USBH_ClosePipe(phost, CDC_Handle->CommItf.NotifPipe); + USBH_FreePipe (phost, CDC_Handle->CommItf.NotifPipe); + CDC_Handle->CommItf.NotifPipe = 0; /* Reset the Channel as Free */ + } + + if ( CDC_Handle->DataItf.InPipe) + { + USBH_ClosePipe(phost, CDC_Handle->DataItf.InPipe); + USBH_FreePipe (phost, CDC_Handle->DataItf.InPipe); + CDC_Handle->DataItf.InPipe = 0; /* Reset the Channel as Free */ + } + + if ( CDC_Handle->DataItf.OutPipe) + { + USBH_ClosePipe(phost, CDC_Handle->DataItf.OutPipe); + USBH_FreePipe (phost, CDC_Handle->DataItf.OutPipe); + CDC_Handle->DataItf.OutPipe = 0; /* Reset the Channel as Free */ + } + + if(phost->pActiveClass->pData) + { + m_free (phost->pActiveClass->pData); + phost->pActiveClass->pData = 0; + } + + return USBH_OK; +} + +/** + * @brief USBH_CDC_ClassRequest + * The function is responsible for handling Standard requests + * for CDC class. + * @param phost: Host handle + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_CDC_ClassRequest (USBH_HandleTypeDef *phost) +{ + USBH_StatusTypeDef status = USBH_FAIL ; + CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; + + /*Issue the get line coding request*/ + status = GetLineCoding(phost, &CDC_Handle->LineCoding); + if(status == USBH_OK) + { + phost->pUser(phost, HOST_USER_CLASS_ACTIVE); + } + return status; +} + + +/** + * @brief USBH_CDC_Process + * The function is for managing state machine for CDC data transfers + * @param phost: Host handle + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_CDC_Process (USBH_HandleTypeDef *phost) +{ + USBH_StatusTypeDef status = USBH_BUSY; + USBH_StatusTypeDef req_status = USBH_OK; + CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; + + switch(CDC_Handle->state) + { + + case CDC_IDLE_STATE: + status = USBH_OK; + break; + + case CDC_SET_LINE_CODING_STATE: + req_status = SetLineCoding(phost, CDC_Handle->pUserLineCoding); + + if(req_status == USBH_OK) + { + CDC_Handle->state = CDC_GET_LAST_LINE_CODING_STATE; + } + + else if(req_status != USBH_BUSY) + { + CDC_Handle->state = CDC_ERROR_STATE; + } + break; + + + case CDC_GET_LAST_LINE_CODING_STATE: + req_status = GetLineCoding(phost, &(CDC_Handle->LineCoding)); + + if(req_status == USBH_OK) + { + CDC_Handle->state = CDC_IDLE_STATE; + + if((CDC_Handle->LineCoding.b.bCharFormat == CDC_Handle->pUserLineCoding->b.bCharFormat) && + (CDC_Handle->LineCoding.b.bDataBits == CDC_Handle->pUserLineCoding->b.bDataBits) && + (CDC_Handle->LineCoding.b.bParityType == CDC_Handle->pUserLineCoding->b.bParityType) && + (CDC_Handle->LineCoding.b.dwDTERate == CDC_Handle->pUserLineCoding->b.dwDTERate)) + { + USBH_CDC_LineCodingChanged(phost); + } + } + + else if(req_status != USBH_BUSY) + { + CDC_Handle->state = CDC_ERROR_STATE; + } + + break; + + case CDC_TRANSFER_DATA: + CDC_ProcessTransmission(phost); + CDC_ProcessReception(phost); + break; + + case CDC_ERROR_STATE: + req_status = USBH_ClrFeature(phost, 0x00); + + if(req_status == USBH_OK ) + { + /*Change the state to waiting*/ + CDC_Handle->state = CDC_IDLE_STATE ; + } + break; + + default: + break; + + } + + return status; +} + +/** + * @brief USBH_CDC_SOFProcess + * The function is for managing SOF callback + * @param phost: Host handle + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_CDC_SOFProcess (USBH_HandleTypeDef *phost) +{ + return USBH_OK; +} + + + /** + * @brief USBH_CDC_Stop + * Stop current CDC Transmission + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_CDC_Stop(USBH_HandleTypeDef *phost) +{ + CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; + + if(phost->gState == HOST_CLASS) + { + CDC_Handle->state = CDC_IDLE_STATE; + + USBH_ClosePipe(phost, CDC_Handle->CommItf.NotifPipe); + USBH_ClosePipe(phost, CDC_Handle->DataItf.InPipe); + USBH_ClosePipe(phost, CDC_Handle->DataItf.OutPipe); + } + return USBH_OK; +} +/** + * @brief This request allows the host to find out the currently + * configured line coding. + * @param pdev: Selected device + * @retval USBH_StatusTypeDef : USB ctl xfer status + */ +static USBH_StatusTypeDef GetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecoding) +{ + + phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_TYPE_CLASS | \ + USB_REQ_RECIPIENT_INTERFACE; + + phost->Control.setup.b.bRequest = CDC_GET_LINE_CODING; + phost->Control.setup.b.wValue.w = 0; + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = LINE_CODING_STRUCTURE_SIZE; + + return USBH_CtlReq(phost, linecoding->Array, LINE_CODING_STRUCTURE_SIZE); +} + + +/** + * @brief This request allows the host to specify typical asynchronous + * line-character formatting properties + * This request applies to asynchronous byte stream data class interfaces + * and endpoints + * @param pdev: Selected device + * @retval USBH_StatusTypeDef : USB ctl xfer status + */ +static USBH_StatusTypeDef SetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecodin) +{ + phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_TYPE_CLASS | \ + USB_REQ_RECIPIENT_INTERFACE; + + phost->Control.setup.b.bRequest = CDC_SET_LINE_CODING; + phost->Control.setup.b.wValue.w = 0; + + phost->Control.setup.b.wIndex.w = 0; + + phost->Control.setup.b.wLength.w = LINE_CODING_STRUCTURE_SIZE; + + return USBH_CtlReq(phost, linecodin->Array , LINE_CODING_STRUCTURE_SIZE ); +} + +/** +* @brief This function prepares the state before issuing the class specific commands +* @param None +* @retval None +*/ +USBH_StatusTypeDef USBH_CDC_SetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecodin) +{ + CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; + if(phost->gState == HOST_CLASS) + { + CDC_Handle->state = CDC_SET_LINE_CODING_STATE; + CDC_Handle->pUserLineCoding = linecodin; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0); +#endif + } + return USBH_OK; +} + +/** +* @brief This function prepares the state before issuing the class specific commands +* @param None +* @retval None +*/ +USBH_StatusTypeDef USBH_CDC_GetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecodin) +{ + CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; + + if((phost->gState == HOST_CLASS) ||(phost->gState == HOST_CLASS_REQUEST)) + { + *linecodin = CDC_Handle->LineCoding; + return USBH_OK; + } + else + { + return USBH_FAIL; + } +} + +/** + * @brief This function return last recieved data size + * @param None + * @retval None + */ +uint16_t USBH_CDC_GetLastReceivedDataSize(USBH_HandleTypeDef *phost) +{ + CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; + + if(phost->gState == HOST_CLASS) + { + return USBH_LL_GetLastXferSize(phost, CDC_Handle->DataItf.InPipe);; + } + else + { + return 0; + } +} + +/** + * @brief This function prepares the state before issuing the class specific commands + * @param None + * @retval None + */ +USBH_StatusTypeDef USBH_CDC_Transmit(USBH_HandleTypeDef *phost, uint8_t *pbuff, uint32_t length) +{ + USBH_StatusTypeDef Status = USBH_BUSY; + CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; + + if((CDC_Handle->state == CDC_IDLE_STATE) || (CDC_Handle->state == CDC_TRANSFER_DATA)) + { + CDC_Handle->pTxData = pbuff; + CDC_Handle->TxDataLength = length; + CDC_Handle->state = CDC_TRANSFER_DATA; + CDC_Handle->data_tx_state = CDC_SEND_DATA; + Status = USBH_OK; + } + return Status; +} + + +/** +* @brief This function prepares the state before issuing the class specific commands +* @param None +* @retval None +*/ +USBH_StatusTypeDef USBH_CDC_Receive(USBH_HandleTypeDef *phost, uint8_t *pbuff, uint32_t length) +{ + USBH_StatusTypeDef Status = USBH_BUSY; + CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; + + if((CDC_Handle->state == CDC_IDLE_STATE) || (CDC_Handle->state == CDC_TRANSFER_DATA)) + { + CDC_Handle->pRxData = pbuff; + CDC_Handle->RxDataLength = length; + CDC_Handle->state = CDC_TRANSFER_DATA; + CDC_Handle->data_rx_state = CDC_RECEIVE_DATA; + Status = USBH_OK; + } + return Status; +} + +/** +* @brief The function is responsible for sending data to the device +* @param pdev: Selected device +* @retval None +*/ +static void CDC_ProcessTransmission(USBH_HandleTypeDef *phost) +{ + CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; + USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE; + + switch(CDC_Handle->data_tx_state) + { + + case CDC_SEND_DATA: + if(CDC_Handle->TxDataLength > CDC_Handle->DataItf.OutEpSize) + { + USBH_BulkSendData (phost, + CDC_Handle->pTxData, + CDC_Handle->DataItf.OutEpSize, + CDC_Handle->DataItf.OutPipe, + 1); + } + else + { + USBH_BulkSendData (phost, + CDC_Handle->pTxData, + CDC_Handle->TxDataLength, + CDC_Handle->DataItf.OutPipe, + 1); + } + + CDC_Handle->data_tx_state = CDC_SEND_DATA_WAIT; + + break; + + case CDC_SEND_DATA_WAIT: + + URB_Status = USBH_LL_GetURBState(phost, CDC_Handle->DataItf.OutPipe); + + /*Check the status done for transmssion*/ + if(URB_Status == USBH_URB_DONE ) + { + if(CDC_Handle->TxDataLength > CDC_Handle->DataItf.OutEpSize) + { + CDC_Handle->TxDataLength -= CDC_Handle->DataItf.OutEpSize ; + CDC_Handle->pTxData += CDC_Handle->DataItf.OutEpSize; + } + else + { + CDC_Handle->TxDataLength = 0; + } + + if( CDC_Handle->TxDataLength > 0) + { + CDC_Handle->data_tx_state = CDC_SEND_DATA; + } + else + { + CDC_Handle->data_tx_state = CDC_IDLE; + USBH_CDC_TransmitCallback(phost); + + } + } + else if( URB_Status == USBH_URB_NOTREADY ) + { + CDC_Handle->data_tx_state = CDC_SEND_DATA; + } + break; + default: + break; + } +} +/** +* @brief This function responsible for reception of data from the device +* @param pdev: Selected device +* @retval None +*/ + +static void CDC_ProcessReception(USBH_HandleTypeDef *phost) +{ + CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; + USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE; + uint16_t length; + + switch(CDC_Handle->data_rx_state) + { + + case CDC_RECEIVE_DATA: + + USBH_BulkReceiveData (phost, + CDC_Handle->pRxData, + CDC_Handle->DataItf.InEpSize, + CDC_Handle->DataItf.InPipe); + + CDC_Handle->data_rx_state = CDC_RECEIVE_DATA_WAIT; + + break; + + case CDC_RECEIVE_DATA_WAIT: + + URB_Status = USBH_LL_GetURBState(phost, CDC_Handle->DataItf.InPipe); + + /*Check the status done for reception*/ + if(URB_Status == USBH_URB_DONE ) + { + length = USBH_LL_GetLastXferSize(phost, CDC_Handle->DataItf.InPipe); + + if(((CDC_Handle->RxDataLength - length) > 0) && (length > CDC_Handle->DataItf.InEpSize)) + { + CDC_Handle->RxDataLength -= length ; + CDC_Handle->pRxData += length; + CDC_Handle->data_rx_state = CDC_RECEIVE_DATA; + } + else + { + CDC_Handle->data_rx_state = CDC_IDLE; + USBH_CDC_ReceiveCallback(phost); + } + } + break; + + default: + break; + } +} + +/** +* @brief The function informs user that data have been received +* @param pdev: Selected device +* @retval None +*/ +__weak void USBH_CDC_TransmitCallback(USBH_HandleTypeDef *phost) +{ + +} + + /** +* @brief The function informs user that data have been sent +* @param pdev: Selected device +* @retval None +*/ +__weak void USBH_CDC_ReceiveCallback(USBH_HandleTypeDef *phost) +{ + +} + + /** +* @brief The function informs user that Settings have been changed +* @param pdev: Selected device +* @retval None +*/ +__weak void USBH_CDC_LineCodingChanged(USBH_HandleTypeDef *phost) +{ + +} + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + + +/** +* @} +*/ + + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbhost/Class/CDC/Src/usbh_cdc.c b/ports/stm32/usbhost/Class/CDC/Src/usbh_cdc.c index 250e1fc7bf0c..a4401e7b14ef 100644 --- a/ports/stm32/usbhost/Class/CDC/Src/usbh_cdc.c +++ b/ports/stm32/usbhost/Class/CDC/Src/usbh_cdc.c @@ -161,7 +161,7 @@ static USBH_StatusTypeDef USBH_CDC_InterfaceInit (USBH_HandleTypeDef *phost) else { USBH_SelectInterface (phost, interface); - phost->pActiveClass->pData = (CDC_HandleTypeDef *)USBH_malloc (sizeof(CDC_HandleTypeDef)); + phost->pActiveClass->pData = (CDC_HandleTypeDef *)m_new (sizeof(CDC_HandleTypeDef)); CDC_Handle = phost->pActiveClass->pData; /*Collect the notification endpoint address and length*/ @@ -287,7 +287,7 @@ USBH_StatusTypeDef USBH_CDC_InterfaceDeInit (USBH_HandleTypeDef *phost) if(phost->pActiveClass->pData) { - USBH_free (phost->pActiveClass->pData); + m_free (phost->pActiveClass->pData); phost->pActiveClass->pData = 0; } diff --git a/ports/stm32/usbhost/Class/HID/Inc/usbh_hid.h b/ports/stm32/usbhost/Class/HID/Inc/usbh_hid.h index 437700eed177..4726e0e937a9 100644 --- a/ports/stm32/usbhost/Class/HID/Inc/usbh_hid.h +++ b/ports/stm32/usbhost/Class/HID/Inc/usbh_hid.h @@ -272,6 +272,9 @@ HID_HandleTypeDef; */ extern USBH_ClassTypeDef HID_Class; #define USBH_HID_CLASS &HID_Class + +extern USBH_ClassTypeDef CDC_Class; +#define USBH_CDC_CLASS &CDC_Class /** * @} */ From b0318640f67a4fb8024f53a42efe05c3eeba5a07 Mon Sep 17 00:00:00 2001 From: hemi454 Date: Sat, 12 Jun 2021 21:34:20 +0300 Subject: [PATCH 07/13] Convert cdc class into ccid --- ports/stm32/boards/STM32F469DISC/mpconfigboard.h | 2 ++ ports/stm32/main.c | 2 +- ports/stm32/usb.c | 4 ++++ ports/stm32/usbh_cdc.c | 6 +++--- ports/stm32/usbhost/Class/CDC/Inc/usbh_cdc.h | 5 ++--- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/ports/stm32/boards/STM32F469DISC/mpconfigboard.h b/ports/stm32/boards/STM32F469DISC/mpconfigboard.h index fb939d63e4be..66d1f6651e14 100644 --- a/ports/stm32/boards/STM32F469DISC/mpconfigboard.h +++ b/ports/stm32/boards/STM32F469DISC/mpconfigboard.h @@ -140,3 +140,5 @@ extern struct _spi_bdev_t spi_bdev; #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) #define USE_HOST_MODE (1) +#define USB_HID_HOST_MODE (1) + diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 2d7494391050..db99a57e2410 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -86,7 +86,7 @@ #if MICROPY_PY_THREAD STATIC pyb_thread_t pyb_thread_main; #endif -#ifdef USE_HOST_MODE +#ifdef USB_HID_HOST_MODE #define MICROPY_HW_UART_REPL PYB_UART_3 #define MICROPY_HW_UART_REPL_BAUD 115200 #endif diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index ce666e9b110f..56596a2ce793 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -1118,6 +1118,10 @@ void pyb_usb_cdc_host_init(void) { USBH_Init(&hUsbHostFS, USBH_UserProcess, HOST_FS); USBH_RegisterClass(&hUsbHostFS, USBH_CDC_CLASS); USBH_Start(&hUsbHostFS); + while(1) + { + pyb_usb_host_process(); + } } host_is_enabled = 1; } diff --git a/ports/stm32/usbh_cdc.c b/ports/stm32/usbh_cdc.c index 43ba4594377d..8d443e21c973 100644 --- a/ports/stm32/usbh_cdc.c +++ b/ports/stm32/usbh_cdc.c @@ -151,8 +151,8 @@ static USBH_StatusTypeDef USBH_CDC_InterfaceInit (USBH_HandleTypeDef *phost) interface = USBH_FindInterface(phost, COMMUNICATION_INTERFACE_CLASS_CODE, - ABSTRACT_CONTROL_MODEL, - COMMON_AT_COMMAND); + 0xFF, + 0xFF); if(interface == 0xFF) /* No Valid Interface */ { @@ -186,7 +186,7 @@ static USBH_StatusTypeDef USBH_CDC_InterfaceInit (USBH_HandleTypeDef *phost) USBH_LL_SetToggle (phost, CDC_Handle->CommItf.NotifPipe, 0); interface = USBH_FindInterface(phost, - DATA_INTERFACE_CLASS_CODE, + USB_CDC_CLASS, RESERVED, NO_CLASS_SPECIFIC_PROTOCOL_CODE); diff --git a/ports/stm32/usbhost/Class/CDC/Inc/usbh_cdc.h b/ports/stm32/usbhost/Class/CDC/Inc/usbh_cdc.h index df11bfddac41..3b81ff9d2360 100644 --- a/ports/stm32/usbhost/Class/CDC/Inc/usbh_cdc.h +++ b/ports/stm32/usbhost/Class/CDC/Inc/usbh_cdc.h @@ -54,9 +54,8 @@ /*Communication Class codes*/ -#define USB_CDC_CLASS 0x02 -#define COMMUNICATION_INTERFACE_CLASS_CODE 0x02 - +#define USB_CDC_CLASS 0x0b +#define COMMUNICATION_INTERFACE_CLASS_CODE 0x0b /*Data Interface Class Codes*/ #define DATA_INTERFACE_CLASS_CODE 0x0A From 365023da41a4e88608b4d44f6a37429aaa0f1a08 Mon Sep 17 00:00:00 2001 From: hemi454 Date: Sun, 13 Jun 2021 22:54:09 +0300 Subject: [PATCH 08/13] Add proper endpoints for CCID class --- ports/stm32/usbh_cdc.c | 175 +++++++------------ ports/stm32/usbh_core.c | 2 +- ports/stm32/usbhost/Class/CDC/Inc/usbh_cdc.h | 6 +- ports/stm32/usbhost/Core/Inc/usbh_conf.h | 2 +- 4 files changed, 63 insertions(+), 122 deletions(-) diff --git a/ports/stm32/usbh_cdc.c b/ports/stm32/usbh_cdc.c index 8d443e21c973..24288823a503 100644 --- a/ports/stm32/usbh_cdc.c +++ b/ports/stm32/usbh_cdc.c @@ -165,10 +165,16 @@ static USBH_StatusTypeDef USBH_CDC_InterfaceInit (USBH_HandleTypeDef *phost) CDC_Handle = phost->pActiveClass->pData; /*Collect the notification endpoint address and length*/ - if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80) + for(int i = 0; i < USBH_MAX_NUM_ENDPOINTS; i++) { - CDC_Handle->CommItf.NotifEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress; - CDC_Handle->CommItf.NotifEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; + if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[i].bEndpointAddress & 0x80) + { + if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[i].bmAttributes == USB_EP_TYPE_INTR) + { + CDC_Handle->CommItf.NotifEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress; + CDC_Handle->CommItf.NotifEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; + } + } } /*Allocate the length for host channel number in*/ @@ -195,30 +201,28 @@ static USBH_StatusTypeDef USBH_CDC_InterfaceInit (USBH_HandleTypeDef *phost) USBH_DbgLog ("Cannot Find the interface for Data Interface Class.", phost->pActiveClass->Name); } else - { - /*Collect the class specific endpoint address and length*/ - if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80) - { - CDC_Handle->DataItf.InEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress; - CDC_Handle->DataItf.InEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; - } - else - { - CDC_Handle->DataItf.OutEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress; - CDC_Handle->DataItf.OutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; - } - - if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress & 0x80) - { - CDC_Handle->DataItf.InEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress; - CDC_Handle->DataItf.InEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].wMaxPacketSize; + { + for(int i = 0; i < USBH_MAX_NUM_ENDPOINTS; i++) + { + /*Collect the class specific endpoint address and length*/ + if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[i].bEndpointAddress & 0x80) + { + if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[i].bmAttributes == USB_EP_TYPE_BULK) + { + CDC_Handle->DataItf.InEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[i].bEndpointAddress; + CDC_Handle->DataItf.InEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[i].wMaxPacketSize; + } + } + else + { + if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[i].bmAttributes == USB_EP_TYPE_BULK) + { + CDC_Handle->DataItf.OutEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[i].bEndpointAddress; + CDC_Handle->DataItf.OutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[i].wMaxPacketSize; + } + } } - else - { - CDC_Handle->DataItf.OutEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress; - CDC_Handle->DataItf.OutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].wMaxPacketSize; - } - + /*Allocate the length for host channel number out*/ CDC_Handle->DataItf.OutPipe = USBH_AllocPipe(phost, CDC_Handle->DataItf.OutEp); @@ -303,19 +307,12 @@ USBH_StatusTypeDef USBH_CDC_InterfaceDeInit (USBH_HandleTypeDef *phost) */ static USBH_StatusTypeDef USBH_CDC_ClassRequest (USBH_HandleTypeDef *phost) { - USBH_StatusTypeDef status = USBH_FAIL ; + USBH_StatusTypeDef status = USBH_OK; CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; - - /*Issue the get line coding request*/ - status = GetLineCoding(phost, &CDC_Handle->LineCoding); - if(status == USBH_OK) - { - phost->pUser(phost, HOST_USER_CLASS_ACTIVE); - } return status; } - + uint8_t rawRxData[8] = {}; /** * @brief USBH_CDC_Process * The function is for managing state machine for CDC data transfers @@ -327,69 +324,37 @@ static USBH_StatusTypeDef USBH_CDC_Process (USBH_HandleTypeDef *phost) USBH_StatusTypeDef status = USBH_BUSY; USBH_StatusTypeDef req_status = USBH_OK; CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; - switch(CDC_Handle->state) { - - case CDC_IDLE_STATE: - status = USBH_OK; - break; - - case CDC_SET_LINE_CODING_STATE: - req_status = SetLineCoding(phost, CDC_Handle->pUserLineCoding); - - if(req_status == USBH_OK) - { - CDC_Handle->state = CDC_GET_LAST_LINE_CODING_STATE; - } - - else if(req_status != USBH_BUSY) - { - CDC_Handle->state = CDC_ERROR_STATE; - } - break; - - - case CDC_GET_LAST_LINE_CODING_STATE: - req_status = GetLineCoding(phost, &(CDC_Handle->LineCoding)); - - if(req_status == USBH_OK) - { - CDC_Handle->state = CDC_IDLE_STATE; + case CDC_IDLE_STATE: + status = USBH_OK; + CDC_Handle->state = CCID_GET_DATA_HOST; + break; + + case CCID_GET_DATA_HOST: + USBH_InterruptReceiveData(phost, + rawRxData, + 8, + CDC_Handle->CommItf.NotifPipe); + break; + + case CDC_TRANSFER_DATA: + CDC_ProcessTransmission(phost); + CDC_ProcessReception(phost); + break; - if((CDC_Handle->LineCoding.b.bCharFormat == CDC_Handle->pUserLineCoding->b.bCharFormat) && - (CDC_Handle->LineCoding.b.bDataBits == CDC_Handle->pUserLineCoding->b.bDataBits) && - (CDC_Handle->LineCoding.b.bParityType == CDC_Handle->pUserLineCoding->b.bParityType) && - (CDC_Handle->LineCoding.b.dwDTERate == CDC_Handle->pUserLineCoding->b.dwDTERate)) - { - USBH_CDC_LineCodingChanged(phost); - } - } - - else if(req_status != USBH_BUSY) - { - CDC_Handle->state = CDC_ERROR_STATE; - } - - break; - - case CDC_TRANSFER_DATA: - CDC_ProcessTransmission(phost); - CDC_ProcessReception(phost); - break; - - case CDC_ERROR_STATE: - req_status = USBH_ClrFeature(phost, 0x00); - - if(req_status == USBH_OK ) - { - /*Change the state to waiting*/ - CDC_Handle->state = CDC_IDLE_STATE ; - } - break; - - default: - break; + case CDC_ERROR_STATE: + req_status = USBH_ClrFeature(phost, 0x00); + + if(req_status == USBH_OK ) + { + /*Change the state to waiting*/ + CDC_Handle->state = CDC_IDLE_STATE ; + } + break; + + default: + break; } @@ -472,26 +437,6 @@ static USBH_StatusTypeDef SetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodin return USBH_CtlReq(phost, linecodin->Array , LINE_CODING_STRUCTURE_SIZE ); } -/** -* @brief This function prepares the state before issuing the class specific commands -* @param None -* @retval None -*/ -USBH_StatusTypeDef USBH_CDC_SetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecodin) -{ - CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; - if(phost->gState == HOST_CLASS) - { - CDC_Handle->state = CDC_SET_LINE_CODING_STATE; - CDC_Handle->pUserLineCoding = linecodin; - -#if (USBH_USE_OS == 1) - osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0); -#endif - } - return USBH_OK; -} - /** * @brief This function prepares the state before issuing the class specific commands * @param None diff --git a/ports/stm32/usbh_core.c b/ports/stm32/usbh_core.c index 0aaab2f57f12..985d8b848c82 100644 --- a/ports/stm32/usbh_core.c +++ b/ports/stm32/usbh_core.c @@ -620,7 +620,7 @@ static USBH_StatusTypeDef USBH_HandleEnum (USBH_HandleTypeDef *phost) { case ENUM_IDLE: /* Get Device Desc for only 1st 8 bytes : To get EP0 MaxPacketSize */ - if ( USBH_Get_DevDesc(phost, 8) == USBH_OK) + if ( USBH_Get_DevDesc(phost, 9) == USBH_OK) { phost->Control.pipe_size = phost->device.DevDesc.bMaxPacketSize; diff --git a/ports/stm32/usbhost/Class/CDC/Inc/usbh_cdc.h b/ports/stm32/usbhost/Class/CDC/Inc/usbh_cdc.h index 3b81ff9d2360..2899bc21c061 100644 --- a/ports/stm32/usbhost/Class/CDC/Inc/usbh_cdc.h +++ b/ports/stm32/usbhost/Class/CDC/Inc/usbh_cdc.h @@ -151,8 +151,7 @@ CDC_DataStateTypeDef; typedef enum { CDC_IDLE_STATE= 0, - CDC_SET_LINE_CODING_STATE, - CDC_GET_LAST_LINE_CODING_STATE, + CCID_GET_DATA_HOST, CDC_TRANSFER_DATA, CDC_ERROR_STATE, } @@ -397,9 +396,6 @@ extern USBH_ClassTypeDef CDC_Class; * @{ */ -USBH_StatusTypeDef USBH_CDC_SetLineCoding(USBH_HandleTypeDef *phost, - CDC_LineCodingTypeDef *linecoding); - USBH_StatusTypeDef USBH_CDC_GetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecoding); diff --git a/ports/stm32/usbhost/Core/Inc/usbh_conf.h b/ports/stm32/usbhost/Core/Inc/usbh_conf.h index ef2aa0a5c2e6..b9ae49a01beb 100644 --- a/ports/stm32/usbhost/Core/Inc/usbh_conf.h +++ b/ports/stm32/usbhost/Core/Inc/usbh_conf.h @@ -62,7 +62,7 @@ */ /*---------- -----------*/ -#define USBH_MAX_NUM_ENDPOINTS 2U +#define USBH_MAX_NUM_ENDPOINTS 3U /*---------- -----------*/ #define USBH_MAX_NUM_INTERFACES 2U From 05488001329c2e8bcea77b62eb9729776b06a6a4 Mon Sep 17 00:00:00 2001 From: hemi454 Date: Sun, 13 Jun 2021 22:54:09 +0300 Subject: [PATCH 09/13] Add proper endpoints for CCID class --- ports/stm32/usbh_cdc.c | 190 ++++++++----------- ports/stm32/usbh_core.c | 2 +- ports/stm32/usbhost/Class/CDC/Inc/usbh_cdc.h | 6 +- ports/stm32/usbhost/Core/Inc/usbh_conf.h | 2 +- 4 files changed, 77 insertions(+), 123 deletions(-) diff --git a/ports/stm32/usbh_cdc.c b/ports/stm32/usbh_cdc.c index 8d443e21c973..d71783db4607 100644 --- a/ports/stm32/usbh_cdc.c +++ b/ports/stm32/usbh_cdc.c @@ -165,10 +165,16 @@ static USBH_StatusTypeDef USBH_CDC_InterfaceInit (USBH_HandleTypeDef *phost) CDC_Handle = phost->pActiveClass->pData; /*Collect the notification endpoint address and length*/ - if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80) + for(int i = 0; i < USBH_MAX_NUM_ENDPOINTS; i++) { - CDC_Handle->CommItf.NotifEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress; - CDC_Handle->CommItf.NotifEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; + if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[i].bEndpointAddress & 0x80) + { + if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[i].bmAttributes == USB_EP_TYPE_INTR) + { + CDC_Handle->CommItf.NotifEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress; + CDC_Handle->CommItf.NotifEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; + } + } } /*Allocate the length for host channel number in*/ @@ -195,30 +201,28 @@ static USBH_StatusTypeDef USBH_CDC_InterfaceInit (USBH_HandleTypeDef *phost) USBH_DbgLog ("Cannot Find the interface for Data Interface Class.", phost->pActiveClass->Name); } else - { - /*Collect the class specific endpoint address and length*/ - if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80) - { - CDC_Handle->DataItf.InEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress; - CDC_Handle->DataItf.InEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; - } - else - { - CDC_Handle->DataItf.OutEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress; - CDC_Handle->DataItf.OutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; - } - - if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress & 0x80) - { - CDC_Handle->DataItf.InEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress; - CDC_Handle->DataItf.InEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].wMaxPacketSize; + { + for(int i = 0; i < USBH_MAX_NUM_ENDPOINTS; i++) + { + /*Collect the class specific endpoint address and length*/ + if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[i].bEndpointAddress & 0x80) + { + if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[i].bmAttributes == USB_EP_TYPE_BULK) + { + CDC_Handle->DataItf.InEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[i].bEndpointAddress; + CDC_Handle->DataItf.InEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[i].wMaxPacketSize; + } + } + else + { + if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[i].bmAttributes == USB_EP_TYPE_BULK) + { + CDC_Handle->DataItf.OutEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[i].bEndpointAddress; + CDC_Handle->DataItf.OutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[i].wMaxPacketSize; + } + } } - else - { - CDC_Handle->DataItf.OutEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress; - CDC_Handle->DataItf.OutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].wMaxPacketSize; - } - + /*Allocate the length for host channel number out*/ CDC_Handle->DataItf.OutPipe = USBH_AllocPipe(phost, CDC_Handle->DataItf.OutEp); @@ -303,19 +307,17 @@ USBH_StatusTypeDef USBH_CDC_InterfaceDeInit (USBH_HandleTypeDef *phost) */ static USBH_StatusTypeDef USBH_CDC_ClassRequest (USBH_HandleTypeDef *phost) { - USBH_StatusTypeDef status = USBH_FAIL ; + USBH_StatusTypeDef status = USBH_OK; CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; - - /*Issue the get line coding request*/ - status = GetLineCoding(phost, &CDC_Handle->LineCoding); - if(status == USBH_OK) - { - phost->pUser(phost, HOST_USER_CLASS_ACTIVE); - } return status; } - + uint8_t rawRxData[64] = {}; + unsigned char cmd[10]; + #define BUFF_SIZE 64 +uint8_t CDC_RX_Buffer[BUFF_SIZE]; +uint8_t CDC_TX_Buffer[BUFF_SIZE]; + int pbSeq; /** * @brief USBH_CDC_Process * The function is for managing state machine for CDC data transfers @@ -326,70 +328,46 @@ static USBH_StatusTypeDef USBH_CDC_Process (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_BUSY; USBH_StatusTypeDef req_status = USBH_OK; - CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; - + CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; + cmd[0] = 0x62; /* IccPowerOn */ + cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */ + cmd[5] = 0; /* slot number */ + cmd[6] = pbSeq++; + cmd[7] = 1; + cmd[8] = cmd[9] = 0; /* RFU */ switch(CDC_Handle->state) { - - case CDC_IDLE_STATE: - status = USBH_OK; - break; - - case CDC_SET_LINE_CODING_STATE: - req_status = SetLineCoding(phost, CDC_Handle->pUserLineCoding); - - if(req_status == USBH_OK) - { - CDC_Handle->state = CDC_GET_LAST_LINE_CODING_STATE; - } - - else if(req_status != USBH_BUSY) - { - CDC_Handle->state = CDC_ERROR_STATE; - } - break; - - - case CDC_GET_LAST_LINE_CODING_STATE: - req_status = GetLineCoding(phost, &(CDC_Handle->LineCoding)); - - if(req_status == USBH_OK) - { - CDC_Handle->state = CDC_IDLE_STATE; + case CDC_IDLE_STATE: + status = USBH_OK; + CDC_Handle->state = CDC_TRANSFER_DATA; + //USBH_CDC_Transmit(phost, cmd, sizeof(cmd)); + break; + + case CCID_GET_DATA_HOST: + USBH_InterruptReceiveData(phost, + rawRxData, + 8, + CDC_Handle->CommItf.NotifPipe); + break; + case CDC_TRANSFER_DATA: + USBH_CDC_Transmit(phost, cmd, sizeof(cmd)); + CDC_ProcessTransmission(phost); + USBH_CDC_Receive(phost, rawRxData, sizeof(rawRxData)); + CDC_ProcessReception(phost); + break; - if((CDC_Handle->LineCoding.b.bCharFormat == CDC_Handle->pUserLineCoding->b.bCharFormat) && - (CDC_Handle->LineCoding.b.bDataBits == CDC_Handle->pUserLineCoding->b.bDataBits) && - (CDC_Handle->LineCoding.b.bParityType == CDC_Handle->pUserLineCoding->b.bParityType) && - (CDC_Handle->LineCoding.b.dwDTERate == CDC_Handle->pUserLineCoding->b.dwDTERate)) - { - USBH_CDC_LineCodingChanged(phost); - } - } - - else if(req_status != USBH_BUSY) - { - CDC_Handle->state = CDC_ERROR_STATE; - } - - break; - - case CDC_TRANSFER_DATA: - CDC_ProcessTransmission(phost); - CDC_ProcessReception(phost); - break; - - case CDC_ERROR_STATE: - req_status = USBH_ClrFeature(phost, 0x00); - - if(req_status == USBH_OK ) - { - /*Change the state to waiting*/ - CDC_Handle->state = CDC_IDLE_STATE ; - } - break; - - default: - break; + case CDC_ERROR_STATE: + req_status = USBH_ClrFeature(phost, 0x00); + + if(req_status == USBH_OK ) + { + /*Change the state to waiting*/ + CDC_Handle->state = CDC_IDLE_STATE ; + } + break; + + default: + break; } @@ -472,26 +450,6 @@ static USBH_StatusTypeDef SetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodin return USBH_CtlReq(phost, linecodin->Array , LINE_CODING_STRUCTURE_SIZE ); } -/** -* @brief This function prepares the state before issuing the class specific commands -* @param None -* @retval None -*/ -USBH_StatusTypeDef USBH_CDC_SetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecodin) -{ - CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; - if(phost->gState == HOST_CLASS) - { - CDC_Handle->state = CDC_SET_LINE_CODING_STATE; - CDC_Handle->pUserLineCoding = linecodin; - -#if (USBH_USE_OS == 1) - osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0); -#endif - } - return USBH_OK; -} - /** * @brief This function prepares the state before issuing the class specific commands * @param None diff --git a/ports/stm32/usbh_core.c b/ports/stm32/usbh_core.c index 0aaab2f57f12..985d8b848c82 100644 --- a/ports/stm32/usbh_core.c +++ b/ports/stm32/usbh_core.c @@ -620,7 +620,7 @@ static USBH_StatusTypeDef USBH_HandleEnum (USBH_HandleTypeDef *phost) { case ENUM_IDLE: /* Get Device Desc for only 1st 8 bytes : To get EP0 MaxPacketSize */ - if ( USBH_Get_DevDesc(phost, 8) == USBH_OK) + if ( USBH_Get_DevDesc(phost, 9) == USBH_OK) { phost->Control.pipe_size = phost->device.DevDesc.bMaxPacketSize; diff --git a/ports/stm32/usbhost/Class/CDC/Inc/usbh_cdc.h b/ports/stm32/usbhost/Class/CDC/Inc/usbh_cdc.h index 3b81ff9d2360..2899bc21c061 100644 --- a/ports/stm32/usbhost/Class/CDC/Inc/usbh_cdc.h +++ b/ports/stm32/usbhost/Class/CDC/Inc/usbh_cdc.h @@ -151,8 +151,7 @@ CDC_DataStateTypeDef; typedef enum { CDC_IDLE_STATE= 0, - CDC_SET_LINE_CODING_STATE, - CDC_GET_LAST_LINE_CODING_STATE, + CCID_GET_DATA_HOST, CDC_TRANSFER_DATA, CDC_ERROR_STATE, } @@ -397,9 +396,6 @@ extern USBH_ClassTypeDef CDC_Class; * @{ */ -USBH_StatusTypeDef USBH_CDC_SetLineCoding(USBH_HandleTypeDef *phost, - CDC_LineCodingTypeDef *linecoding); - USBH_StatusTypeDef USBH_CDC_GetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecoding); diff --git a/ports/stm32/usbhost/Core/Inc/usbh_conf.h b/ports/stm32/usbhost/Core/Inc/usbh_conf.h index ef2aa0a5c2e6..b9ae49a01beb 100644 --- a/ports/stm32/usbhost/Core/Inc/usbh_conf.h +++ b/ports/stm32/usbhost/Core/Inc/usbh_conf.h @@ -62,7 +62,7 @@ */ /*---------- -----------*/ -#define USBH_MAX_NUM_ENDPOINTS 2U +#define USBH_MAX_NUM_ENDPOINTS 3U /*---------- -----------*/ #define USBH_MAX_NUM_INTERFACES 2U From e4ddb9bd179f608df4ae4f85489400837db1c24d Mon Sep 17 00:00:00 2001 From: hemi454 Date: Thu, 17 Jun 2021 01:45:46 +0300 Subject: [PATCH 10/13] Add chip card descriptor --- ports/stm32/usbh_ctlreq.c | 23 +++++++++++++++++++---- ports/stm32/usbhost/Core/Inc/usbh_def.h | 24 +++++++++++++++++++++++- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/ports/stm32/usbh_ctlreq.c b/ports/stm32/usbh_ctlreq.c index 90dca7ffef12..674188165b5a 100644 --- a/ports/stm32/usbh_ctlreq.c +++ b/ports/stm32/usbh_ctlreq.c @@ -24,6 +24,7 @@ * ****************************************************************************** */ + #define dw2i(a, x) (unsigned int)((((((a[x+3] << 8) + a[x+2]) << 8) + a[x+1]) << 8) + a[x]) /* Includes ------------------------------------------------------------------*/ #include "usbh_ctlreq.h" @@ -89,7 +90,7 @@ static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc, static void USBH_ParseEPDesc (USBH_EpDescTypeDef *ep_descriptor, uint8_t *buf); static void USBH_ParseStringDesc (uint8_t* psrc, uint8_t* pdest, uint16_t length); static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor, uint8_t *buf); - +static void USBH_ParseCCDDesc (USBH_ChipCardDescTypeDef *ccd_descriptor, uint8_t *buf); /** * @} @@ -368,7 +369,8 @@ static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc, uint16_t length) { USBH_InterfaceDescTypeDef *pif ; - USBH_EpDescTypeDef *pep; + USBH_EpDescTypeDef *pep; + USBH_ChipCardDescTypeDef *pccd; USBH_DescHeader_t *pdesc = (USBH_DescHeader_t *)buf; uint16_t ptr; int8_t if_ix = 0; @@ -391,6 +393,7 @@ static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc, { ptr = USB_LEN_CFG_DESC; pif = (USBH_InterfaceDescTypeDef *)0; + pccd = (USBH_ChipCardDescTypeDef *)0; while ((if_ix < USBH_MAX_NUM_INTERFACES ) && (ptr < cfg_desc->wTotalLength)) @@ -399,8 +402,9 @@ static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc, if (pdesc->bDescriptorType == USB_DESC_TYPE_INTERFACE) { pif = &cfg_desc->Itf_Desc[if_ix]; - USBH_ParseInterfaceDesc (pif, (uint8_t *)pdesc); - + USBH_ParseInterfaceDesc (pif, (uint8_t *)pdesc); + pccd = &cfg_desc->Itf_Desc[if_ix].Ch_Desc; + USBH_ParseCCDDesc (pccd, (uint8_t *)pdesc); ep_ix = 0; pep = (USBH_EpDescTypeDef *)0; while ((ep_ix < pif->bNumEndpoints) && (ptr < cfg_desc->wTotalLength)) @@ -441,7 +445,18 @@ static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor, if_descriptor->bInterfaceProtocol = *(uint8_t *) (buf + 7); if_descriptor->iInterface = *(uint8_t *) (buf + 8); } +static void USBH_ParseCCDDesc (USBH_ChipCardDescTypeDef *ccd_descriptor, + uint8_t *buf) +{ + ccd_descriptor->bLength = *(uint8_t *) (buf + 9); + ccd_descriptor->bDescriptorType = *(uint8_t *) (buf + 10); + ccd_descriptor->bcdCCID = *(uint8_t *) (buf + 11); + ccd_descriptor->nMaxSlotIndex = *(uint8_t *) (buf + 12); + ccd_descriptor->bVoltageSupport = *(uint8_t *) (buf + 13); + ccd_descriptor->dwProtocols = *(uint8_t *) (buf + 14); + ccd_descriptor->dwDefaultClock = dw2i(buf, 19);; +} /** * @brief USBH_ParseEPDesc * This function Parses the endpoint descriptor diff --git a/ports/stm32/usbhost/Core/Inc/usbh_def.h b/ports/stm32/usbhost/Core/Inc/usbh_def.h index 9015d829713b..494a430c627d 100644 --- a/ports/stm32/usbhost/Core/Inc/usbh_def.h +++ b/ports/stm32/usbhost/Core/Inc/usbh_def.h @@ -261,6 +261,28 @@ typedef struct _EndpointDescriptor } USBH_EpDescTypeDef; +typedef struct _ChipCardDescriptor +{ + uint8_t *pbSeq; + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bcdCCID; + uint8_t nMaxSlotIndex; + uint8_t bVoltageSupport; + uint8_t dwProtocols; + unsigned int dwDefaultClock; + uint8_t dwMaxiumumClock; + uint8_t bNumClockSupported; + uint8_t dwDataRate; + uint8_t dwMaxDataRate; + uint8_t bNumDataRatesSupp; + uint8_t dwMaxIFSD; + uint8_t dwSyncProtocols; + uint8_t dwMechanical; + uint8_t dwFeatures; +} +USBH_ChipCardDescTypeDef; + typedef struct _InterfaceDescriptor { uint8_t bLength; @@ -272,11 +294,11 @@ typedef struct _InterfaceDescriptor uint8_t bInterfaceSubClass; /* Subclass Code (Assigned by USB Org) */ uint8_t bInterfaceProtocol; /* Protocol Code */ uint8_t iInterface; /* Index of String Descriptor Describing this interface */ + USBH_ChipCardDescTypeDef Ch_Desc; /* Chip card descriptor */ USBH_EpDescTypeDef Ep_Desc[USBH_MAX_NUM_ENDPOINTS]; } USBH_InterfaceDescTypeDef; - typedef struct _ConfigurationDescriptor { uint8_t bLength; From 5c4be781c3d70e5c8c9fff7c588ffb3aa2653efd Mon Sep 17 00:00:00 2001 From: hemi454 Date: Thu, 17 Jun 2021 01:45:46 +0300 Subject: [PATCH 11/13] Add chip card descriptor --- ports/stm32/usbh_cdc.c | 10 +++--- ports/stm32/usbh_ctlreq.c | 38 +++++++++++++++++++--- ports/stm32/usbhost/Core/Inc/usbh_ctlreq.h | 2 +- ports/stm32/usbhost/Core/Inc/usbh_def.h | 31 +++++++++++++++++- 4 files changed, 70 insertions(+), 11 deletions(-) diff --git a/ports/stm32/usbh_cdc.c b/ports/stm32/usbh_cdc.c index d71783db4607..d9a00cdffd4a 100644 --- a/ports/stm32/usbh_cdc.c +++ b/ports/stm32/usbh_cdc.c @@ -313,11 +313,10 @@ static USBH_StatusTypeDef USBH_CDC_ClassRequest (USBH_HandleTypeDef *phost) } uint8_t rawRxData[64] = {}; - unsigned char cmd[10]; #define BUFF_SIZE 64 uint8_t CDC_RX_Buffer[BUFF_SIZE]; uint8_t CDC_TX_Buffer[BUFF_SIZE]; - int pbSeq; +int pbSeq = 0; /** * @brief USBH_CDC_Process * The function is for managing state machine for CDC data transfers @@ -329,11 +328,13 @@ static USBH_StatusTypeDef USBH_CDC_Process (USBH_HandleTypeDef *phost) USBH_StatusTypeDef status = USBH_BUSY; USBH_StatusTypeDef req_status = USBH_OK; CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; + USBH_ChipCardDescTypeDef chipCardDesc = phost->device.CfgDesc.Itf_Desc[0].CCD_Desc; + uint8_t cmd[10] = {}; cmd[0] = 0x62; /* IccPowerOn */ cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */ - cmd[5] = 0; /* slot number */ + cmd[5] = chipCardDesc.bCurrentSlotIndex; /* slot number */ cmd[6] = pbSeq++; - cmd[7] = 1; + cmd[7] = chipCardDesc.bVoltageSupport; cmd[8] = cmd[9] = 0; /* RFU */ switch(CDC_Handle->state) { @@ -352,6 +353,7 @@ static USBH_StatusTypeDef USBH_CDC_Process (USBH_HandleTypeDef *phost) case CDC_TRANSFER_DATA: USBH_CDC_Transmit(phost, cmd, sizeof(cmd)); CDC_ProcessTransmission(phost); + USBH_Delay(200); USBH_CDC_Receive(phost, rawRxData, sizeof(rawRxData)); CDC_ProcessReception(phost); break; diff --git a/ports/stm32/usbh_ctlreq.c b/ports/stm32/usbh_ctlreq.c index 90dca7ffef12..c87b8c96a649 100644 --- a/ports/stm32/usbh_ctlreq.c +++ b/ports/stm32/usbh_ctlreq.c @@ -89,7 +89,7 @@ static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc, static void USBH_ParseEPDesc (USBH_EpDescTypeDef *ep_descriptor, uint8_t *buf); static void USBH_ParseStringDesc (uint8_t* psrc, uint8_t* pdest, uint16_t length); static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor, uint8_t *buf); - +static void USBH_ParseCCDDesc (USBH_ChipCardDescTypeDef *ccd_descriptor, uint8_t *buf); /** * @} @@ -368,7 +368,8 @@ static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc, uint16_t length) { USBH_InterfaceDescTypeDef *pif ; - USBH_EpDescTypeDef *pep; + USBH_EpDescTypeDef *pep; + USBH_ChipCardDescTypeDef *pccd; USBH_DescHeader_t *pdesc = (USBH_DescHeader_t *)buf; uint16_t ptr; int8_t if_ix = 0; @@ -391,6 +392,7 @@ static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc, { ptr = USB_LEN_CFG_DESC; pif = (USBH_InterfaceDescTypeDef *)0; + pccd = (USBH_ChipCardDescTypeDef *)0; while ((if_ix < USBH_MAX_NUM_INTERFACES ) && (ptr < cfg_desc->wTotalLength)) @@ -399,8 +401,9 @@ static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc, if (pdesc->bDescriptorType == USB_DESC_TYPE_INTERFACE) { pif = &cfg_desc->Itf_Desc[if_ix]; - USBH_ParseInterfaceDesc (pif, (uint8_t *)pdesc); - + USBH_ParseInterfaceDesc (pif, (uint8_t *)pdesc); + pccd = &cfg_desc->Itf_Desc[if_ix].CCD_Desc; + USBH_ParseCCDDesc (pccd, (uint8_t *)pdesc); ep_ix = 0; pep = (USBH_EpDescTypeDef *)0; while ((ep_ix < pif->bNumEndpoints) && (ptr < cfg_desc->wTotalLength)) @@ -441,7 +444,32 @@ static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor, if_descriptor->bInterfaceProtocol = *(uint8_t *) (buf + 7); if_descriptor->iInterface = *(uint8_t *) (buf + 8); } - +static void USBH_ParseCCDDesc (USBH_ChipCardDescTypeDef *ccd_descriptor, + uint8_t *buf) +{ + ccd_descriptor->bLength = *(uint8_t *) (buf + 9); + ccd_descriptor->bDescriptorType = *(uint8_t *) (buf + 10); + ccd_descriptor->bcdCCID = *(uint8_t *) (buf + 11); + ccd_descriptor->nMaxSlotIndex = *(uint8_t *) (buf + 12); + ccd_descriptor->bVoltageSupport = *(uint8_t *) (buf + 13); + ccd_descriptor->dwProtocols = *(uint8_t *) (buf + 14); + ccd_descriptor->dwDefaultClock = dw2i(buf, 10); + ccd_descriptor->dwMaxiumumClock = dw2i(buf, 14); + ccd_descriptor->bNumClockSupported = *(uint8_t *) (buf + 27); + ccd_descriptor->dwDataRate = dw2i(buf, 19); + ccd_descriptor->dwMaxDataRate = dw2i(buf, 23); + ccd_descriptor->bNumDataRatesSupp = *(uint8_t *) (buf + 36); + ccd_descriptor->dwMaxIFSD = dw2i(buf, 28); + ccd_descriptor->dwSyncProtocols = dw2i(buf, 32); + ccd_descriptor->dwMechanical = dw2i(buf, 36); + ccd_descriptor->dwFeatures = dw2i(buf, 40); + ccd_descriptor->dwMaxCCIDMessageLength = dw2i(buf, 44); + ccd_descriptor->bClassGetResponse = *(uint8_t *) (buf + 57); + ccd_descriptor->bClassEnvelope = *(uint8_t *) (buf + 58); + ccd_descriptor->wLcdLayout = (buf[60] << 8) + buf[59]; + ccd_descriptor->bPINSupport = *(uint8_t *) (buf + 61); + ccd_descriptor->bMaxCCIDBusySlots = *(uint8_t *) (buf + 62); +} /** * @brief USBH_ParseEPDesc * This function Parses the endpoint descriptor diff --git a/ports/stm32/usbhost/Core/Inc/usbh_ctlreq.h b/ports/stm32/usbhost/Core/Inc/usbh_ctlreq.h index cd61755e3ed3..9614460500dc 100644 --- a/ports/stm32/usbhost/Core/Inc/usbh_ctlreq.h +++ b/ports/stm32/usbhost/Core/Inc/usbh_ctlreq.h @@ -57,7 +57,7 @@ #define INTERFACE_DESC_TYPE 0x04 #define ENDPOINT_DESC_TYPE 0x05 #define INTERFACE_DESC_SIZE 0x09 - +#define dw2i(a, x) (unsigned int)((((((a[x+12] << 8) + a[x+11]) << 8) + a[x+10]) << 8) + a[x+9]) /** * @} */ diff --git a/ports/stm32/usbhost/Core/Inc/usbh_def.h b/ports/stm32/usbhost/Core/Inc/usbh_def.h index 9015d829713b..d505c59a6f5b 100644 --- a/ports/stm32/usbhost/Core/Inc/usbh_def.h +++ b/ports/stm32/usbhost/Core/Inc/usbh_def.h @@ -261,6 +261,35 @@ typedef struct _EndpointDescriptor } USBH_EpDescTypeDef; +typedef struct _ChipCardDescriptor +{ + int readerID; + uint8_t bCurrentSlotIndex; + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bcdCCID; + uint8_t nMaxSlotIndex; + uint8_t bVoltageSupport; + uint8_t dwProtocols; + unsigned int dwDefaultClock; + unsigned int dwMaxiumumClock; + uint8_t bNumClockSupported; + unsigned int dwDataRate; + unsigned int dwMaxDataRate; + uint8_t bNumDataRatesSupp; + unsigned int dwMaxIFSD; + unsigned int dwSyncProtocols; + unsigned int dwMechanical; + int dwFeatures; + unsigned int dwMaxCCIDMessageLength; + uint8_t bClassGetResponse; + uint8_t bClassEnvelope; + unsigned int wLcdLayout; + uint8_t bPINSupport; + uint8_t bMaxCCIDBusySlots; +} +USBH_ChipCardDescTypeDef; + typedef struct _InterfaceDescriptor { uint8_t bLength; @@ -272,11 +301,11 @@ typedef struct _InterfaceDescriptor uint8_t bInterfaceSubClass; /* Subclass Code (Assigned by USB Org) */ uint8_t bInterfaceProtocol; /* Protocol Code */ uint8_t iInterface; /* Index of String Descriptor Describing this interface */ + USBH_ChipCardDescTypeDef CCD_Desc; /* Chip card descriptor */ USBH_EpDescTypeDef Ep_Desc[USBH_MAX_NUM_ENDPOINTS]; } USBH_InterfaceDescTypeDef; - typedef struct _ConfigurationDescriptor { uint8_t bLength; From 54bd249197abb011396d37040cf4c34b416fbee6 Mon Sep 17 00:00:00 2001 From: hemi454 Date: Sun, 4 Jul 2021 18:15:44 +0300 Subject: [PATCH 12/13] Add usb smard card reader user module --- ports/stm32/Makefile | 10 +---- .../boards/STM32F469DISC/mpconfigboard.h | 6 ++- ports/stm32/main.c | 2 +- ports/stm32/mphalport.c | 2 +- ports/stm32/usb.c | 45 +++++-------------- ports/stm32/usbh_ctlreq.c | 4 +- 6 files changed, 20 insertions(+), 49 deletions(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index fd1fb997af8e..236734061f3d 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -58,7 +58,7 @@ INC += -I$(TOP)/lib/cmsis/inc INC += -I$(CMSIS_DIR)/ INC += -I$(TOP)/$(HAL_DIR)/Inc INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/inc -INC += -I$(USBHOST_DIR)/Core/Inc -I$(USBHOST_DIR)/Class/HID/Inc -I$(USBHOST_DIR)/Class/CDC/Inc +INC += -I$(USBHOST_DIR)/Class/HID/Inc INC += -Ilwip_inc # Basic Cortex-M flags @@ -256,18 +256,10 @@ SRC_C = \ usbd_cdc_interface.c \ usbd_hid_interface.c \ usbd_msc_interface.c \ - usbh_conf.c \ - usbh_core.c \ usbh_hid.c \ usbh_hid_keybd.c \ usbh_hid_mouse.c \ usbh_hid_parser.c \ - usb_host.c \ - usbh_platform.c \ - usbh_pipes.c \ - usbh_ctlreq.c\ - usbh_ioreq.c \ - usbh_cdc.c \ mphalport.c \ mpthreadport.c \ irq.c \ diff --git a/ports/stm32/boards/STM32F469DISC/mpconfigboard.h b/ports/stm32/boards/STM32F469DISC/mpconfigboard.h index 66d1f6651e14..bf58a752b8b4 100644 --- a/ports/stm32/boards/STM32F469DISC/mpconfigboard.h +++ b/ports/stm32/boards/STM32F469DISC/mpconfigboard.h @@ -74,6 +74,9 @@ extern struct _spi_bdev_t spi_bdev; #ifndef MODULE_SDRAM_ENABLED #define MODULE_SDRAM_ENABLED (1) #endif +#ifndef MODULE_USBSCARD_ENABLED +#define MODULE_USBSCARD_ENABLED (1) +#endif // #define MICROPY_PY_THREAD (1) // HSE is 8MHz @@ -140,5 +143,6 @@ extern struct _spi_bdev_t spi_bdev; #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) #define USE_HOST_MODE (1) -#define USB_HID_HOST_MODE (1) +//#define USB_HID_HOST_MODE (1) +#define USB_CCID_HOST_MODE (1) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index db99a57e2410..238df63c6024 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -86,7 +86,7 @@ #if MICROPY_PY_THREAD STATIC pyb_thread_t pyb_thread_main; #endif -#ifdef USB_HID_HOST_MODE +#if defined(USB_HID_HOST_MODE) || defined(USB_CCID_HOST_MODE) #define MICROPY_HW_UART_REPL PYB_UART_3 #define MICROPY_HW_UART_REPL_BAUD 115200 #endif diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index 6fa57e4f970d..8865229b665a 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -33,7 +33,7 @@ MP_WEAK uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { MP_WEAK int mp_hal_stdin_rx_chr(void) { for (;;) { -#ifdef USE_HOST_MODE +#if defined(USE_HOST_MODE) && defined(USB_HID_HOST_MODE) keyboardKeyCode = 0; pyb_usb_host_process(); if (keyboardKeyCode != 0) diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 56596a2ce793..6b43edcbd472 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -445,10 +445,16 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * { pyb_usb_hid_host_init(); } +/* else if (strcmp(mode_str, "CDC_HOST") == 0) { pyb_usb_cdc_host_init(); - } + } +*/ + else if (strcmp(mode_str, "CCID_HOST") == 0) + { + return mp_const_none; + } else { goto bad_mode; @@ -1016,7 +1022,7 @@ const mp_obj_type_t pyb_usb_hid_type = { #include "usbh_hid_keybd.h" #include "usbh_hid_mouse.h" #include "usbh_hid.h" -#include "usbh_cdc.h" +//#include "usbh_cdc.h" #include "usb_host.h" //__ALIGN_BEGIN USBH_HOST USB_Host __ALIGN_END ; /* USB Host core handle declaration */ @@ -1068,36 +1074,6 @@ void USBH_HID_EventCallback(USBH_HandleTypeDef *phost) } } -void USBH_CDC_Handle (void) -{ - uint8_t i = 0; - switch (CDC_STATE) - { - case CDC_STATE_IDLE: - { - USBH_CDC_Stop(&hUsbHostFS); - int len = sprintf ((char *)CDC_TX_Buffer, "DATA = %d", i); - if (USBH_CDC_Transmit (&hUsbHostFS, CDC_TX_Buffer, len) == USBH_OK) - { - CDC_STATE = CDC_RECEIVE; - } - i++; - break; - } - - case CDC_RECEIVE: - { - USBH_CDC_Stop(&hUsbHostFS); - usbResult = USBH_CDC_Receive(&hUsbHostFS, (uint8_t *) CDC_RX_Buffer, BUFF_SIZE); - HAL_Delay (1000); - CDC_STATE = CDC_IDLE; - } - - default: - break; - } -} - void pyb_usb_hid_host_init(void) { if (!host_is_enabled) { // only init USBH once in the device's power-lifetime @@ -1109,11 +1085,10 @@ void pyb_usb_hid_host_init(void) { } host_is_enabled = 1; } - +/* void pyb_usb_cdc_host_init(void) { if (!host_is_enabled) { // only init USBH once in the device's power-lifetime - /* Init Host Library */ INIT_TEST_LED_Usb(); USBH_Init(&hUsbHostFS, USBH_UserProcess, HOST_FS); USBH_RegisterClass(&hUsbHostFS, USBH_CDC_CLASS); @@ -1125,7 +1100,7 @@ void pyb_usb_cdc_host_init(void) { } host_is_enabled = 1; } - +*/ void pyb_usb_host_process(void) { USBH_Process(&hUsbHostFS); } diff --git a/ports/stm32/usbh_ctlreq.c b/ports/stm32/usbh_ctlreq.c index 389003a06b8a..14eac8f56461 100644 --- a/ports/stm32/usbh_ctlreq.c +++ b/ports/stm32/usbh_ctlreq.c @@ -24,8 +24,8 @@ * ****************************************************************************** */ - #define dw2i(a, x) (unsigned int)((((((a[x+3] << 8) + a[x+2]) << 8) + a[x+1]) << 8) + a[x]) -/* Includes ------------------------------------------------------------------*/ + + /* Includes ------------------------------------------------------------------*/ #include "usbh_ctlreq.h" From 73e99279d805918318e7b9328f7eaf07d3ffe18c Mon Sep 17 00:00:00 2001 From: hemi454 Date: Sun, 4 Jul 2021 18:15:44 +0300 Subject: [PATCH 13/13] Add usb smard card reader user module --- ports/stm32/Makefile | 12 +---- .../boards/STM32F469DISC/mpconfigboard.h | 6 ++- ports/stm32/main.c | 2 +- ports/stm32/mphalport.c | 2 +- ports/stm32/usb.c | 45 +++++-------------- ports/stm32/usbh_ctlreq.c | 4 +- 6 files changed, 21 insertions(+), 50 deletions(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index fd1fb997af8e..e24af2756e6e 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -6,7 +6,7 @@ BOARD ?= PYBV10 BUILD ?= build-$(BOARD) SKIP_USBINIT ?= 0 -MICROPY_HW_SDCARD_MOUNT_AT_BOOT ?= 0 +MICROPY_HW_SDCARD_MOUNT_AT_BOOT ?= 1 BOARD_DIR ?= boards/$(BOARD) ifeq ($(wildcard $(BOARD_DIR)/.),) @@ -58,7 +58,7 @@ INC += -I$(TOP)/lib/cmsis/inc INC += -I$(CMSIS_DIR)/ INC += -I$(TOP)/$(HAL_DIR)/Inc INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/inc -INC += -I$(USBHOST_DIR)/Core/Inc -I$(USBHOST_DIR)/Class/HID/Inc -I$(USBHOST_DIR)/Class/CDC/Inc +INC += -I$(USBHOST_DIR)/Class/HID/Inc INC += -Ilwip_inc # Basic Cortex-M flags @@ -256,18 +256,10 @@ SRC_C = \ usbd_cdc_interface.c \ usbd_hid_interface.c \ usbd_msc_interface.c \ - usbh_conf.c \ - usbh_core.c \ usbh_hid.c \ usbh_hid_keybd.c \ usbh_hid_mouse.c \ usbh_hid_parser.c \ - usb_host.c \ - usbh_platform.c \ - usbh_pipes.c \ - usbh_ctlreq.c\ - usbh_ioreq.c \ - usbh_cdc.c \ mphalport.c \ mpthreadport.c \ irq.c \ diff --git a/ports/stm32/boards/STM32F469DISC/mpconfigboard.h b/ports/stm32/boards/STM32F469DISC/mpconfigboard.h index 66d1f6651e14..bf58a752b8b4 100644 --- a/ports/stm32/boards/STM32F469DISC/mpconfigboard.h +++ b/ports/stm32/boards/STM32F469DISC/mpconfigboard.h @@ -74,6 +74,9 @@ extern struct _spi_bdev_t spi_bdev; #ifndef MODULE_SDRAM_ENABLED #define MODULE_SDRAM_ENABLED (1) #endif +#ifndef MODULE_USBSCARD_ENABLED +#define MODULE_USBSCARD_ENABLED (1) +#endif // #define MICROPY_PY_THREAD (1) // HSE is 8MHz @@ -140,5 +143,6 @@ extern struct _spi_bdev_t spi_bdev; #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) #define USE_HOST_MODE (1) -#define USB_HID_HOST_MODE (1) +//#define USB_HID_HOST_MODE (1) +#define USB_CCID_HOST_MODE (1) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index db99a57e2410..238df63c6024 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -86,7 +86,7 @@ #if MICROPY_PY_THREAD STATIC pyb_thread_t pyb_thread_main; #endif -#ifdef USB_HID_HOST_MODE +#if defined(USB_HID_HOST_MODE) || defined(USB_CCID_HOST_MODE) #define MICROPY_HW_UART_REPL PYB_UART_3 #define MICROPY_HW_UART_REPL_BAUD 115200 #endif diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index 6fa57e4f970d..8865229b665a 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -33,7 +33,7 @@ MP_WEAK uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { MP_WEAK int mp_hal_stdin_rx_chr(void) { for (;;) { -#ifdef USE_HOST_MODE +#if defined(USE_HOST_MODE) && defined(USB_HID_HOST_MODE) keyboardKeyCode = 0; pyb_usb_host_process(); if (keyboardKeyCode != 0) diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 56596a2ce793..6b43edcbd472 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -445,10 +445,16 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * { pyb_usb_hid_host_init(); } +/* else if (strcmp(mode_str, "CDC_HOST") == 0) { pyb_usb_cdc_host_init(); - } + } +*/ + else if (strcmp(mode_str, "CCID_HOST") == 0) + { + return mp_const_none; + } else { goto bad_mode; @@ -1016,7 +1022,7 @@ const mp_obj_type_t pyb_usb_hid_type = { #include "usbh_hid_keybd.h" #include "usbh_hid_mouse.h" #include "usbh_hid.h" -#include "usbh_cdc.h" +//#include "usbh_cdc.h" #include "usb_host.h" //__ALIGN_BEGIN USBH_HOST USB_Host __ALIGN_END ; /* USB Host core handle declaration */ @@ -1068,36 +1074,6 @@ void USBH_HID_EventCallback(USBH_HandleTypeDef *phost) } } -void USBH_CDC_Handle (void) -{ - uint8_t i = 0; - switch (CDC_STATE) - { - case CDC_STATE_IDLE: - { - USBH_CDC_Stop(&hUsbHostFS); - int len = sprintf ((char *)CDC_TX_Buffer, "DATA = %d", i); - if (USBH_CDC_Transmit (&hUsbHostFS, CDC_TX_Buffer, len) == USBH_OK) - { - CDC_STATE = CDC_RECEIVE; - } - i++; - break; - } - - case CDC_RECEIVE: - { - USBH_CDC_Stop(&hUsbHostFS); - usbResult = USBH_CDC_Receive(&hUsbHostFS, (uint8_t *) CDC_RX_Buffer, BUFF_SIZE); - HAL_Delay (1000); - CDC_STATE = CDC_IDLE; - } - - default: - break; - } -} - void pyb_usb_hid_host_init(void) { if (!host_is_enabled) { // only init USBH once in the device's power-lifetime @@ -1109,11 +1085,10 @@ void pyb_usb_hid_host_init(void) { } host_is_enabled = 1; } - +/* void pyb_usb_cdc_host_init(void) { if (!host_is_enabled) { // only init USBH once in the device's power-lifetime - /* Init Host Library */ INIT_TEST_LED_Usb(); USBH_Init(&hUsbHostFS, USBH_UserProcess, HOST_FS); USBH_RegisterClass(&hUsbHostFS, USBH_CDC_CLASS); @@ -1125,7 +1100,7 @@ void pyb_usb_cdc_host_init(void) { } host_is_enabled = 1; } - +*/ void pyb_usb_host_process(void) { USBH_Process(&hUsbHostFS); } diff --git a/ports/stm32/usbh_ctlreq.c b/ports/stm32/usbh_ctlreq.c index 389003a06b8a..14eac8f56461 100644 --- a/ports/stm32/usbh_ctlreq.c +++ b/ports/stm32/usbh_ctlreq.c @@ -24,8 +24,8 @@ * ****************************************************************************** */ - #define dw2i(a, x) (unsigned int)((((((a[x+3] << 8) + a[x+2]) << 8) + a[x+1]) << 8) + a[x]) -/* Includes ------------------------------------------------------------------*/ + + /* Includes ------------------------------------------------------------------*/ #include "usbh_ctlreq.h"