diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 0e529b3462be..d80d5f28894f 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -1767,6 +1767,14 @@ */ //#define SDSUPPORT +/** + * USB HOST MSC + * + * USB Flash mounted in MCU USB OTG Host port + * you need uncomment both SDSUPPORT and following option at the same time or it won't work. + */ +//#define USB_HOST_MSC_FLASH_SUPPORT + /** * SD CARD: SPI SPEED * diff --git a/Marlin/src/HAL/STM32/inc/SanityCheck.h b/Marlin/src/HAL/STM32/inc/SanityCheck.h index c51fecc7bdb9..e747433ed570 100644 --- a/Marlin/src/HAL/STM32/inc/SanityCheck.h +++ b/Marlin/src/HAL/STM32/inc/SanityCheck.h @@ -46,6 +46,10 @@ #error "FLASH_EEPROM_LEVELING is currently only supported on STM32F4 hardware." #endif +#if !defined(STM32F4xx) && ENABLED(USB_HOST_MSC_FLASH_SUPPORT) + #error "For now USB host MSC is only supported on STM32F4." +#endif + #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED) #error "SERIAL_STATS_MAX_RX_QUEUED is not supported on this platform." #elif ENABLED(SERIAL_STATS_DROPPED_RX) diff --git a/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc.h b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc.h new file mode 100644 index 000000000000..55aeab65ea0b --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc.h @@ -0,0 +1,216 @@ +/** + ****************************************************************************** + * @file usbh_msc.h + * @author MCD Application Team + * @brief This file contains all the prototypes for the usbh_msc.c + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 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 + * + ****************************************************************************** + */ + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_MSC_H +#define __USBH_MSC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "../../../Core/Inc/usbh_core.h" +#include "usbh_msc_bot.h" +#include "usbh_msc_scsi.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_CLASS + * @{ + */ + +/** @addtogroup USBH_MSC_CLASS + * @{ + */ + +/** @defgroup USBH_MSC_CORE + * @brief This file is the Header file for usbh_msc.c + * @{ + */ + + +/** @defgroup USBH_MSC_CORE_Exported_Types + * @{ + */ + +typedef enum +{ + MSC_INIT = 0, + MSC_IDLE, + MSC_TEST_UNIT_READY, + MSC_READ_CAPACITY10, + MSC_READ_INQUIRY, + MSC_REQUEST_SENSE, + MSC_READ, + MSC_WRITE, + MSC_UNRECOVERED_ERROR, + MSC_PERIODIC_CHECK, +} +MSC_StateTypeDef; + +typedef enum +{ + MSC_OK, + MSC_NOT_READY, + MSC_ERROR, + +} +MSC_ErrorTypeDef; + +typedef enum +{ + MSC_REQ_IDLE = 0, + MSC_REQ_RESET, + MSC_REQ_GET_MAX_LUN, + MSC_REQ_ERROR, +} +MSC_ReqStateTypeDef; + +#ifndef MAX_SUPPORTED_LUN +#define MAX_SUPPORTED_LUN 2U +#endif + + +/* Structure for LUN */ +typedef struct +{ + MSC_StateTypeDef state; + MSC_ErrorTypeDef error; + USBH_StatusTypeDef prev_ready_state; + SCSI_CapacityTypeDef capacity; + SCSI_SenseTypeDef sense; + SCSI_StdInquiryDataTypeDef inquiry; + uint8_t state_changed; + +} +MSC_LUNTypeDef; + +/* Structure for MSC process */ +typedef struct _MSC_Process +{ + uint8_t max_lun; + uint8_t Reserved[3]; + uint8_t InPipe; + uint8_t OutPipe; + uint8_t OutEp; + uint8_t InEp; + uint16_t OutEpSize; + uint16_t InEpSize; + MSC_StateTypeDef state; + MSC_ErrorTypeDef error; + MSC_ReqStateTypeDef req_state; + MSC_ReqStateTypeDef prev_req_state; + BOT_HandleTypeDef hbot; + MSC_LUNTypeDef unit[MAX_SUPPORTED_LUN]; + uint16_t current_lun; + uint16_t rw_lun; + uint32_t timer; +} +MSC_HandleTypeDef; + + +/** + * @} + */ + + + +/** @defgroup USBH_MSC_CORE_Exported_Defines + * @{ + */ + +#define USB_REQ_BOT_RESET 0xFFU +#define USB_REQ_GET_MAX_LUN 0xFEU + + +/* MSC Class Codes */ +#define USB_MSC_CLASS 0x08U + +/* Interface Descriptor field values for HID Boot Protocol */ +#define MSC_BOT 0x50U +#define MSC_TRANSPARENT 0x06U +/** + * @} + */ + +/** @defgroup USBH_MSC_CORE_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_MSC_CORE_Exported_Variables + * @{ + */ +extern USBH_ClassTypeDef USBH_msc; +#define USBH_MSC_CLASS &USBH_msc + +/** + * @} + */ + +/** @defgroup USBH_MSC_CORE_Exported_FunctionsPrototype + * @{ + */ +uint8_t USBH_MSC_IsReady(USBH_HandleTypeDef *phost); +uint8_t USBH_MSC_GetMaxLUN(USBH_HandleTypeDef *phost); +uint8_t USBH_MSC_UnitIsReady(USBH_HandleTypeDef *phost, uint8_t lun); + +USBH_StatusTypeDef USBH_MSC_GetLUNInfo(USBH_HandleTypeDef *phost, uint8_t lun, + MSC_LUNTypeDef *info); + +USBH_StatusTypeDef USBH_MSC_Read(USBH_HandleTypeDef *phost, uint8_t lun, + uint32_t address, uint8_t *pbuf, uint32_t length); + +USBH_StatusTypeDef USBH_MSC_Write(USBH_HandleTypeDef *phost, uint8_t lun, + uint32_t address, uint8_t *pbuf, uint32_t length); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_MSC_H */ + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + diff --git a/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_bot.h b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_bot.h new file mode 100644 index 000000000000..731c6cfbfc28 --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_bot.h @@ -0,0 +1,232 @@ +/** + ****************************************************************************** + * @file usbh_msc_bot.h + * @author MCD Application Team + * @brief Header file for usbh_msc_bot.c + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 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 + * + ****************************************************************************** + */ + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_MSC_BOT_H +#define __USBH_MSC_BOT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "../../../Core/Inc/usbh_core.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_CLASS + * @{ + */ + +/** @addtogroup USBH_MSC_CLASS + * @{ + */ + +/** @defgroup USBH_MSC_BOT + * @brief This file is the Header file for usbh_msc_bot.c + * @{ + */ + + +/** @defgroup USBH_MSC_BOT_Exported_Types + * @{ + */ + +typedef enum +{ + BOT_OK = 0, + BOT_FAIL = 1, + BOT_PHASE_ERROR = 2, + BOT_BUSY = 3 +} +BOT_StatusTypeDef; + +typedef enum +{ + BOT_CMD_IDLE = 0, + BOT_CMD_SEND, + BOT_CMD_WAIT, +} +BOT_CMDStateTypeDef; + +/* CSW Status Definitions */ +typedef enum +{ + + BOT_CSW_CMD_PASSED = 0x00, + BOT_CSW_CMD_FAILED = 0x01, + BOT_CSW_PHASE_ERROR = 0x02, +} +BOT_CSWStatusTypeDef; + +typedef enum +{ + BOT_SEND_CBW = 1, + BOT_SEND_CBW_WAIT, + BOT_DATA_IN, + BOT_DATA_IN_WAIT, + BOT_DATA_OUT, + BOT_DATA_OUT_WAIT, + BOT_RECEIVE_CSW, + BOT_RECEIVE_CSW_WAIT, + BOT_ERROR_IN, + BOT_ERROR_OUT, + BOT_UNRECOVERED_ERROR +} +BOT_StateTypeDef; + +typedef union +{ + struct __CBW + { + uint32_t Signature; + uint32_t Tag; + uint32_t DataTransferLength; + uint8_t Flags; + uint8_t LUN; + uint8_t CBLength; + uint8_t CB[16]; + } field; + uint8_t data[31]; +} +BOT_CBWTypeDef; + +typedef union +{ + struct __CSW + { + uint32_t Signature; + uint32_t Tag; + uint32_t DataResidue; + uint8_t Status; + } field; + uint8_t data[13]; +} +BOT_CSWTypeDef; + +typedef struct +{ + uint32_t data[16]; + BOT_StateTypeDef state; + BOT_StateTypeDef prev_state; + BOT_CMDStateTypeDef cmd_state; + BOT_CBWTypeDef cbw; + uint8_t Reserved1; + BOT_CSWTypeDef csw; + uint8_t Reserved2[3]; + uint8_t *pbuf; +} +BOT_HandleTypeDef; + +/** + * @} + */ + + + +/** @defgroup USBH_MSC_BOT_Exported_Defines + * @{ + */ +#define BOT_CBW_SIGNATURE 0x43425355U +#define BOT_CBW_TAG 0x20304050U +#define BOT_CSW_SIGNATURE 0x53425355U +#define BOT_CBW_LENGTH 31U +#define BOT_CSW_LENGTH 13U + + + +#define BOT_SEND_CSW_DISABLE 0U +#define BOT_SEND_CSW_ENABLE 1U + +#define BOT_DIR_IN 0U +#define BOT_DIR_OUT 1U +#define BOT_DIR_BOTH 2U + +#define BOT_PAGE_LENGTH 512U + + +#define BOT_CBW_CB_LENGTH 16U + + +#define MAX_BULK_STALL_COUNT_LIMIT 0x04U /* If STALL is seen on Bulk + Endpoint continuously, this means + that device and Host has phase error + Hence a Reset is needed */ + +/** + * @} + */ + +/** @defgroup USBH_MSC_BOT_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_MSC_BOT_Exported_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBH_MSC_BOT_Exported_FunctionsPrototype + * @{ + */ +USBH_StatusTypeDef USBH_MSC_BOT_REQ_Reset(USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_MSC_BOT_REQ_GetMaxLUN(USBH_HandleTypeDef *phost, uint8_t *Maxlun); + +USBH_StatusTypeDef USBH_MSC_BOT_Init(USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_MSC_BOT_Process(USBH_HandleTypeDef *phost, uint8_t lun); +USBH_StatusTypeDef USBH_MSC_BOT_Error(USBH_HandleTypeDef *phost, uint8_t lun); + + + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_MSC_BOT_H__ */ + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_scsi.h b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_scsi.h new file mode 100644 index 000000000000..3f3e611df56d --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_scsi.h @@ -0,0 +1,218 @@ +/** + ****************************************************************************** + * @file usbh_msc_scsi.h + * @author MCD Application Team + * @brief Header file for usbh_msc_scsi.c + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 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 + * + ****************************************************************************** + */ + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_MSC_SCSI_H +#define __USBH_MSC_SCSI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "../../../Core/Inc/usbh_core.h" + + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_CLASS + * @{ + */ + +/** @addtogroup USBH_MSC_CLASS + * @{ + */ + +/** @defgroup USBH_MSC_SCSI + * @brief This file is the Header file for usbh_msc_scsi.c + * @{ + */ + + +/* Capacity data */ +typedef struct +{ + uint32_t block_nbr; + uint16_t block_size; +} SCSI_CapacityTypeDef; + + +/* Sense data */ +typedef struct +{ + uint8_t key; + uint8_t asc; + uint8_t ascq; +} SCSI_SenseTypeDef; + +/* INQUIRY data */ +typedef struct +{ + uint8_t PeripheralQualifier; + uint8_t DeviceType; + uint8_t RemovableMedia; + uint8_t vendor_id[9]; + uint8_t product_id[17]; + uint8_t revision_id[5]; +} SCSI_StdInquiryDataTypeDef; + +/** @defgroup USBH_MSC_SCSI_Exported_Defines + * @{ + */ +#define OPCODE_TEST_UNIT_READY 0x00U +#define OPCODE_READ_CAPACITY10 0x25U +#define OPCODE_READ10 0x28U +#define OPCODE_WRITE10 0x2AU +#define OPCODE_REQUEST_SENSE 0x03U +#define OPCODE_INQUIRY 0x12U + +#define DATA_LEN_MODE_TEST_UNIT_READY 0U +#define DATA_LEN_READ_CAPACITY10 8U +#define DATA_LEN_INQUIRY 36U +#define DATA_LEN_REQUEST_SENSE 14U + +#define CBW_CB_LENGTH 16U +#define CBW_LENGTH 10U + +/** @defgroup USBH_MSC_SCSI_Exported_Defines + * @{ + */ +#define SCSI_SENSE_KEY_NO_SENSE 0x00U +#define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01U +#define SCSI_SENSE_KEY_NOT_READY 0x02U +#define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03U +#define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04U +#define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05U +#define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06U +#define SCSI_SENSE_KEY_DATA_PROTECT 0x07U +#define SCSI_SENSE_KEY_BLANK_CHECK 0x08U +#define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09U +#define SCSI_SENSE_KEY_COPY_ABORTED 0x0AU +#define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0BU +#define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0DU +#define SCSI_SENSE_KEY_MISCOMPARE 0x0EU +/** + * @} + */ + + +/** @defgroup USBH_MSC_SCSI_Exported_Defines + * @{ + */ +#define SCSI_ASC_NO_ADDITIONAL_SENSE_INFORMATION 0x00 +#define SCSI_ASC_LOGICAL_UNIT_NOT_READY 0x04 +#define SCSI_ASC_INVALID_FIELD_IN_CDB 0x24 +#define SCSI_ASC_WRITE_PROTECTED 0x27 +#define SCSI_ASC_FORMAT_ERROR 0x31 +#define SCSI_ASC_INVALID_COMMAND_OPERATION_CODE 0x20 +#define SCSI_ASC_NOT_READY_TO_READY_CHANGE 0x28 +#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A +/** + * @} + */ + + +/** @defgroup USBH_MSC_SCSI_Exported_Defines + * @{ + */ +#define SCSI_ASCQ_FORMAT_COMMAND_FAILED 0x01 +#define SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02 +#define SCSI_ASCQ_OPERATION_IN_PROGRESS 0x07 + +/** + * @} + */ + +/** @defgroup USBH_MSC_SCSI_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup _Exported_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBH_MSC_SCSI_Exported_FunctionsPrototype + * @{ + */ +USBH_StatusTypeDef USBH_MSC_SCSI_TestUnitReady(USBH_HandleTypeDef *phost, + uint8_t lun); + +USBH_StatusTypeDef USBH_MSC_SCSI_ReadCapacity(USBH_HandleTypeDef *phost, + uint8_t lun, + SCSI_CapacityTypeDef *capacity); + +USBH_StatusTypeDef USBH_MSC_SCSI_Inquiry(USBH_HandleTypeDef *phost, + uint8_t lun, + SCSI_StdInquiryDataTypeDef *inquiry); + +USBH_StatusTypeDef USBH_MSC_SCSI_RequestSense(USBH_HandleTypeDef *phost, + uint8_t lun, + SCSI_SenseTypeDef *sense_data); + +USBH_StatusTypeDef USBH_MSC_SCSI_Write(USBH_HandleTypeDef *phost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); + +USBH_StatusTypeDef USBH_MSC_SCSI_Read(USBH_HandleTypeDef *phost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); + + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_MSC_SCSI_H */ + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc.cpp b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc.cpp new file mode 100644 index 000000000000..90f1fa05ea01 --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc.cpp @@ -0,0 +1,866 @@ +/** + ****************************************************************************** + * @file usbh_msc.c + * @author MCD Application Team + * @brief This file implements the MSC class driver functions + * =================================================================== + * MSC Class Description + * =================================================================== + * This module manages the MSC class V1.0 following the "Universal + * Serial Bus Mass Storage Class (MSC) Bulk-Only Transport (BOT) Version 1.0 + * Sep. 31, 1999". + * This driver implements the following aspects of the specification: + * - Bulk-Only Transport protocol + * - Subclass : SCSI transparent command set (ref. SCSI Primary Commands - 3 (SPC-3)) + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 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 + * + ****************************************************************************** + */ +#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC) + +#include "../../../../../../../inc/MarlinConfig.h" + +#if ENABLED(USB_HOST_MSC_FLASH_SUPPORT) + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +- "stm32xxxxx_{eval}{discovery}{adafruit}_lcd.c" +- "stm32xxxxx_{eval}{discovery}_sdram.c" +EndBSPDependencies */ + +/* Includes ------------------------------------------------------------------*/ +#include "../Inc/usbh_msc.h" +#include "../Inc/usbh_msc_bot.h" +#include "../Inc/usbh_msc_scsi.h" + + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_CLASS + * @{ + */ + +/** @addtogroup USBH_MSC_CLASS + * @{ + */ + +/** @defgroup USBH_MSC_CORE + * @brief This file includes the mass storage related functions + * @{ + */ + + +/** @defgroup USBH_MSC_CORE_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_MSC_CORE_Private_Defines + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_MSC_CORE_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_MSC_CORE_Private_Variables + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_MSC_CORE_Private_FunctionPrototypes + * @{ + */ + +static USBH_StatusTypeDef USBH_MSC_InterfaceInit(USBH_HandleTypeDef *phost); + +static USBH_StatusTypeDef USBH_MSC_InterfaceDeInit(USBH_HandleTypeDef *phost); + +static USBH_StatusTypeDef USBH_MSC_Process(USBH_HandleTypeDef *phost); + +static USBH_StatusTypeDef USBH_MSC_ClassRequest(USBH_HandleTypeDef *phost); + +static USBH_StatusTypeDef USBH_MSC_SOFProcess(USBH_HandleTypeDef *phost); + +static USBH_StatusTypeDef USBH_MSC_RdWrProcess(USBH_HandleTypeDef *phost, uint8_t lun); + +USBH_ClassTypeDef USBH_msc = +{ + "MSC", + USB_MSC_CLASS, + USBH_MSC_InterfaceInit, + USBH_MSC_InterfaceDeInit, + USBH_MSC_ClassRequest, + USBH_MSC_Process, + USBH_MSC_SOFProcess, + NULL, +}; + + +/** + * @} + */ + + +/** @defgroup USBH_MSC_CORE_Exported_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBH_MSC_CORE_Private_Functions + * @{ + */ + + +/** + * @brief USBH_MSC_InterfaceInit + * The function init the MSC class. + * @param phost: Host handle + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_MSC_InterfaceInit(USBH_HandleTypeDef *phost) +{ + USBH_StatusTypeDef status; + uint8_t interface; + MSC_HandleTypeDef *MSC_Handle; + + interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, MSC_TRANSPARENT, MSC_BOT); + + if ((interface == 0xFFU) || (interface >= USBH_MAX_NUM_INTERFACES)) /* Not Valid Interface */ + { + USBH_DbgLog("Cannot Find the interface for %s class.", phost->pActiveClass->Name); + return USBH_FAIL; + } + + status = USBH_SelectInterface(phost, interface); + + if (status != USBH_OK) + { + return USBH_FAIL; + } + + phost->pActiveClass->pData = (MSC_HandleTypeDef *)USBH_malloc(sizeof(MSC_HandleTypeDef)); + MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + if (MSC_Handle == NULL) + { + USBH_DbgLog("Cannot allocate memory for MSC Handle"); + return USBH_FAIL; + } + + /* Initialize msc handler */ + USBH_memset(MSC_Handle, 0, sizeof(MSC_HandleTypeDef)); + + if (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80U) + { + MSC_Handle->InEp = (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress); + MSC_Handle->InEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; + } + else + { + MSC_Handle->OutEp = (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress); + MSC_Handle->OutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; + } + + if (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress & 0x80U) + { + MSC_Handle->InEp = (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress); + MSC_Handle->InEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].wMaxPacketSize; + } + else + { + MSC_Handle->OutEp = (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress); + MSC_Handle->OutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].wMaxPacketSize; + } + + MSC_Handle->state = MSC_INIT; + MSC_Handle->error = MSC_OK; + MSC_Handle->req_state = MSC_REQ_IDLE; + MSC_Handle->OutPipe = USBH_AllocPipe(phost, MSC_Handle->OutEp); + MSC_Handle->InPipe = USBH_AllocPipe(phost, MSC_Handle->InEp); + + USBH_MSC_BOT_Init(phost); + + /* Open the new channels */ + USBH_OpenPipe(phost, MSC_Handle->OutPipe, MSC_Handle->OutEp, + phost->device.address, phost->device.speed, + USB_EP_TYPE_BULK, MSC_Handle->OutEpSize); + + USBH_OpenPipe(phost, MSC_Handle->InPipe, MSC_Handle->InEp, + phost->device.address, phost->device.speed, USB_EP_TYPE_BULK, + MSC_Handle->InEpSize); + + USBH_LL_SetToggle(phost, MSC_Handle->InPipe, 0U); + USBH_LL_SetToggle(phost, MSC_Handle->OutPipe, 0U); + + return USBH_OK; +} + +/** + * @brief USBH_MSC_InterfaceDeInit + * The function DeInit the Pipes used for the MSC class. + * @param phost: Host handle + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_MSC_InterfaceDeInit(USBH_HandleTypeDef *phost) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + if (MSC_Handle->OutPipe) + { + USBH_ClosePipe(phost, MSC_Handle->OutPipe); + USBH_FreePipe(phost, MSC_Handle->OutPipe); + MSC_Handle->OutPipe = 0U; /* Reset the Channel as Free */ + } + + if (MSC_Handle->InPipe) + { + USBH_ClosePipe(phost, MSC_Handle->InPipe); + USBH_FreePipe(phost, MSC_Handle->InPipe); + MSC_Handle->InPipe = 0U; /* Reset the Channel as Free */ + } + + if (phost->pActiveClass->pData) + { + USBH_free(phost->pActiveClass->pData); + phost->pActiveClass->pData = 0U; + } + + return USBH_OK; +} + +/** + * @brief USBH_MSC_ClassRequest + * The function is responsible for handling Standard requests + * for MSC class. + * @param phost: Host handle + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_MSC_ClassRequest(USBH_HandleTypeDef *phost) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + USBH_StatusTypeDef status = USBH_BUSY; + uint8_t i; + + /* Switch MSC REQ state machine */ + switch (MSC_Handle->req_state) + { + case MSC_REQ_IDLE: + case MSC_REQ_GET_MAX_LUN: + /* Issue GetMaxLUN request */ + status = USBH_MSC_BOT_REQ_GetMaxLUN(phost, &MSC_Handle->max_lun); + + /* When devices do not support the GetMaxLun request, this should + be considred as only one logical unit is supported */ + if (status == USBH_NOT_SUPPORTED) + { + MSC_Handle->max_lun = 0U; + status = USBH_OK; + } + + if (status == USBH_OK) + { + MSC_Handle->max_lun = (MSC_Handle->max_lun > MAX_SUPPORTED_LUN) ? MAX_SUPPORTED_LUN : (MSC_Handle->max_lun + 1U); + USBH_UsrLog("Number of supported LUN: %d", MSC_Handle->max_lun); + + for (i = 0U; i < MSC_Handle->max_lun; i++) + { + MSC_Handle->unit[i].prev_ready_state = USBH_FAIL; + MSC_Handle->unit[i].state_changed = 0U; + } + } + break; + + case MSC_REQ_ERROR: + /* a Clear Feature should be issued here */ + if (USBH_ClrFeature(phost, 0x00U) == USBH_OK) + { + MSC_Handle->req_state = MSC_Handle->prev_req_state; + } + break; + + default: + break; + } + + return status; +} + +/** + * @brief USBH_MSC_Process + * The function is for managing state machine for MSC data transfers + * @param phost: Host handle + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_MSC_Process(USBH_HandleTypeDef *phost) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + USBH_StatusTypeDef error = USBH_BUSY; + USBH_StatusTypeDef scsi_status = USBH_BUSY; + USBH_StatusTypeDef ready_status = USBH_BUSY; + + switch (MSC_Handle->state) + { + case MSC_INIT: + + if (MSC_Handle->current_lun < MSC_Handle->max_lun) + { + + MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_NOT_READY; + /* Switch MSC REQ state machine */ + switch (MSC_Handle->unit[MSC_Handle->current_lun].state) + { + case MSC_INIT: + USBH_UsrLog("LUN #%d: ", MSC_Handle->current_lun); + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_READ_INQUIRY; + MSC_Handle->timer = phost->Timer; + break; + + case MSC_READ_INQUIRY: + scsi_status = USBH_MSC_SCSI_Inquiry(phost, (uint8_t)MSC_Handle->current_lun, &MSC_Handle->unit[MSC_Handle->current_lun].inquiry); + + if (scsi_status == USBH_OK) + { + USBH_UsrLog("Inquiry Vendor : %s", MSC_Handle->unit[MSC_Handle->current_lun].inquiry.vendor_id); + USBH_UsrLog("Inquiry Product : %s", MSC_Handle->unit[MSC_Handle->current_lun].inquiry.product_id); + USBH_UsrLog("Inquiry Version : %s", MSC_Handle->unit[MSC_Handle->current_lun].inquiry.revision_id); + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_TEST_UNIT_READY; + } + if (scsi_status == USBH_FAIL) + { + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_REQUEST_SENSE; + } + else + { + if (scsi_status == USBH_UNRECOVERED_ERROR) + { + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE; + MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR; + } + } + break; + + case MSC_TEST_UNIT_READY: + ready_status = USBH_MSC_SCSI_TestUnitReady(phost, (uint8_t)MSC_Handle->current_lun); + + if (ready_status == USBH_OK) + { + if (MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state != USBH_OK) + { + MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 1U; + USBH_UsrLog("MSC Device ready"); + } + else + { + MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 0U; + } + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_READ_CAPACITY10; + MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_OK; + MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state = USBH_OK; + } + if (ready_status == USBH_FAIL) + { + /* Media not ready, so try to check again during 10s */ + if (MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state != USBH_FAIL) + { + MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 1U; + USBH_UsrLog("MSC Device NOT ready"); + } + else + { + MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 0U; + } + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_REQUEST_SENSE; + MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_NOT_READY; + MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state = USBH_FAIL; + } + else + { + if (ready_status == USBH_UNRECOVERED_ERROR) + { + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE; + MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR; + } + } + break; + + case MSC_READ_CAPACITY10: + scsi_status = USBH_MSC_SCSI_ReadCapacity(phost, (uint8_t)MSC_Handle->current_lun, &MSC_Handle->unit[MSC_Handle->current_lun].capacity) ; + + if (scsi_status == USBH_OK) + { + if (MSC_Handle->unit[MSC_Handle->current_lun].state_changed == 1U) + { + USBH_UsrLog("MSC Device capacity : %lu Bytes", \ + (int32_t)(MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_nbr * MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_size)); + USBH_UsrLog("Block number : %lu", (int32_t)(MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_nbr)); + USBH_UsrLog("Block Size : %lu", (int32_t)(MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_size)); + } + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE; + MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_OK; + MSC_Handle->current_lun++; + } + else if (scsi_status == USBH_FAIL) + { + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_REQUEST_SENSE; + } + else + { + if (scsi_status == USBH_UNRECOVERED_ERROR) + { + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE; + MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR; + } + } + break; + + case MSC_REQUEST_SENSE: + scsi_status = USBH_MSC_SCSI_RequestSense(phost, (uint8_t)MSC_Handle->current_lun, &MSC_Handle->unit[MSC_Handle->current_lun].sense); + + if (scsi_status == USBH_OK) + { + if ((MSC_Handle->unit[MSC_Handle->current_lun].sense.key == SCSI_SENSE_KEY_UNIT_ATTENTION) || + (MSC_Handle->unit[MSC_Handle->current_lun].sense.key == SCSI_SENSE_KEY_NOT_READY)) + { + + if ((phost->Timer - MSC_Handle->timer) < 10000U) + { + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_TEST_UNIT_READY; + break; + } + } + + USBH_UsrLog("Sense Key : %x", MSC_Handle->unit[MSC_Handle->current_lun].sense.key); + USBH_UsrLog("Additional Sense Code : %x", MSC_Handle->unit[MSC_Handle->current_lun].sense.asc); + USBH_UsrLog("Additional Sense Code Qualifier: %x", MSC_Handle->unit[MSC_Handle->current_lun].sense.ascq); + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE; + MSC_Handle->current_lun++; + } + if (scsi_status == USBH_FAIL) + { + USBH_UsrLog("MSC Device NOT ready"); + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_UNRECOVERED_ERROR; + } + else + { + if (scsi_status == USBH_UNRECOVERED_ERROR) + { + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE; + MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR; + } + } + break; + + case MSC_UNRECOVERED_ERROR: + MSC_Handle->current_lun++; + break; + + default: + break; + } + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_CLASS_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 + } + else + { + MSC_Handle->current_lun = 0U; + MSC_Handle->state = MSC_IDLE; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_CLASS_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 + phost->pUser(phost, HOST_USER_CLASS_ACTIVE); + } + break; + + case MSC_IDLE: + error = USBH_OK; + break; + + default: + break; + } + return error; +} + + +/** + * @brief USBH_MSC_SOFProcess + * The function is for SOF state + * @param phost: Host handle + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_MSC_SOFProcess(USBH_HandleTypeDef *phost) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(phost); + + return USBH_OK; +} +/** + * @brief USBH_MSC_RdWrProcess + * The function is for managing state machine for MSC I/O Process + * @param phost: Host handle + * @param lun: logical Unit Number + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_MSC_RdWrProcess(USBH_HandleTypeDef *phost, uint8_t lun) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + USBH_StatusTypeDef error = USBH_BUSY ; + USBH_StatusTypeDef scsi_status = USBH_BUSY ; + + /* Switch MSC REQ state machine */ + switch (MSC_Handle->unit[lun].state) + { + + case MSC_READ: + scsi_status = USBH_MSC_SCSI_Read(phost, lun, 0U, NULL, 0U); + + if (scsi_status == USBH_OK) + { + MSC_Handle->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } + else if (scsi_status == USBH_FAIL) + { + MSC_Handle->unit[lun].state = MSC_REQUEST_SENSE; + } + else + { + if (scsi_status == USBH_UNRECOVERED_ERROR) + { + MSC_Handle->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_CLASS_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 + break; + + case MSC_WRITE: + scsi_status = USBH_MSC_SCSI_Write(phost, lun, 0U, NULL, 0U); + + if (scsi_status == USBH_OK) + { + MSC_Handle->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } + else if (scsi_status == USBH_FAIL) + { + MSC_Handle->unit[lun].state = MSC_REQUEST_SENSE; + } + else + { + if (scsi_status == USBH_UNRECOVERED_ERROR) + { + MSC_Handle->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_CLASS_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 + break; + + case MSC_REQUEST_SENSE: + scsi_status = USBH_MSC_SCSI_RequestSense(phost, lun, &MSC_Handle->unit[lun].sense); + + if (scsi_status == USBH_OK) + { + USBH_UsrLog("Sense Key : %x", MSC_Handle->unit[lun].sense.key); + USBH_UsrLog("Additional Sense Code : %x", MSC_Handle->unit[lun].sense.asc); + USBH_UsrLog("Additional Sense Code Qualifier: %x", MSC_Handle->unit[lun].sense.ascq); + MSC_Handle->unit[lun].state = MSC_IDLE; + MSC_Handle->unit[lun].error = MSC_ERROR; + + error = USBH_FAIL; + } + if (scsi_status == USBH_FAIL) + { + USBH_UsrLog("MSC Device NOT ready"); + } + else + { + if (scsi_status == USBH_UNRECOVERED_ERROR) + { + MSC_Handle->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_CLASS_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 + break; + + default: + break; + + } + return error; +} + +/** + * @brief USBH_MSC_IsReady + * The function check if the MSC function is ready + * @param phost: Host handle + * @retval USBH Status + */ +uint8_t USBH_MSC_IsReady(USBH_HandleTypeDef *phost) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + uint8_t res; + + if ((phost->gState == HOST_CLASS) && (MSC_Handle->state == MSC_IDLE)) + { + res = 1U; + } + else + { + res = 0U; + } + + return res; +} + +/** + * @brief USBH_MSC_GetMaxLUN + * The function return the Max LUN supported + * @param phost: Host handle + * @retval logical Unit Number supported + */ +uint8_t USBH_MSC_GetMaxLUN(USBH_HandleTypeDef *phost) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + if ((phost->gState == HOST_CLASS) && (MSC_Handle->state == MSC_IDLE)) + { + return (uint8_t)MSC_Handle->max_lun; + } + + return 0xFFU; +} + +/** + * @brief USBH_MSC_UnitIsReady + * The function check whether a LUN is ready + * @param phost: Host handle + * @param lun: logical Unit Number + * @retval Lun status (0: not ready / 1: ready) + */ +uint8_t USBH_MSC_UnitIsReady(USBH_HandleTypeDef *phost, uint8_t lun) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + uint8_t res; + + if ((phost->gState == HOST_CLASS) && (MSC_Handle->unit[lun].error == MSC_OK)) + { + res = 1U; + } + else + { + res = 0U; + } + + return res; +} + +/** + * @brief USBH_MSC_GetLUNInfo + * The function return a LUN information + * @param phost: Host handle + * @param lun: logical Unit Number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_GetLUNInfo(USBH_HandleTypeDef *phost, uint8_t lun, MSC_LUNTypeDef *info) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + if (phost->gState == HOST_CLASS) + { + USBH_memcpy(info, &MSC_Handle->unit[lun], sizeof(MSC_LUNTypeDef)); + return USBH_OK; + } + else + { + return USBH_FAIL; + } +} + +/** + * @brief USBH_MSC_Read + * The function performs a Read operation + * @param phost: Host handle + * @param lun: logical Unit Number + * @param address: sector address + * @param pbuf: pointer to data + * @param length: number of sector to read + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_Read(USBH_HandleTypeDef *phost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout; + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + if ((phost->device.is_connected == 0U) || + (phost->gState != HOST_CLASS) || + (MSC_Handle->unit[lun].state != MSC_IDLE)) + { + return USBH_FAIL; + } + + MSC_Handle->state = MSC_READ; + MSC_Handle->unit[lun].state = MSC_READ; + MSC_Handle->rw_lun = lun; + + USBH_MSC_SCSI_Read(phost, lun, address, pbuf, length); + + timeout = phost->Timer; + + while (USBH_MSC_RdWrProcess(phost, lun) == USBH_BUSY) + { + if (((phost->Timer - timeout) > (10000U * length)) || (phost->device.is_connected == 0U)) + { + MSC_Handle->state = MSC_IDLE; + return USBH_FAIL; + } + } + MSC_Handle->state = MSC_IDLE; + + return USBH_OK; +} + +/** + * @brief USBH_MSC_Write + * The function performs a Write operation + * @param phost: Host handle + * @param lun: logical Unit Number + * @param address: sector address + * @param pbuf: pointer to data + * @param length: number of sector to write + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_Write(USBH_HandleTypeDef *phost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout; + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + if ((phost->device.is_connected == 0U) || + (phost->gState != HOST_CLASS) || + (MSC_Handle->unit[lun].state != MSC_IDLE)) + { + return USBH_FAIL; + } + + MSC_Handle->state = MSC_WRITE; + MSC_Handle->unit[lun].state = MSC_WRITE; + MSC_Handle->rw_lun = lun; + + USBH_MSC_SCSI_Write(phost, lun, address, pbuf, length); + + timeout = phost->Timer; + while (USBH_MSC_RdWrProcess(phost, lun) == USBH_BUSY) + { + if (((phost->Timer - timeout) > (10000U * length)) || (phost->device.is_connected == 0U)) + { + MSC_Handle->state = MSC_IDLE; + return USBH_FAIL; + } + } + MSC_Handle->state = MSC_IDLE; + return USBH_OK; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + +#endif // USB_HOST_MSC_FLASH_SUPPORT +#endif // STM32 diff --git a/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_bot.cpp b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_bot.cpp new file mode 100644 index 000000000000..42bef03b14dc --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_bot.cpp @@ -0,0 +1,706 @@ +/** + ****************************************************************************** + * @file usbh_msc_bot.c + * @author MCD Application Team + * @brief This file includes the BOT protocol related functions + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 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 + * + ****************************************************************************** + */ + +#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC) + +#include "../../../../../../../inc/MarlinConfig.h" + +#if ENABLED(USB_HOST_MSC_FLASH_SUPPORT) + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +- "stm32xxxxx_{eval}{discovery}{adafruit}_lcd.c" +- "stm32xxxxx_{eval}{discovery}_sdram.c" +EndBSPDependencies */ + +/* Includes ------------------------------------------------------------------*/ +#include "../Inc/usbh_msc_bot.h" +#include "../Inc/usbh_msc.h" + +/** @addtogroup USBH_LIB +* @{ +*/ + +/** @addtogroup USBH_CLASS +* @{ +*/ + +/** @addtogroup USBH_MSC_CLASS +* @{ +*/ + +/** @defgroup USBH_MSC_BOT +* @brief This file includes the mass storage related functions +* @{ +*/ + + +/** @defgroup USBH_MSC_BOT_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + +/** @defgroup USBH_MSC_BOT_Private_Defines +* @{ +*/ +/** +* @} +*/ + +/** @defgroup USBH_MSC_BOT_Private_Macros +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_MSC_BOT_Private_Variables +* @{ +*/ + +/** +* @} +*/ + + +/** @defgroup USBH_MSC_BOT_Private_FunctionPrototypes +* @{ +*/ +static USBH_StatusTypeDef USBH_MSC_BOT_Abort(USBH_HandleTypeDef *phost, uint8_t lun, uint8_t dir); +static BOT_CSWStatusTypeDef USBH_MSC_DecodeCSW(USBH_HandleTypeDef *phost); +/** +* @} +*/ + + +/** @defgroup USBH_MSC_BOT_Exported_Variables +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_MSC_BOT_Private_Functions +* @{ +*/ + +/** + * @brief USBH_MSC_BOT_REQ_Reset + * The function the MSC BOT Reset request. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_BOT_REQ_Reset(USBH_HandleTypeDef *phost) +{ + + phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_TYPE_CLASS + | USB_REQ_RECIPIENT_INTERFACE; + + phost->Control.setup.b.bRequest = USB_REQ_BOT_RESET; + phost->Control.setup.b.wValue.w = 0U; + phost->Control.setup.b.wIndex.w = 0U; + phost->Control.setup.b.wLength.w = 0U; + + return USBH_CtlReq(phost, 0U, 0U); +} + +/** + * @brief USBH_MSC_BOT_REQ_GetMaxLUN + * The function the MSC BOT GetMaxLUN request. + * @param phost: Host handle + * @param Maxlun: pointer to Maxlun variable + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_BOT_REQ_GetMaxLUN(USBH_HandleTypeDef *phost, uint8_t *Maxlun) +{ + phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_TYPE_CLASS + | USB_REQ_RECIPIENT_INTERFACE; + + phost->Control.setup.b.bRequest = USB_REQ_GET_MAX_LUN; + phost->Control.setup.b.wValue.w = 0U; + phost->Control.setup.b.wIndex.w = 0U; + phost->Control.setup.b.wLength.w = 1U; + + return USBH_CtlReq(phost, Maxlun, 1U); +} + + + +/** + * @brief USBH_MSC_BOT_Init + * The function Initializes the BOT protocol. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_BOT_Init(USBH_HandleTypeDef *phost) +{ + + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + MSC_Handle->hbot.cbw.field.Signature = BOT_CBW_SIGNATURE; + MSC_Handle->hbot.cbw.field.Tag = BOT_CBW_TAG; + MSC_Handle->hbot.state = BOT_SEND_CBW; + MSC_Handle->hbot.cmd_state = BOT_CMD_SEND; + + return USBH_OK; +} + + + +/** + * @brief USBH_MSC_BOT_Process + * The function handle the BOT protocol. + * @param phost: Host handle + * @param lun: Logical Unit Number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_BOT_Process(USBH_HandleTypeDef *phost, uint8_t lun) +{ + USBH_StatusTypeDef status = USBH_BUSY; + USBH_StatusTypeDef error = USBH_BUSY; + BOT_CSWStatusTypeDef CSW_Status = BOT_CSW_CMD_FAILED; + USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE; + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + uint8_t toggle = 0U; + + switch (MSC_Handle->hbot.state) + { + case BOT_SEND_CBW: + MSC_Handle->hbot.cbw.field.LUN = lun; + MSC_Handle->hbot.state = BOT_SEND_CBW_WAIT; + USBH_BulkSendData(phost, MSC_Handle->hbot.cbw.data, + BOT_CBW_LENGTH, MSC_Handle->OutPipe, 1U); + + break; + + case BOT_SEND_CBW_WAIT: + + URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe); + + if (URB_Status == USBH_URB_DONE) + { + if (MSC_Handle->hbot.cbw.field.DataTransferLength != 0U) + { + /* If there is Data Transfer Stage */ + if (((MSC_Handle->hbot.cbw.field.Flags) & USB_REQ_DIR_MASK) == USB_D2H) + { + /* Data Direction is IN */ + MSC_Handle->hbot.state = BOT_DATA_IN; + } + else + { + /* Data Direction is OUT */ + MSC_Handle->hbot.state = BOT_DATA_OUT; + } + } + + else + { + /* If there is NO Data Transfer Stage */ + MSC_Handle->hbot.state = BOT_RECEIVE_CSW; + } + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_URB_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 + } + else if (URB_Status == USBH_URB_NOTREADY) + { + /* Re-send CBW */ + MSC_Handle->hbot.state = BOT_SEND_CBW; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_URB_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 + } + else + { + if (URB_Status == USBH_URB_STALL) + { + MSC_Handle->hbot.state = BOT_ERROR_OUT; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_URB_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 + } + } + break; + + case BOT_DATA_IN: + /* Send first packet */ + USBH_BulkReceiveData(phost, MSC_Handle->hbot.pbuf, + MSC_Handle->InEpSize, MSC_Handle->InPipe); + + MSC_Handle->hbot.state = BOT_DATA_IN_WAIT; + + break; + + case BOT_DATA_IN_WAIT: + + URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe); + + if (URB_Status == USBH_URB_DONE) + { + /* Adjust Data pointer and data length */ + if (MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->InEpSize) + { + MSC_Handle->hbot.pbuf += MSC_Handle->InEpSize; + MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->InEpSize; + } + else + { + MSC_Handle->hbot.cbw.field.DataTransferLength = 0U; + } + + /* More Data To be Received */ + if (MSC_Handle->hbot.cbw.field.DataTransferLength > 0U) + { + /* Send next packet */ + USBH_BulkReceiveData(phost, MSC_Handle->hbot.pbuf, + MSC_Handle->InEpSize, MSC_Handle->InPipe); + } + else + { + /* If value was 0, and successful transfer, then change the state */ + MSC_Handle->hbot.state = BOT_RECEIVE_CSW; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_URB_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 + } + } + else if (URB_Status == USBH_URB_STALL) + { + /* This is Data IN Stage STALL Condition */ + MSC_Handle->hbot.state = BOT_ERROR_IN; + + /* Refer to USB Mass-Storage Class : BOT (www.usb.org) + 6.7.2 Host expects to receive data from the device + 3. On a STALL condition receiving data, then: + The host shall accept the data received. + The host shall clear the Bulk-In pipe. + 4. The host shall attempt to receive a CSW.*/ + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_URB_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 + } + else + { + } + break; + + case BOT_DATA_OUT: + + USBH_BulkSendData(phost, MSC_Handle->hbot.pbuf, + MSC_Handle->OutEpSize, MSC_Handle->OutPipe, 1U); + + MSC_Handle->hbot.state = BOT_DATA_OUT_WAIT; + break; + + case BOT_DATA_OUT_WAIT: + URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe); + + if (URB_Status == USBH_URB_DONE) + { + /* Adjust Data pointer and data length */ + if (MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->OutEpSize) + { + MSC_Handle->hbot.pbuf += MSC_Handle->OutEpSize; + MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->OutEpSize; + } + else + { + MSC_Handle->hbot.cbw.field.DataTransferLength = 0U; + } + + /* More Data To be Sent */ + if (MSC_Handle->hbot.cbw.field.DataTransferLength > 0U) + { + USBH_BulkSendData(phost, MSC_Handle->hbot.pbuf, + MSC_Handle->OutEpSize, MSC_Handle->OutPipe, 1U); + } + else + { + /* If value was 0, and successful transfer, then change the state */ + MSC_Handle->hbot.state = BOT_RECEIVE_CSW; + } + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_URB_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 + } + + else if (URB_Status == USBH_URB_NOTREADY) + { + /* Resend same data */ + MSC_Handle->hbot.state = BOT_DATA_OUT; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_URB_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 + } + + else if (URB_Status == USBH_URB_STALL) + { + MSC_Handle->hbot.state = BOT_ERROR_OUT; + + /* Refer to USB Mass-Storage Class : BOT (www.usb.org) + 6.7.3 Ho - Host expects to send data to the device + 3. On a STALL condition sending data, then: + " The host shall clear the Bulk-Out pipe. + 4. The host shall attempt to receive a CSW. + */ + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_URB_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 + } + else + { + } + break; + + case BOT_RECEIVE_CSW: + + USBH_BulkReceiveData(phost, MSC_Handle->hbot.csw.data, + BOT_CSW_LENGTH, MSC_Handle->InPipe); + + MSC_Handle->hbot.state = BOT_RECEIVE_CSW_WAIT; + break; + + case BOT_RECEIVE_CSW_WAIT: + + URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe); + + /* Decode CSW */ + if (URB_Status == USBH_URB_DONE) + { + MSC_Handle->hbot.state = BOT_SEND_CBW; + MSC_Handle->hbot.cmd_state = BOT_CMD_SEND; + CSW_Status = USBH_MSC_DecodeCSW(phost); + + if (CSW_Status == BOT_CSW_CMD_PASSED) + { + status = USBH_OK; + } + else + { + status = USBH_FAIL; + } + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_URB_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 + } + else if (URB_Status == USBH_URB_STALL) + { + MSC_Handle->hbot.state = BOT_ERROR_IN; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_URB_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 + } + else + { + } + break; + + case BOT_ERROR_IN: + error = USBH_MSC_BOT_Abort(phost, lun, BOT_DIR_IN); + + if (error == USBH_OK) + { + MSC_Handle->hbot.state = BOT_RECEIVE_CSW; + } + else if (error == USBH_UNRECOVERED_ERROR) + { + /* This means that there is a STALL Error limit, Do Reset Recovery */ + MSC_Handle->hbot.state = BOT_UNRECOVERED_ERROR; + } + else + { + } + break; + + case BOT_ERROR_OUT: + error = USBH_MSC_BOT_Abort(phost, lun, BOT_DIR_OUT); + + if (error == USBH_OK) + { + + toggle = USBH_LL_GetToggle(phost, MSC_Handle->OutPipe); + USBH_LL_SetToggle(phost, MSC_Handle->OutPipe, 1U - toggle); + USBH_LL_SetToggle(phost, MSC_Handle->InPipe, 0U); + MSC_Handle->hbot.state = BOT_ERROR_IN; + } + else + { + if (error == USBH_UNRECOVERED_ERROR) + { + MSC_Handle->hbot.state = BOT_UNRECOVERED_ERROR; + } + } + break; + + + case BOT_UNRECOVERED_ERROR: + status = USBH_MSC_BOT_REQ_Reset(phost); + if (status == USBH_OK) + { + MSC_Handle->hbot.state = BOT_SEND_CBW; + } + break; + + default: + break; + } + return status; +} + +/** + * @brief USBH_MSC_BOT_Abort + * The function handle the BOT Abort process. + * @param phost: Host handle + * @param lun: Logical Unit Number + * @param dir: direction (0: out / 1 : in) + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_MSC_BOT_Abort(USBH_HandleTypeDef *phost, uint8_t lun, uint8_t dir) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(lun); + + USBH_StatusTypeDef status = USBH_FAIL; + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + switch (dir) + { + case BOT_DIR_IN : + /* send ClrFeture on Bulk IN endpoint */ + status = USBH_ClrFeature(phost, MSC_Handle->InEp); + + break; + + case BOT_DIR_OUT : + /*send ClrFeature on Bulk OUT endpoint */ + status = USBH_ClrFeature(phost, MSC_Handle->OutEp); + break; + + default: + break; + } + return status; +} + +/** + * @brief USBH_MSC_BOT_DecodeCSW + * This function decodes the CSW received by the device and updates the + * same to upper layer. + * @param phost: Host handle + * @retval USBH Status + * @notes + * Refer to USB Mass-Storage Class : BOT (www.usb.org) + * 6.3.1 Valid CSW Conditions : + * The host shall consider the CSW valid when: + * 1. dCSWSignature is equal to 53425355h + * 2. the CSW is 13 (Dh) bytes in length, + * 3. dCSWTag matches the dCBWTag from the corresponding CBW. + */ + +static BOT_CSWStatusTypeDef USBH_MSC_DecodeCSW(USBH_HandleTypeDef *phost) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + BOT_CSWStatusTypeDef status = BOT_CSW_CMD_FAILED; + + /*Checking if the transfer length is different than 13*/ + if (USBH_LL_GetLastXferSize(phost, MSC_Handle->InPipe) != BOT_CSW_LENGTH) + { + /*(4) Hi > Dn (Host expects to receive data from the device, + Device intends to transfer no data) + (5) Hi > Di (Host expects to receive data from the device, + Device intends to send data to the host) + (9) Ho > Dn (Host expects to send data to the device, + Device intends to transfer no data) + (11) Ho > Do (Host expects to send data to the device, + Device intends to receive data from the host)*/ + + + status = BOT_CSW_PHASE_ERROR; + } + else + { + /* CSW length is Correct */ + + /* Check validity of the CSW Signature and CSWStatus */ + if (MSC_Handle->hbot.csw.field.Signature == BOT_CSW_SIGNATURE) + { + /* Check Condition 1. dCSWSignature is equal to 53425355h */ + + if (MSC_Handle->hbot.csw.field.Tag == MSC_Handle->hbot.cbw.field.Tag) + { + /* Check Condition 3. dCSWTag matches the dCBWTag from the + corresponding CBW */ + + if (MSC_Handle->hbot.csw.field.Status == 0U) + { + /* Refer to USB Mass-Storage Class : BOT (www.usb.org) + + Hn Host expects no data transfers + Hi Host expects to receive data from the device + Ho Host expects to send data to the device + + Dn Device intends to transfer no data + Di Device intends to send data to the host + Do Device intends to receive data from the host + + Section 6.7 + (1) Hn = Dn (Host expects no data transfers, + Device intends to transfer no data) + (6) Hi = Di (Host expects to receive data from the device, + Device intends to send data to the host) + (12) Ho = Do (Host expects to send data to the device, + Device intends to receive data from the host) + + */ + + status = BOT_CSW_CMD_PASSED; + } + else if (MSC_Handle->hbot.csw.field.Status == 1U) + { + status = BOT_CSW_CMD_FAILED; + } + + else if (MSC_Handle->hbot.csw.field.Status == 2U) + { + /* Refer to USB Mass-Storage Class : BOT (www.usb.org) + Section 6.7 + (2) Hn < Di ( Host expects no data transfers, + Device intends to send data to the host) + (3) Hn < Do ( Host expects no data transfers, + Device intends to receive data from the host) + (7) Hi < Di ( Host expects to receive data from the device, + Device intends to send data to the host) + (8) Hi <> Do ( Host expects to receive data from the device, + Device intends to receive data from the host) + (10) Ho <> Di (Host expects to send data to the device, + Di Device intends to send data to the host) + (13) Ho < Do (Host expects to send data to the device, + Device intends to receive data from the host) + */ + + status = BOT_CSW_PHASE_ERROR; + } + else + { + } + } /* CSW Tag Matching is Checked */ + } /* CSW Signature Correct Checking */ + else + { + /* If the CSW Signature is not valid, We sall return the Phase Error to + Upper Layers for Reset Recovery */ + + status = BOT_CSW_PHASE_ERROR; + } + } /* CSW Length Check*/ + + return status; +} + + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + +#endif // USB_HOST_MSC_FLASH_SUPPORT +#endif // STM32 diff --git a/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_scsi.cpp b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_scsi.cpp new file mode 100644 index 000000000000..373d43a5c9a6 --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_scsi.cpp @@ -0,0 +1,472 @@ +/** + ****************************************************************************** + * @file usbh_msc_scsi.c + * @author MCD Application Team + * @brief This file implements the SCSI commands + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 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 + * + ****************************************************************************** + */ + +#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC) + +#include "../../../../../../../inc/MarlinConfig.h" + +#if ENABLED(USB_HOST_MSC_FLASH_SUPPORT) + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +- "stm32xxxxx_{eval}{discovery}{adafruit}_lcd.c" +- "stm32xxxxx_{eval}{discovery}_sdram.c" +EndBSPDependencies */ + +/* Includes ------------------------------------------------------------------*/ +#include "../Inc/usbh_msc.h" +#include "../Inc/usbh_msc_scsi.h" +#include "../Inc/usbh_msc_bot.h" + + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_CLASS + * @{ + */ + +/** @addtogroup USBH_MSC_CLASS + * @{ + */ + +/** @defgroup USBH_MSC_SCSI + * @brief This file includes the mass storage related functions + * @{ + */ + + +/** @defgroup USBH_MSC_SCSI_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBH_MSC_SCSI_Private_Defines + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_MSC_SCSI_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_MSC_SCSI_Private_FunctionPrototypes + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_MSC_SCSI_Exported_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBH_MSC_SCSI_Private_Functions + * @{ + */ + + +/** + * @brief USBH_MSC_SCSI_TestUnitReady + * Issue TestUnitReady command. + * @param phost: Host handle + * @param lun: Logical Unit Number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_SCSI_TestUnitReady(USBH_HandleTypeDef *phost, + uint8_t lun) +{ + USBH_StatusTypeDef error = USBH_FAIL ; + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + switch (MSC_Handle->hbot.cmd_state) + { + case BOT_CMD_SEND: + + /*Prepare the CBW and relevent field*/ + MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_MODE_TEST_UNIT_READY; + MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_OUT; + MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; + + USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH); + MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_TEST_UNIT_READY; + + MSC_Handle->hbot.state = BOT_SEND_CBW; + MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + error = USBH_MSC_BOT_Process(phost, lun); + break; + + default: + break; + } + + return error; +} + +/** + * @brief USBH_MSC_SCSI_ReadCapacity + * Issue Read Capacity command. + * @param phost: Host handle + * @param lun: Logical Unit Number + * @param capacity: pointer to the capacity structure + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_SCSI_ReadCapacity(USBH_HandleTypeDef *phost, + uint8_t lun, + SCSI_CapacityTypeDef *capacity) +{ + USBH_StatusTypeDef error = USBH_BUSY ; + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + switch (MSC_Handle->hbot.cmd_state) + { + case BOT_CMD_SEND: + + /*Prepare the CBW and relevent field*/ + MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_READ_CAPACITY10; + MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN; + MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; + + USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH); + MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_READ_CAPACITY10; + + MSC_Handle->hbot.state = BOT_SEND_CBW; + + MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; + MSC_Handle->hbot.pbuf = (uint8_t *)(void *)MSC_Handle->hbot.data; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + + error = USBH_MSC_BOT_Process(phost, lun); + + if (error == USBH_OK) + { + /*assign the capacity*/ + capacity->block_nbr = MSC_Handle->hbot.pbuf[3] | ((uint32_t)MSC_Handle->hbot.pbuf[2] << 8U) | \ + ((uint32_t)MSC_Handle->hbot.pbuf[1] << 16U) | ((uint32_t)MSC_Handle->hbot.pbuf[0] << 24U); + + /*assign the page length*/ + capacity->block_size = (uint16_t)(MSC_Handle->hbot.pbuf[7] | ((uint32_t)MSC_Handle->hbot.pbuf[6] << 8U)); + } + break; + + default: + break; + } + + return error; +} + +/** + * @brief USBH_MSC_SCSI_Inquiry + * Issue Inquiry command. + * @param phost: Host handle + * @param lun: Logical Unit Number + * @param capacity: pointer to the inquiry structure + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_SCSI_Inquiry(USBH_HandleTypeDef *phost, uint8_t lun, + SCSI_StdInquiryDataTypeDef *inquiry) +{ + USBH_StatusTypeDef error = USBH_FAIL; + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + switch (MSC_Handle->hbot.cmd_state) + { + case BOT_CMD_SEND: + + /*Prepare the CBW and relevent field*/ + MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_INQUIRY; + MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN; + MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; + + USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_LENGTH); + MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_INQUIRY; + MSC_Handle->hbot.cbw.field.CB[1] = (lun << 5); + MSC_Handle->hbot.cbw.field.CB[2] = 0U; + MSC_Handle->hbot.cbw.field.CB[3] = 0U; + MSC_Handle->hbot.cbw.field.CB[4] = 0x24U; + MSC_Handle->hbot.cbw.field.CB[5] = 0U; + + MSC_Handle->hbot.state = BOT_SEND_CBW; + + MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; + MSC_Handle->hbot.pbuf = (uint8_t *)(void *)MSC_Handle->hbot.data; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + + error = USBH_MSC_BOT_Process(phost, lun); + + if (error == USBH_OK) + { + USBH_memset(inquiry, 0, sizeof(SCSI_StdInquiryDataTypeDef)); + /*assign Inquiry Data */ + inquiry->DeviceType = MSC_Handle->hbot.pbuf[0] & 0x1FU; + inquiry->PeripheralQualifier = MSC_Handle->hbot.pbuf[0] >> 5U; + + if (((uint32_t)MSC_Handle->hbot.pbuf[1] & 0x80U) == 0x80U) + { + inquiry->RemovableMedia = 1U; + } + else + { + inquiry->RemovableMedia = 0U; + } + + USBH_memcpy(inquiry->vendor_id, &MSC_Handle->hbot.pbuf[8], 8U); + USBH_memcpy(inquiry->product_id, &MSC_Handle->hbot.pbuf[16], 16U); + USBH_memcpy(inquiry->revision_id, &MSC_Handle->hbot.pbuf[32], 4U); + } + break; + + default: + break; + } + + return error; +} + +/** + * @brief USBH_MSC_SCSI_RequestSense + * Issue RequestSense command. + * @param phost: Host handle + * @param lun: Logical Unit Number + * @param capacity: pointer to the sense data structure + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_SCSI_RequestSense(USBH_HandleTypeDef *phost, + uint8_t lun, + SCSI_SenseTypeDef *sense_data) +{ + USBH_StatusTypeDef error = USBH_FAIL ; + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + switch (MSC_Handle->hbot.cmd_state) + { + case BOT_CMD_SEND: + + /*Prepare the CBW and relevent field*/ + MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_REQUEST_SENSE; + MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN; + MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; + + USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH); + MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_REQUEST_SENSE; + MSC_Handle->hbot.cbw.field.CB[1] = (lun << 5); + MSC_Handle->hbot.cbw.field.CB[2] = 0U; + MSC_Handle->hbot.cbw.field.CB[3] = 0U; + MSC_Handle->hbot.cbw.field.CB[4] = DATA_LEN_REQUEST_SENSE; + MSC_Handle->hbot.cbw.field.CB[5] = 0U; + + MSC_Handle->hbot.state = BOT_SEND_CBW; + MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; + MSC_Handle->hbot.pbuf = (uint8_t *)(void *)MSC_Handle->hbot.data; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + + error = USBH_MSC_BOT_Process(phost, lun); + + if (error == USBH_OK) + { + sense_data->key = MSC_Handle->hbot.pbuf[2] & 0x0FU; + sense_data->asc = MSC_Handle->hbot.pbuf[12]; + sense_data->ascq = MSC_Handle->hbot.pbuf[13]; + } + break; + + default: + break; + } + + return error; +} + +/** + * @brief USBH_MSC_SCSI_Write + * Issue write10 command. + * @param phost: Host handle + * @param lun: Logical Unit Number + * @param address: sector address + * @param pbuf: pointer to data + * @param length: number of sector to write + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_SCSI_Write(USBH_HandleTypeDef *phost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + USBH_StatusTypeDef error = USBH_FAIL ; + + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + switch (MSC_Handle->hbot.cmd_state) + { + case BOT_CMD_SEND: + + /*Prepare the CBW and relevent field*/ + MSC_Handle->hbot.cbw.field.DataTransferLength = length * MSC_Handle->unit[0].capacity.block_size; + MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_OUT; + MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; + + USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH); + MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_WRITE10; + + /*logical block address*/ + MSC_Handle->hbot.cbw.field.CB[2] = (((uint8_t *)(void *)&address)[3]); + MSC_Handle->hbot.cbw.field.CB[3] = (((uint8_t *)(void *)&address)[2]); + MSC_Handle->hbot.cbw.field.CB[4] = (((uint8_t *)(void *)&address)[1]); + MSC_Handle->hbot.cbw.field.CB[5] = (((uint8_t *)(void *)&address)[0]); + + + /*Transfer length */ + MSC_Handle->hbot.cbw.field.CB[7] = (((uint8_t *)(void *)&length)[1]) ; + MSC_Handle->hbot.cbw.field.CB[8] = (((uint8_t *)(void *)&length)[0]) ; + + + MSC_Handle->hbot.state = BOT_SEND_CBW; + MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; + MSC_Handle->hbot.pbuf = pbuf; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + error = USBH_MSC_BOT_Process(phost, lun); + break; + + default: + break; + } + + return error; +} + +/** + * @brief USBH_MSC_SCSI_Read + * Issue Read10 command. + * @param phost: Host handle + * @param lun: Logical Unit Number + * @param address: sector address + * @param pbuf: pointer to data + * @param length: number of sector to read + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_SCSI_Read(USBH_HandleTypeDef *phost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + USBH_StatusTypeDef error = USBH_FAIL ; + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + switch (MSC_Handle->hbot.cmd_state) + { + case BOT_CMD_SEND: + + /*Prepare the CBW and relevent field*/ + MSC_Handle->hbot.cbw.field.DataTransferLength = length * MSC_Handle->unit[0].capacity.block_size; + MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN; + MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; + + USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH); + MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_READ10; + + /*logical block address*/ + MSC_Handle->hbot.cbw.field.CB[2] = (((uint8_t *)(void *)&address)[3]); + MSC_Handle->hbot.cbw.field.CB[3] = (((uint8_t *)(void *)&address)[2]); + MSC_Handle->hbot.cbw.field.CB[4] = (((uint8_t *)(void *)&address)[1]); + MSC_Handle->hbot.cbw.field.CB[5] = (((uint8_t *)(void *)&address)[0]); + + + /*Transfer length */ + MSC_Handle->hbot.cbw.field.CB[7] = (((uint8_t *)(void *)&length)[1]) ; + MSC_Handle->hbot.cbw.field.CB[8] = (((uint8_t *)(void *)&length)[0]) ; + + + MSC_Handle->hbot.state = BOT_SEND_CBW; + MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; + MSC_Handle->hbot.pbuf = pbuf; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + error = USBH_MSC_BOT_Process(phost, lun); + break; + + default: + break; + } + + return error; +} + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + +#endif // USB_HOST_MSC_FLASH_SUPPORT +#endif // STM32 diff --git a/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Inc/usbh_core.h b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Inc/usbh_core.h new file mode 100644 index 000000000000..8f059de2bc1e --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Inc/usbh_core.h @@ -0,0 +1,192 @@ +/** + ****************************************************************************** + * @file usbh_core.h + * @author MCD Application Team + * @brief Header file for usbh_core.c + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 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 + * + ****************************************************************************** + */ +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_CORE_H +#define __USBH_CORE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "../../../usbh_conf.h" +#include "usbh_def.h" +#include "usbh_ioreq.h" +#include "usbh_pipes.h" +#include "usbh_ctlreq.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_CORE + * @brief This file is the Header file for usbh_core.c + * @{ + */ + + +/** @defgroup USBH_CORE_Exported_Defines + * @{ + */ + +/** + * @} + */ +#define HOST_USER_SELECT_CONFIGURATION 0x01U +#define HOST_USER_CLASS_ACTIVE 0x02U +#define HOST_USER_CLASS_SELECTED 0x03U +#define HOST_USER_CONNECTION 0x04U +#define HOST_USER_DISCONNECTION 0x05U +#define HOST_USER_UNRECOVERED_ERROR 0x06U + + +/** + * @} + */ + + + +/** @defgroup USBH_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBH_CORE_Exported_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBH_CORE_Exported_FunctionsPrototype + * @{ + */ + + +USBH_StatusTypeDef USBH_Init(USBH_HandleTypeDef *phost, void (*pUsrFunc)(USBH_HandleTypeDef *phost, uint8_t id), uint8_t id); +USBH_StatusTypeDef USBH_DeInit(USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_RegisterClass(USBH_HandleTypeDef *phost, USBH_ClassTypeDef *pclass); +USBH_StatusTypeDef USBH_SelectInterface(USBH_HandleTypeDef *phost, uint8_t interface); +uint8_t USBH_FindInterface(USBH_HandleTypeDef *phost, + uint8_t Class, + uint8_t SubClass, + uint8_t Protocol); +uint8_t USBH_GetActiveClass(USBH_HandleTypeDef *phost); + +uint8_t USBH_FindInterfaceIndex(USBH_HandleTypeDef *phost, + uint8_t interface_number, + uint8_t alt_settings); + +uint8_t USBH_IsPortEnabled(USBH_HandleTypeDef *phost); + +USBH_StatusTypeDef USBH_Start(USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_Stop(USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_Process(USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_ReEnumerate(USBH_HandleTypeDef *phost); + +/* USBH Low Level Driver */ +USBH_StatusTypeDef USBH_LL_Init(USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_LL_DeInit(USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_LL_Start(USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_LL_Stop(USBH_HandleTypeDef *phost); + +USBH_StatusTypeDef USBH_LL_Connect(USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_LL_Disconnect(USBH_HandleTypeDef *phost); +USBH_SpeedTypeDef USBH_LL_GetSpeed(USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_LL_ResetPort(USBH_HandleTypeDef *phost); +uint32_t USBH_LL_GetLastXferSize(USBH_HandleTypeDef *phost, + uint8_t pipe); + +USBH_StatusTypeDef USBH_LL_DriverVBUS(USBH_HandleTypeDef *phost, + uint8_t state); + +USBH_StatusTypeDef USBH_LL_OpenPipe(USBH_HandleTypeDef *phost, + uint8_t pipe, + uint8_t epnum, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps); + +USBH_StatusTypeDef USBH_LL_ClosePipe(USBH_HandleTypeDef *phost, + uint8_t pipe); + +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); + +USBH_URBStateTypeDef USBH_LL_GetURBState(USBH_HandleTypeDef *phost, + uint8_t pipe); + +#if (USBH_USE_OS == 1U) +USBH_StatusTypeDef USBH_LL_NotifyURBChange(USBH_HandleTypeDef *phost); +#endif + +USBH_StatusTypeDef USBH_LL_SetToggle(USBH_HandleTypeDef *phost, + uint8_t pipe, uint8_t toggle); + +uint8_t USBH_LL_GetToggle(USBH_HandleTypeDef *phost, uint8_t pipe); + +void USBH_LL_PortDisabled(USBH_HandleTypeDef *phost); +void USBH_LL_PortEnabled(USBH_HandleTypeDef *phost); + +/* USBH Time base */ +void USBH_LL_SetTimer(USBH_HandleTypeDef *phost, uint32_t time); +void USBH_LL_IncTimer(USBH_HandleTypeDef *phost); + +void USBH_Delay(uint32_t Delay); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_CORE_H */ +/** + * @} + */ + +/** + * @} + */ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + diff --git a/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Inc/usbh_ctlreq.h b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Inc/usbh_ctlreq.h new file mode 100644 index 000000000000..5fef83f3c02d --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Inc/usbh_ctlreq.h @@ -0,0 +1,141 @@ +/** + ****************************************************************************** + * @file usbh_ctlreq.h + * @author MCD Application Team + * @brief Header file for usbh_ctlreq.c + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 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 + * + ****************************************************************************** + */ + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_CTLREQ_H +#define __USBH_CTLREQ_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_core.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_CTLREQ + * @brief This file is the + * @{ + */ + + +/** @defgroup USBH_CTLREQ_Exported_Defines + * @{ + */ +/*Standard Feature Selector for clear feature command*/ +#define FEATURE_SELECTOR_ENDPOINT 0x00U +#define FEATURE_SELECTOR_DEVICE 0x01U +#define FEATURE_SELECTOR_REMOTEWAKEUP 0X01U + + +#define INTERFACE_DESC_TYPE 0x04U +#define ENDPOINT_DESC_TYPE 0x05U +#define INTERFACE_DESC_SIZE 0x09U + +/** + * @} + */ + + +/** @defgroup USBH_CTLREQ_Exported_Types + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_CTLREQ_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_CTLREQ_Exported_Variables + * @{ + */ +extern uint8_t USBH_CfgDesc[512]; +/** + * @} + */ + +/** @defgroup USBH_CTLREQ_Exported_FunctionsPrototype + * @{ + */ +USBH_StatusTypeDef USBH_CtlReq(USBH_HandleTypeDef *phost, uint8_t *buff, + uint16_t length); + +USBH_StatusTypeDef USBH_GetDescriptor(USBH_HandleTypeDef *phost, + uint8_t req_type, uint16_t value_idx, + uint8_t *buff, uint16_t length); + +USBH_StatusTypeDef USBH_Get_DevDesc(USBH_HandleTypeDef *phost, uint8_t length); + +USBH_StatusTypeDef USBH_Get_StringDesc(USBH_HandleTypeDef *phost, + uint8_t string_index, uint8_t *buff, + uint16_t length); + +USBH_StatusTypeDef USBH_SetCfg(USBH_HandleTypeDef *phost, uint16_t cfg_idx); + +USBH_StatusTypeDef USBH_Get_CfgDesc(USBH_HandleTypeDef *phost, uint16_t length); + +USBH_StatusTypeDef USBH_SetAddress(USBH_HandleTypeDef *phost, + uint8_t DeviceAddress); + +USBH_StatusTypeDef USBH_SetInterface(USBH_HandleTypeDef *phost, uint8_t ep_num, + uint8_t altSetting); + +USBH_StatusTypeDef USBH_SetFeature(USBH_HandleTypeDef *phost, uint8_t wValue); + +USBH_StatusTypeDef USBH_ClrFeature(USBH_HandleTypeDef *phost, uint8_t ep_num); + +USBH_DescHeader_t *USBH_GetNextDesc(uint8_t *pbuf, uint16_t *ptr); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_CTLREQ_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + diff --git a/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Inc/usbh_def.h b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Inc/usbh_def.h new file mode 100644 index 000000000000..69b2b3567a98 --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Inc/usbh_def.h @@ -0,0 +1,500 @@ +/** + ****************************************************************************** + * @file usbh_def.h + * @author MCD Application Team + * @brief Definitions used in the USB host library + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 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 + * + ****************************************************************************** + */ + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef USBH_DEF_H +#define USBH_DEF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "../../../usbh_conf.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_DEF + * @brief This file is includes USB descriptors + * @{ + */ + +#ifndef NULL +#define NULL 0U +#endif + +#ifndef FALSE +#define FALSE 0U +#endif + +#ifndef TRUE +#define TRUE 1U +#endif + +#ifndef USBH_DEV_RESET_TIMEOUT +#define USBH_DEV_RESET_TIMEOUT 1000U +#endif + +#define ValBit(VAR,POS) (VAR & (1 << POS)) +#define SetBit(VAR,POS) (VAR |= (1 << POS)) +#define ClrBit(VAR,POS) (VAR &= ((1 << POS)^255)) + +#define LE16(addr) (((uint16_t)(addr)[0]) | \ + ((uint16_t)(((uint32_t)(addr)[1]) << 8))) + +#define LE24(addr) (((uint32_t)(addr)[0]) | \ + (((uint32_t)(addr)[1]) << 8) | \ + (((uint32_t)(addr)[2]) << 16)) + +#define LE32(addr) (((uint32_t)(addr)[0]) | \ + (((uint32_t)(addr)[1]) << 8) | \ + (((uint32_t)(addr)[2]) << 16) | \ + (((uint32_t)(addr)[3]) << 24)) + +#define LE64(addr) (((uint64_t)(addr)[0]) | \ + (((uint64_t)(addr)[1]) << 8) | \ + (((uint64_t)(addr)[2]) << 16) | \ + (((uint64_t)(addr)[3]) << 24) | \ + (((uint64_t)(addr)[4]) << 32) | \ + (((uint64_t)(addr)[5]) << 40) | \ + (((uint64_t)(addr)[6]) << 48) | \ + (((uint64_t)(addr)[7]) << 56)) + +#define LE16S(addr) ((int16_t)(LE16((addr)))) +#define LE24S(addr) ((int32_t)(LE24((addr)))) +#define LE32S(addr) ((int32_t)(LE32((addr)))) +#define LE64S(addr) ((int64_t)(LE64((addr)))) + + + +#define USB_LEN_DESC_HDR 0x02U +#define USB_LEN_DEV_DESC 0x12U +#define USB_LEN_CFG_DESC 0x09U +#define USB_LEN_IF_DESC 0x09U +#define USB_LEN_EP_DESC 0x07U +#define USB_LEN_OTG_DESC 0x03U +#define USB_LEN_SETUP_PKT 0x08U + +/* bmRequestType :D7 Data Phase Transfer Direction */ +#define USB_REQ_DIR_MASK 0x80U +#define USB_H2D 0x00U +#define USB_D2H 0x80U + +/* bmRequestType D6..5 Type */ +#define USB_REQ_TYPE_STANDARD 0x00U +#define USB_REQ_TYPE_CLASS 0x20U +#define USB_REQ_TYPE_VENDOR 0x40U +#define USB_REQ_TYPE_RESERVED 0x60U + +/* bmRequestType D4..0 Recipient */ +#define USB_REQ_RECIPIENT_DEVICE 0x00U +#define USB_REQ_RECIPIENT_INTERFACE 0x01U +#define USB_REQ_RECIPIENT_ENDPOINT 0x02U +#define USB_REQ_RECIPIENT_OTHER 0x03U + +/* Table 9-4. Standard Request Codes */ +/* bRequest , Value */ +#define USB_REQ_GET_STATUS 0x00U +#define USB_REQ_CLEAR_FEATURE 0x01U +#define USB_REQ_SET_FEATURE 0x03U +#define USB_REQ_SET_ADDRESS 0x05U +#define USB_REQ_GET_DESCRIPTOR 0x06U +#define USB_REQ_SET_DESCRIPTOR 0x07U +#define USB_REQ_GET_CONFIGURATION 0x08U +#define USB_REQ_SET_CONFIGURATION 0x09U +#define USB_REQ_GET_INTERFACE 0x0AU +#define USB_REQ_SET_INTERFACE 0x0BU +#define USB_REQ_SYNCH_FRAME 0x0CU + +/* Table 9-5. Descriptor Types of USB Specifications */ +#define USB_DESC_TYPE_DEVICE 0x01U +#define USB_DESC_TYPE_CONFIGURATION 0x02U +#define USB_DESC_TYPE_STRING 0x03U +#define USB_DESC_TYPE_INTERFACE 0x04U +#define USB_DESC_TYPE_ENDPOINT 0x05U +#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06U +#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07U +#define USB_DESC_TYPE_INTERFACE_POWER 0x08U +#define USB_DESC_TYPE_HID 0x21U +#define USB_DESC_TYPE_HID_REPORT 0x22U + + +#define USB_DEVICE_DESC_SIZE 0x12U +#define USB_CONFIGURATION_DESC_SIZE 0x09U +#define USB_HID_DESC_SIZE 0x09U +#define USB_INTERFACE_DESC_SIZE 0x09U +#define USB_ENDPOINT_DESC_SIZE 0x07U + +/* Descriptor Type and Descriptor Index */ +/* Use the following values when calling the function USBH_GetDescriptor */ +#define USB_DESC_DEVICE ((USB_DESC_TYPE_DEVICE << 8) & 0xFF00U) +#define USB_DESC_CONFIGURATION ((USB_DESC_TYPE_CONFIGURATION << 8) & 0xFF00U) +#define USB_DESC_STRING ((USB_DESC_TYPE_STRING << 8) & 0xFF00U) +#define USB_DESC_INTERFACE ((USB_DESC_TYPE_INTERFACE << 8) & 0xFF00U) +#define USB_DESC_ENDPOINT ((USB_DESC_TYPE_INTERFACE << 8) & 0xFF00U) +#define USB_DESC_DEVICE_QUALIFIER ((USB_DESC_TYPE_DEVICE_QUALIFIER << 8) & 0xFF00U) +#define USB_DESC_OTHER_SPEED_CONFIGURATION ((USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION << 8) & 0xFF00U) +#define USB_DESC_INTERFACE_POWER ((USB_DESC_TYPE_INTERFACE_POWER << 8) & 0xFF00U) +#define USB_DESC_HID_REPORT ((USB_DESC_TYPE_HID_REPORT << 8) & 0xFF00U) +#define USB_DESC_HID ((USB_DESC_TYPE_HID << 8) & 0xFF00U) + + +#define USB_EP_TYPE_CTRL 0x00U +#define USB_EP_TYPE_ISOC 0x01U +#define USB_EP_TYPE_BULK 0x02U +#define USB_EP_TYPE_INTR 0x03U + +#define USB_EP_DIR_OUT 0x00U +#define USB_EP_DIR_IN 0x80U +#define USB_EP_DIR_MSK 0x80U + +#ifndef USBH_MAX_PIPES_NBR +#define USBH_MAX_PIPES_NBR 15U +#endif /* USBH_MAX_PIPES_NBR */ + +#define USBH_DEVICE_ADDRESS_DEFAULT 0x00U +#define USBH_DEVICE_ADDRESS 0x01U + +#define USBH_MAX_ERROR_COUNT 0x02U + +#if (USBH_USE_OS == 1U) +#define MSGQUEUE_OBJECTS 0x10U +#endif + + +/** + * @} + */ + + +#define USBH_CONFIGURATION_DESCRIPTOR_SIZE (USB_CONFIGURATION_DESC_SIZE \ + + USB_INTERFACE_DESC_SIZE\ + + (USBH_MAX_NUM_ENDPOINTS * USB_ENDPOINT_DESC_SIZE)) + + +#define CONFIG_DESC_wTOTAL_LENGTH (ConfigurationDescriptorData.ConfigDescfield.\ + ConfigurationDescriptor.wTotalLength) + + +typedef union +{ + uint16_t w; + struct BW + { + uint8_t msb; + uint8_t lsb; + } + bw; +} +uint16_t_uint8_t; + + +typedef union _USB_Setup +{ + uint32_t d8[2]; + + struct _SetupPkt_Struc + { + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t_uint8_t wValue; + uint16_t_uint8_t wIndex; + uint16_t_uint8_t wLength; + } b; +} +USB_Setup_TypeDef; + +typedef struct _DescHeader +{ + uint8_t bLength; + uint8_t bDescriptorType; +} +USBH_DescHeader_t; + +typedef struct _DeviceDescriptor +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; /* USB Specification Number which device complies too */ + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + /* If equal to Zero, each interface specifies its own class + code if equal to 0xFF, the class code is vendor specified. + Otherwise field is valid Class Code.*/ + uint8_t bMaxPacketSize; + uint16_t idVendor; /* Vendor ID (Assigned by USB Org) */ + uint16_t idProduct; /* Product ID (Assigned by Manufacturer) */ + uint16_t bcdDevice; /* Device Release Number */ + uint8_t iManufacturer; /* Index of Manufacturer String Descriptor */ + uint8_t iProduct; /* Index of Product String Descriptor */ + uint8_t iSerialNumber; /* Index of Serial Number String Descriptor */ + uint8_t bNumConfigurations; /* Number of Possible Configurations */ +} +USBH_DevDescTypeDef; + +typedef struct _EndpointDescriptor +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; /* indicates what endpoint this descriptor is describing */ + uint8_t bmAttributes; /* specifies the transfer type. */ + uint16_t wMaxPacketSize; /* Maximum Packet Size this endpoint is capable of sending or receiving */ + uint8_t bInterval; /* is used to specify the polling interval of certain transfers. */ +} +USBH_EpDescTypeDef; + +typedef struct _InterfaceDescriptor +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; /* Value used to select alternative setting */ + uint8_t bNumEndpoints; /* Number of Endpoints used for this interface */ + uint8_t bInterfaceClass; /* Class Code (Assigned by USB Org) */ + 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_EpDescTypeDef Ep_Desc[USBH_MAX_NUM_ENDPOINTS]; +} +USBH_InterfaceDescTypeDef; + + +typedef struct _ConfigurationDescriptor +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; /* Total Length of Data Returned */ + uint8_t bNumInterfaces; /* Number of Interfaces */ + uint8_t bConfigurationValue; /* Value to use as an argument to select this configuration*/ + uint8_t iConfiguration; /*Index of String Descriptor Describing this configuration */ + uint8_t bmAttributes; /* D7 Bus Powered , D6 Self Powered, D5 Remote Wakeup , D4..0 Reserved (0)*/ + uint8_t bMaxPower; /*Maximum Power Consumption */ + USBH_InterfaceDescTypeDef Itf_Desc[USBH_MAX_NUM_INTERFACES]; +} +USBH_CfgDescTypeDef; + + +/* Following USB Host status */ +typedef enum +{ + USBH_OK = 0, + USBH_BUSY, + USBH_FAIL, + USBH_NOT_SUPPORTED, + USBH_UNRECOVERED_ERROR, + USBH_ERROR_SPEED_UNKNOWN, +} USBH_StatusTypeDef; + + +/** @defgroup USBH_CORE_Exported_Types + * @{ + */ + +typedef enum +{ + USBH_SPEED_HIGH = 0U, + USBH_SPEED_FULL = 1U, + USBH_SPEED_LOW = 2U, + +} USBH_SpeedTypeDef; + +/* Following states are used for gState */ +typedef enum +{ + HOST_IDLE = 0U, + HOST_DEV_WAIT_FOR_ATTACHMENT, + HOST_DEV_ATTACHED, + HOST_DEV_DISCONNECTED, + HOST_DETECT_DEVICE_SPEED, + HOST_ENUMERATION, + HOST_CLASS_REQUEST, + HOST_INPUT, + HOST_SET_CONFIGURATION, + HOST_SET_WAKEUP_FEATURE, + HOST_CHECK_CLASS, + HOST_CLASS, + HOST_SUSPENDED, + HOST_ABORT_STATE, +} HOST_StateTypeDef; + +/* Following states are used for EnumerationState */ +typedef enum +{ + ENUM_IDLE = 0U, + ENUM_GET_FULL_DEV_DESC, + ENUM_SET_ADDR, + ENUM_GET_CFG_DESC, + ENUM_GET_FULL_CFG_DESC, + ENUM_GET_MFC_STRING_DESC, + ENUM_GET_PRODUCT_STRING_DESC, + ENUM_GET_SERIALNUM_STRING_DESC, +} ENUM_StateTypeDef; + +/* Following states are used for CtrlXferStateMachine */ +typedef enum +{ + CTRL_IDLE = 0U, + CTRL_SETUP, + CTRL_SETUP_WAIT, + CTRL_DATA_IN, + CTRL_DATA_IN_WAIT, + CTRL_DATA_OUT, + CTRL_DATA_OUT_WAIT, + CTRL_STATUS_IN, + CTRL_STATUS_IN_WAIT, + CTRL_STATUS_OUT, + CTRL_STATUS_OUT_WAIT, + CTRL_ERROR, + CTRL_STALLED, + CTRL_COMPLETE +} CTRL_StateTypeDef; + + +/* Following states are used for RequestState */ +typedef enum +{ + CMD_IDLE = 0U, + CMD_SEND, + CMD_WAIT +} CMD_StateTypeDef; + +typedef enum +{ + USBH_URB_IDLE = 0U, + USBH_URB_DONE, + USBH_URB_NOTREADY, + USBH_URB_NYET, + USBH_URB_ERROR, + USBH_URB_STALL +} USBH_URBStateTypeDef; + +typedef enum +{ + USBH_PORT_EVENT = 1U, + USBH_URB_EVENT, + USBH_CONTROL_EVENT, + USBH_CLASS_EVENT, + USBH_STATE_CHANGED_EVENT, +} +USBH_OSEventTypeDef; + +/* Control request structure */ +typedef struct +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t pipe_size; + uint8_t *buff; + uint16_t length; + uint16_t timer; + USB_Setup_TypeDef setup; + CTRL_StateTypeDef state; + uint8_t errorcount; + +} USBH_CtrlTypeDef; + +/* Attached device structure */ +typedef struct +{ + uint8_t CfgDesc_Raw[USBH_MAX_SIZE_CONFIGURATION]; + uint8_t Data[USBH_MAX_DATA_BUFFER]; + uint8_t address; + uint8_t speed; + uint8_t EnumCnt; + uint8_t RstCnt; + __IO uint8_t is_connected; + __IO uint8_t is_disconnected; + __IO uint8_t is_ReEnumerated; + uint8_t PortEnabled; + uint8_t current_interface; + USBH_DevDescTypeDef DevDesc; + USBH_CfgDescTypeDef CfgDesc; +} USBH_DeviceTypeDef; + +struct _USBH_HandleTypeDef; + +/* USB Host Class structure */ +typedef struct +{ + const char *Name; + uint8_t ClassCode; + USBH_StatusTypeDef(*Init)(struct _USBH_HandleTypeDef *phost); + USBH_StatusTypeDef(*DeInit)(struct _USBH_HandleTypeDef *phost); + USBH_StatusTypeDef(*Requests)(struct _USBH_HandleTypeDef *phost); + USBH_StatusTypeDef(*BgndProcess)(struct _USBH_HandleTypeDef *phost); + USBH_StatusTypeDef(*SOFProcess)(struct _USBH_HandleTypeDef *phost); + void *pData; +} USBH_ClassTypeDef; + +/* USB Host handle structure */ +typedef struct _USBH_HandleTypeDef +{ + __IO HOST_StateTypeDef gState; /* Host State Machine Value */ + ENUM_StateTypeDef EnumState; /* Enumeration state Machine */ + CMD_StateTypeDef RequestState; + USBH_CtrlTypeDef Control; + USBH_DeviceTypeDef device; + USBH_ClassTypeDef *pClass[USBH_MAX_NUM_SUPPORTED_CLASS]; + USBH_ClassTypeDef *pActiveClass; + uint32_t ClassNumber; + uint32_t Pipes[16]; + __IO uint32_t Timer; + uint32_t Timeout; + uint8_t id; + void *pData; + void (* pUser)(struct _USBH_HandleTypeDef *pHandle, uint8_t id); + +#if (USBH_USE_OS == 1U) +#if osCMSIS < 0x20000 + osMessageQId os_event; + osThreadId thread; +#else + osMessageQueueId_t os_event; + osThreadId_t thread; +#endif + uint32_t os_msg; +#endif + +} USBH_HandleTypeDef; + + +#if defined ( __GNUC__ ) +#ifndef __weak +#define __weak __attribute__((weak)) +#endif /* __weak */ +#ifndef __packed +#define __packed __attribute__((__packed__)) +#endif /* __packed */ +#endif /* __GNUC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* USBH_DEF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Inc/usbh_ioreq.h b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Inc/usbh_ioreq.h new file mode 100644 index 000000000000..307bb2b696ff --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Inc/usbh_ioreq.h @@ -0,0 +1,160 @@ +/** + ****************************************************************************** + * @file usbh_ioreq.h + * @author MCD Application Team + * @brief Header file for usbh_ioreq.c + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 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 + * + ****************************************************************************** + */ + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_IOREQ_H +#define __USBH_IOREQ_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "../../../usbh_conf.h" +#include "usbh_core.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_IOREQ + * @brief This file is the header file for usbh_ioreq.c + * @{ + */ + + +/** @defgroup USBH_IOREQ_Exported_Defines + * @{ + */ + +#define USBH_PID_SETUP 0U +#define USBH_PID_DATA 1U + +#define USBH_EP_CONTROL 0U +#define USBH_EP_ISO 1U +#define USBH_EP_BULK 2U +#define USBH_EP_INTERRUPT 3U + +#define USBH_SETUP_PKT_SIZE 8U +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Exported_Types + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_IOREQ_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_IOREQ_Exported_FunctionsPrototype + * @{ + */ +USBH_StatusTypeDef USBH_CtlSendSetup(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint8_t pipe_num); + +USBH_StatusTypeDef USBH_CtlSendData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length, + uint8_t pipe_num, + uint8_t do_ping); + +USBH_StatusTypeDef USBH_CtlReceiveData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length, + uint8_t pipe_num); + +USBH_StatusTypeDef USBH_BulkReceiveData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length, + uint8_t pipe_num); + +USBH_StatusTypeDef USBH_BulkSendData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length, + uint8_t pipe_num, + uint8_t do_ping); + +USBH_StatusTypeDef USBH_InterruptReceiveData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint8_t length, + uint8_t pipe_num); + +USBH_StatusTypeDef USBH_InterruptSendData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint8_t length, + uint8_t pipe_num); + + +USBH_StatusTypeDef USBH_IsocReceiveData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint32_t length, + uint8_t pipe_num); + + +USBH_StatusTypeDef USBH_IsocSendData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint32_t length, + uint8_t pipe_num); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_IOREQ_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + diff --git a/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Inc/usbh_pipes.h b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Inc/usbh_pipes.h new file mode 100644 index 000000000000..a2b4c81b3d88 --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Inc/usbh_pipes.h @@ -0,0 +1,123 @@ +/** + ****************************************************************************** + * @file usbh_pipes.h + * @author MCD Application Team + * @brief Header file for usbh_pipes.c + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 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 + * + ****************************************************************************** + */ + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_PIPES_H +#define __USBH_PIPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_core.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_PIPES + * @brief This file is the header file for usbh_pipes.c + * @{ + */ + +/** @defgroup USBH_PIPES_Exported_Defines + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_PIPES_Exported_Types + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_PIPES_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_PIPES_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_PIPES_Exported_FunctionsPrototype + * @{ + */ + +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_StatusTypeDef USBH_ClosePipe(USBH_HandleTypeDef *phost, + uint8_t pipe_num); + +uint8_t USBH_AllocPipe(USBH_HandleTypeDef *phost, + uint8_t ep_addr); + +USBH_StatusTypeDef USBH_FreePipe(USBH_HandleTypeDef *phost, + uint8_t idx); + + + + +/** + * @} + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_PIPES_H */ + + +/** + * @} + */ + +/** + * @} + */ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + diff --git a/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Src/usbh_core.cpp b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Src/usbh_core.cpp new file mode 100644 index 000000000000..cc6f1b09db30 --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Src/usbh_core.cpp @@ -0,0 +1,1379 @@ +/** + ****************************************************************************** + * @file usbh_core.c + * @author MCD Application Team + * @brief This file implements the functions for the core state machine process + * the enumeration and the control transfer process + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 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 + * + ****************************************************************************** + */ + +#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC) + +#include "../../../../../../inc/MarlinConfig.h" + +#if ENABLED(USB_HOST_MSC_FLASH_SUPPORT) + +/* Includes ------------------------------------------------------------------*/ +#include "../Inc/usbh_core.h" + + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE + * @{ + */ + +/** @defgroup USBH_CORE + * @brief This file handles the basic enumeration when a device is connected + * to the host. + * @{ + */ + + +/** @defgroup USBH_CORE_Private_Defines + * @{ + */ +#define USBH_ADDRESS_DEFAULT 0x00U +#define USBH_ADDRESS_ASSIGNED 0x01U +#define USBH_MPS_DEFAULT 0x40U +/** + * @} + */ + +/** @defgroup USBH_CORE_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_CORE_Private_Variables + * @{ + */ +#if (USBH_USE_OS == 1U) +#if (osCMSIS >= 0x20000U) +osThreadAttr_t USBH_Thread_Atrr; +#endif +#endif + + +/** + * @} + */ + + +/** @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 == 1U) +#if (osCMSIS < 0x20000U) +static void USBH_Process_OS(void const *argument); +#else +static void USBH_Process_OS(void *argument); +#endif +#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 id), 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 = 0U; + + /* Restore default states and prepare EP0 */ + DeInitStateMachine(phost); + + /* Restore default Device connection states */ + phost->device.PortEnabled = 0U; + phost->device.is_connected = 0U; + phost->device.is_disconnected = 0U; + phost->device.is_ReEnumerated = 0U; + + /* Assign User process */ + if (pUsrFunc != NULL) + { + phost->pUser = pUsrFunc; + } + +#if (USBH_USE_OS == 1U) +#if (osCMSIS < 0x20000U) + + /* Create USB Host Queue */ + osMessageQDef(USBH_Queue, MSGQUEUE_OBJECTS, uint16_t); + 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, 0U, USBH_PROCESS_STACK_SIZE); +#else + osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0U, 8U * configMINIMAL_STACK_SIZE); +#endif /* defined (USBH_PROCESS_STACK_SIZE) */ + + phost->thread = osThreadCreate(osThread(USBH_Thread), phost); + +#else + + /* Create USB Host Queue */ + phost->os_event = osMessageQueueNew(MSGQUEUE_OBJECTS, sizeof(uint32_t), NULL); + + /* Create USB Host Task */ + USBH_Thread_Atrr.name = "USBH_Queue"; + +#if defined (USBH_PROCESS_STACK_SIZE) + USBH_Thread_Atrr.stack_size = USBH_PROCESS_STACK_SIZE; +#else + USBH_Thread_Atrr.stack_size = (8U * configMINIMAL_STACK_SIZE); +#endif /* defined (USBH_PROCESS_STACK_SIZE) */ + + USBH_Thread_Atrr.priority = USBH_PROCESS_PRIO; + phost->thread = osThreadNew(USBH_Process_OS, phost, &USBH_Thread_Atrr); + +#endif /* (osCMSIS < 0x20000U) */ +#endif /* (USBH_USE_OS == 1U) */ + + /* 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); + + /* Restore default Device connection states */ + phost->device.PortEnabled = 0U; + phost->device.is_connected = 0U; + phost->device.is_disconnected = 0U; + phost->device.is_ReEnumerated = 0U; + phost->device.RstCnt = 0U; + phost->device.EnumCnt = 0U; + + if (phost->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 = 0U; + + /* Clear Pipes flags*/ + for (i = 0U; i < USBH_MAX_PIPES_NBR; i++) + { + phost->Pipes[i] = 0U; + } + + for (i = 0U; i < USBH_MAX_DATA_BUFFER; i++) + { + phost->device.Data[i] = 0U; + } + + phost->gState = HOST_IDLE; + phost->EnumState = ENUM_IDLE; + phost->RequestState = CMD_SEND; + phost->Timer = 0U; + + phost->Control.state = CTRL_SETUP; + phost->Control.pipe_size = USBH_MPS_DEFAULT; + phost->Control.errorcount = 0U; + + phost->device.address = USBH_ADDRESS_DEFAULT; + phost->device.speed = USBH_SPEED_FULL; + phost->device.RstCnt = 0U; + phost->device.EnumCnt = 0U; + + 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 != NULL) + { + if (phost->ClassNumber < USBH_MAX_NUM_SUPPORTED_CLASS) + { + /* link the class to 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; + uint8_t if_ix = 0U; + + pif = (USBH_InterfaceDescTypeDef *)0; + pcfg = &phost->device.CfgDesc; + + while (if_ix < USBH_MAX_NUM_INTERFACES) + { + pif = &pcfg->Itf_Desc[if_ix]; + if (((pif->bInterfaceClass == Class) || (Class == 0xFFU)) && + ((pif->bInterfaceSubClass == SubClass) || (SubClass == 0xFFU)) && + ((pif->bInterfaceProtocol == Protocol) || (Protocol == 0xFFU))) + { + return if_ix; + } + if_ix++; + } + return 0xFFU; +} + + +/** + * @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 : alternate 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; + uint8_t if_ix = 0U; + + 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 0xFFU; +} + + +/** + * @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) +{ + /* DeActivate VBUS on the port */ + USBH_LL_DriverVBUS(phost, FALSE); + + /* Stop and cleanup the low level driver */ + USBH_LL_Stop(phost); + + /* 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) +{ + if (USBH_IsPortEnabled(phost)) + { + phost->device.is_ReEnumerated = 1U; + + /* Stop Host */ + USBH_Stop(phost); + + phost->device.is_disconnected = 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 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 = 0U; + + /* check for Host pending port disconnect event */ + if (phost->device.is_disconnected == 1U) + { + phost->gState = HOST_DEV_DISCONNECTED; + } + + switch (phost->gState) + { + case HOST_IDLE : + + if (phost->device.is_connected) + { + USBH_UsrLog("USB Device Connected"); + + /* Wait for 200 ms after connection */ + phost->gState = HOST_DEV_WAIT_FOR_ATTACHMENT; + USBH_Delay(200U); + USBH_LL_ResetPort(phost); + + /* Make sure to start with Default address */ + phost->device.address = USBH_ADDRESS_DEFAULT; + phost->Timeout = 0U; + +#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 + } + break; + + case HOST_DEV_WAIT_FOR_ATTACHMENT: /* Wait for Port Enabled */ + + if (phost->device.PortEnabled == 1U) + { + USBH_UsrLog("USB Device Reset Completed"); + phost->device.RstCnt = 0U; + phost->gState = HOST_DEV_ATTACHED; + } + else + { + if (phost->Timeout > USBH_DEV_RESET_TIMEOUT) + { + phost->device.RstCnt++; + if (phost->device.RstCnt > 3U) + { + /* Buggy Device can't complete reset */ + USBH_UsrLog("USB Reset Failed, Please unplug the Device."); + phost->gState = HOST_ABORT_STATE; + } + else + { + phost->gState = HOST_IDLE; + } + } + else + { + phost->Timeout += 10U; + USBH_Delay(10U); + } + } +#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 + break; + + case HOST_DEV_ATTACHED : + + if (phost->pUser != NULL) + { + phost->pUser(phost, HOST_USER_CONNECTION); + } + + /* Wait for 100 ms after Reset */ + USBH_Delay(100U); + + phost->device.speed = USBH_LL_GetSpeed(phost); + + phost->gState = HOST_ENUMERATION; + + phost->Control.pipe_out = USBH_AllocPipe(phost, 0x00U); + phost->Control.pipe_in = USBH_AllocPipe(phost, 0x80U); + + /* Open Control pipes */ + USBH_OpenPipe(phost, phost->Control.pipe_in, 0x80U, + phost->device.address, phost->device.speed, + USBH_EP_CONTROL, (uint16_t)phost->Control.pipe_size); + + /* Open Control pipes */ + USBH_OpenPipe(phost, phost->Control.pipe_out, 0x00U, + phost->device.address, phost->device.speed, + USBH_EP_CONTROL, (uint16_t)phost->Control.pipe_size); + +#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 + break; + + case HOST_ENUMERATION: + /* Check for enumeration status */ + status = USBH_HandleEnum(phost); + if (status == USBH_OK) + { + /* The function shall return USBH_OK when full enumeration is complete */ + USBH_UsrLog("Enumeration done."); + + phost->device.current_interface = 0U; + + if (phost->device.DevDesc.bNumConfigurations == 1U) + { + USBH_UsrLog("This device has only 1 configuration."); + phost->gState = HOST_SET_CONFIGURATION; + } + else + { + phost->gState = HOST_INPUT; + } +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_STATE_CHANGED_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 + } + 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 == 1U) + phost->os_msg = (uint32_t)USBH_STATE_CHANGED_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 + } + } + break; + + case HOST_SET_CONFIGURATION: + /* set configuration */ + if (USBH_SetCfg(phost, (uint16_t)phost->device.CfgDesc.bConfigurationValue) == USBH_OK) + { + phost->gState = HOST_SET_WAKEUP_FEATURE; + USBH_UsrLog("Default configuration set."); + } + +#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 + break; + + case HOST_SET_WAKEUP_FEATURE: + + if ((phost->device.CfgDesc.bmAttributes) & (1U << 5)) + { + if (USBH_SetFeature(phost, FEATURE_SELECTOR_REMOTEWAKEUP) == USBH_OK) + { + USBH_UsrLog("Device remote wakeup enabled"); + phost->gState = HOST_CHECK_CLASS; + } + } + else + { + phost->gState = HOST_CHECK_CLASS; + } + +#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 + break; + + case HOST_CHECK_CLASS: + + if (phost->ClassNumber == 0U) + { + USBH_UsrLog("No Class has been registered."); + } + else + { + phost->pActiveClass = NULL; + + for (idx = 0U; idx < USBH_MAX_NUM_SUPPORTED_CLASS; idx++) + { + if (phost->pClass[idx]->ClassCode == phost->device.CfgDesc.Itf_Desc[0].bInterfaceClass) + { + phost->pActiveClass = phost->pClass[idx]; + break; + } + } + + 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 == 1U) + phost->os_msg = (uint32_t)USBH_STATE_CHANGED_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 + break; + + case HOST_CLASS_REQUEST: + /* process class standard control requests state machine */ + if (phost->pActiveClass != NULL) + { + status = phost->pActiveClass->Requests(phost); + + if (status == USBH_OK) + { + phost->gState = HOST_CLASS; + } + else if (status == USBH_FAIL) + { + phost->gState = HOST_ABORT_STATE; + USBH_ErrLog("Device not responding Please Unplug."); + } + else + { + /* .. */ + } + } + else + { + phost->gState = HOST_ABORT_STATE; + USBH_ErrLog("Invalid Class Driver."); + } +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_STATE_CHANGED_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 + break; + + case HOST_CLASS: + /* process class state machine */ + if (phost->pActiveClass != NULL) + { + phost->pActiveClass->BgndProcess(phost); + } + break; + + case HOST_DEV_DISCONNECTED : + phost->device.is_disconnected = 0U; + + DeInitStateMachine(phost); + + /* Re-Initilaize Host for new Enumeration */ + if (phost->pActiveClass != NULL) + { + phost->pActiveClass->DeInit(phost); + phost->pActiveClass = NULL; + } + + if (phost->pUser != NULL) + { + phost->pUser(phost, HOST_USER_DISCONNECTION); + } + USBH_UsrLog("USB Device disconnected"); + + if (phost->device.is_ReEnumerated == 1U) + { + phost->device.is_ReEnumerated = 0U; + + /* Start the host and re-enable Vbus */ + USBH_Start(phost); + } + else + { + /* Device Disconnection Completed, start USB Driver */ + USBH_LL_Start(phost); + } + +#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 + 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; + USBH_StatusTypeDef ReqStatus = USBH_BUSY; + + switch (phost->EnumState) + { + case ENUM_IDLE: + /* Get Device Desc for only 1st 8 bytes : To get EP0 MaxPacketSize */ + ReqStatus = USBH_Get_DevDesc(phost, 8U); + if (ReqStatus == 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, 0x80U, phost->device.address, + phost->device.speed, USBH_EP_CONTROL, + (uint16_t)phost->Control.pipe_size); + + /* Open Control pipes */ + USBH_OpenPipe(phost, phost->Control.pipe_out, 0x00U, phost->device.address, + phost->device.speed, USBH_EP_CONTROL, + (uint16_t)phost->Control.pipe_size); + } + else if (ReqStatus == USBH_NOT_SUPPORTED) + { + USBH_ErrLog("Control error: Get Device Descriptor request failed"); + phost->device.EnumCnt++; + if (phost->device.EnumCnt > 3U) + { + /* Buggy Device can't complete get device desc request */ + USBH_UsrLog("Control error, Device not Responding Please unplug the Device."); + phost->gState = HOST_ABORT_STATE; + } + else + { + /* free control pipes */ + USBH_FreePipe(phost, phost->Control.pipe_out); + USBH_FreePipe(phost, phost->Control.pipe_in); + + /* Reset the USB Device */ + phost->gState = HOST_IDLE; + } + } + else + { + /* .. */ + } + break; + + case ENUM_GET_FULL_DEV_DESC: + /* Get FULL Device Desc */ + ReqStatus = USBH_Get_DevDesc(phost, USB_DEVICE_DESC_SIZE); + if (ReqStatus == USBH_OK) + { + USBH_UsrLog("PID: %xh", phost->device.DevDesc.idProduct); + USBH_UsrLog("VID: %xh", phost->device.DevDesc.idVendor); + + phost->EnumState = ENUM_SET_ADDR; + } + else if (ReqStatus == USBH_NOT_SUPPORTED) + { + USBH_ErrLog("Control error: Get Full Device Descriptor request failed"); + phost->device.EnumCnt++; + if (phost->device.EnumCnt > 3U) + { + /* Buggy Device can't complete get device desc request */ + USBH_UsrLog("Control error, Device not Responding Please unplug the Device."); + phost->gState = HOST_ABORT_STATE; + } + else + { + /* Free control pipes */ + USBH_FreePipe(phost, phost->Control.pipe_out); + USBH_FreePipe(phost, phost->Control.pipe_in); + + /* Reset the USB Device */ + phost->EnumState = ENUM_IDLE; + phost->gState = HOST_IDLE; + } + } + else + { + /* .. */ + } + break; + + case ENUM_SET_ADDR: + /* set address */ + ReqStatus = USBH_SetAddress(phost, USBH_DEVICE_ADDRESS); + if (ReqStatus == USBH_OK) + { + USBH_Delay(2U); + 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, 0x80U, phost->device.address, + phost->device.speed, USBH_EP_CONTROL, + (uint16_t)phost->Control.pipe_size); + + /* Open Control pipes */ + USBH_OpenPipe(phost, phost->Control.pipe_out, 0x00U, phost->device.address, + phost->device.speed, USBH_EP_CONTROL, + (uint16_t)phost->Control.pipe_size); + } + else if (ReqStatus == USBH_NOT_SUPPORTED) + { + USBH_ErrLog("Control error: Device Set Address request failed"); + + /* Buggy Device can't complete get device desc request */ + USBH_UsrLog("Control error, Device not Responding Please unplug the Device."); + phost->gState = HOST_ABORT_STATE; + phost->EnumState = ENUM_IDLE; + } + else + { + /* .. */ + } + break; + + case ENUM_GET_CFG_DESC: + /* get standard configuration descriptor */ + ReqStatus = USBH_Get_CfgDesc(phost, USB_CONFIGURATION_DESC_SIZE); + if (ReqStatus == USBH_OK) + { + phost->EnumState = ENUM_GET_FULL_CFG_DESC; + } + else if (ReqStatus == USBH_NOT_SUPPORTED) + { + USBH_ErrLog("Control error: Get Device configuration descriptor request failed"); + phost->device.EnumCnt++; + if (phost->device.EnumCnt > 3U) + { + /* Buggy Device can't complete get device desc request */ + USBH_UsrLog("Control error, Device not Responding Please unplug the Device."); + phost->gState = HOST_ABORT_STATE; + } + else + { + /* Free control pipes */ + USBH_FreePipe(phost, phost->Control.pipe_out); + USBH_FreePipe(phost, phost->Control.pipe_in); + + /* Reset the USB Device */ + phost->EnumState = ENUM_IDLE; + phost->gState = HOST_IDLE; + } + } + else + { + /* .. */ + } + break; + + case ENUM_GET_FULL_CFG_DESC: + /* get FULL config descriptor (config, interface, endpoints) */ + ReqStatus = USBH_Get_CfgDesc(phost, phost->device.CfgDesc.wTotalLength); + if (ReqStatus == USBH_OK) + { + phost->EnumState = ENUM_GET_MFC_STRING_DESC; + } + else if (ReqStatus == USBH_NOT_SUPPORTED) + { + USBH_ErrLog("Control error: Get Device configuration descriptor request failed"); + phost->device.EnumCnt++; + if (phost->device.EnumCnt > 3U) + { + /* Buggy Device can't complete get device desc request */ + USBH_UsrLog("Control error, Device not Responding Please unplug the Device."); + phost->gState = HOST_ABORT_STATE; + } + else + { + /* Free control pipes */ + USBH_FreePipe(phost, phost->Control.pipe_out); + USBH_FreePipe(phost, phost->Control.pipe_in); + + /* Reset the USB Device */ + phost->EnumState = ENUM_IDLE; + phost->gState = HOST_IDLE; + } + } + else + { + /* .. */ + } + break; + + case ENUM_GET_MFC_STRING_DESC: + if (phost->device.DevDesc.iManufacturer != 0U) + { + /* Check that Manufacturer String is available */ + ReqStatus = USBH_Get_StringDesc(phost, phost->device.DevDesc.iManufacturer, + phost->device.Data, 0xFFU); + if (ReqStatus == USBH_OK) + { + /* User callback for Manufacturing string */ + USBH_UsrLog("Manufacturer : %s", (char *)(void *)phost->device.Data); + phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_STATE_CHANGED_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 + } + else if (ReqStatus == USBH_NOT_SUPPORTED) + { + USBH_UsrLog("Manufacturer : N/A"); + phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_STATE_CHANGED_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 + } + else + { + /* .. */ + } + } + else + { + USBH_UsrLog("Manufacturer : N/A"); + phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_STATE_CHANGED_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 + } + break; + + case ENUM_GET_PRODUCT_STRING_DESC: + if (phost->device.DevDesc.iProduct != 0U) + { + /* Check that Product string is available */ + ReqStatus = USBH_Get_StringDesc(phost, phost->device.DevDesc.iProduct, + phost->device.Data, 0xFFU); + if (ReqStatus == USBH_OK) + { + /* User callback for Product string */ + USBH_UsrLog("Product : %s", (char *)(void *)phost->device.Data); + phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC; + } + else if (ReqStatus == USBH_NOT_SUPPORTED) + { + USBH_UsrLog("Product : N/A"); + phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_STATE_CHANGED_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 + } + else + { + /* .. */ + } + } + else + { + USBH_UsrLog("Product : N/A"); + phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_STATE_CHANGED_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 + } + break; + + case ENUM_GET_SERIALNUM_STRING_DESC: + if (phost->device.DevDesc.iSerialNumber != 0U) + { + /* Check that Serial number string is available */ + ReqStatus = USBH_Get_StringDesc(phost, phost->device.DevDesc.iSerialNumber, + phost->device.Data, 0xFFU); + if (ReqStatus == USBH_OK) + { + /* User callback for Serial number string */ + USBH_UsrLog("Serial Number : %s", (char *)(void *)phost->device.Data); + Status = USBH_OK; + } + else if (ReqStatus == USBH_NOT_SUPPORTED) + { + USBH_UsrLog("Serial Number : N/A"); + Status = USBH_OK; + } + else + { + /* .. */ + } + } + else + { + USBH_UsrLog("Serial Number : N/A"); + Status = USBH_OK; + } + 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 + */ +static void USBH_HandleSof(USBH_HandleTypeDef *phost) +{ + if ((phost->gState == HOST_CLASS) && (phost->pActiveClass != NULL)) + { + phost->pActiveClass->SOFProcess(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 HCD_IsPortEnabled + * Is Port Enabled + * @param phost: Host Handle + * @retval None + */ +uint8_t USBH_IsPortEnabled(USBH_HandleTypeDef *phost) +{ + return (phost->device.PortEnabled); +} + + +/** + * @brief USBH_LL_Connect + * Handle USB Host connexion event + * @param phost: Host Handle + * @retval USBH_Status + */ +USBH_StatusTypeDef USBH_LL_Connect(USBH_HandleTypeDef *phost) +{ + phost->device.is_connected = 1U; + phost->device.is_disconnected = 0U; + phost->device.is_ReEnumerated = 0U; + + +#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 USBH_OK; +} + + +/** + * @brief USBH_LL_Disconnect + * Handle USB Host disconnection event + * @param phost: Host Handle + * @retval USBH_Status + */ +USBH_StatusTypeDef USBH_LL_Disconnect(USBH_HandleTypeDef *phost) +{ + /* update device connection states */ + phost->device.is_disconnected = 1U; + phost->device.is_connected = 0U; + phost->device.PortEnabled = 0U; + + /* Stop Host */ + USBH_LL_Stop(phost); + + /* FRee Control Pipes */ + USBH_FreePipe(phost, phost->Control.pipe_in); + USBH_FreePipe(phost, phost->Control.pipe_out); +#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 USBH_OK; +} + + +#if (USBH_USE_OS == 1U) +/** + * @brief USB Host Thread task + * @param pvParameters not used + * @retval None + */ + +#if (osCMSIS < 0x20000U) +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); + } + } +} +#else +static void USBH_Process_OS(void *argument) +{ + osStatus_t status; + + for (;;) + { + status = osMessageQueueGet(((USBH_HandleTypeDef *)argument)->os_event, + &((USBH_HandleTypeDef *)argument)->os_msg, NULL, osWaitForever); + if (status == osOK) + { + USBH_Process((USBH_HandleTypeDef *)argument); + } + } +} +#endif /* (osCMSIS < 0x20000U) */ + + +/** +* @brief USBH_LL_NotifyURBChange +* Notify URB state Change +* @param phost: Host handle +* @retval USBH Status +*/ +USBH_StatusTypeDef USBH_LL_NotifyURBChange(USBH_HandleTypeDef *phost) +{ + 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 + + return USBH_OK; +} +#endif +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + +#endif // USB_HOST_MSC_FLASH_SUPPORT +#endif // STM32 diff --git a/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Src/usbh_ctlreq.cpp b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Src/usbh_ctlreq.cpp new file mode 100644 index 000000000000..6381e8d5426b --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Src/usbh_ctlreq.cpp @@ -0,0 +1,1008 @@ +/** + ****************************************************************************** + * @file usbh_ctlreq.c + * @author MCD Application Team + * @brief This file implements the control requests for device enumeration + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 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 + * + ****************************************************************************** + */ + +#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC) + +#include "../../../../../../inc/MarlinConfig.h" + +#if ENABLED(USB_HOST_MSC_FLASH_SUPPORT) + +/* Includes ------------------------------------------------------------------*/ +#include "../Inc/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 *dev_desc, + 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, + (uint16_t)length)) == USBH_OK) + { + /* Commands successfully sent and Response Received */ + USBH_ParseDevDesc(&phost->device.DevDesc, phost->device.Data, + (uint16_t)length); + } + + return status; +} + + +/** + * @brief USBH_Get_CfgDesc + * Issues Configuration Descriptor to the device. Once the response + * received, it parses the configuration 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 = phost->device.CfgDesc_Raw;; + + 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: Value 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 & 0xff00U) == USB_DESC_STRING) + { + phost->Control.setup.b.wIndex.w = 0x0409U; + } + else + { + phost->Control.setup.b.wIndex.w = 0U; + } + 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 = 0U; + phost->Control.setup.b.wLength.w = 0U; + } + + return USBH_CtlReq(phost, 0U, 0U); +} + + +/** + * @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 = 0U; + phost->Control.setup.b.wLength.w = 0U; + } + + return USBH_CtlReq(phost, 0U, 0U); +} + + +/** + * @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 = 0U; + } + + return USBH_CtlReq(phost, 0U, 0U); +} + + +/** + * @brief USBH_SetFeature + * The command sets the device features (remote wakeup feature,..) + * @param pdev: Selected device + * @param itf_idx + * @retval Status +*/ +USBH_StatusTypeDef USBH_SetFeature(USBH_HandleTypeDef *phost, uint8_t wValue) +{ + 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_FEATURE; + phost->Control.setup.b.wValue.w = wValue; + phost->Control.setup.b.wIndex.w = 0U; + phost->Control.setup.b.wLength.w = 0U; + } + + return USBH_CtlReq(phost, 0U, 0U); +} + + +/** + * @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 = 0U; + } + return USBH_CtlReq(phost, 0U, 0U); +} + + +/** + * @brief USBH_ParseDevDesc + * This function Parses the device descriptor + * @param dev_desc: device_descriptor destination 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 > 8U) + { + /* 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 *)(void *)buf; + uint16_t ptr; + uint8_t if_ix = 0U; + uint8_t ep_ix = 0U; + + pdesc = (USBH_DescHeader_t *)(void *)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 *)(void *)pdesc, &ptr); + if (pdesc->bDescriptorType == USB_DESC_TYPE_INTERFACE) + { + pif = &cfg_desc->Itf_Desc[if_ix]; + USBH_ParseInterfaceDesc(pif, (uint8_t *)(void *)pdesc); + + ep_ix = 0U; + pep = (USBH_EpDescTypeDef *)0; + while ((ep_ix < pif->bNumEndpoints) && (ptr < cfg_desc->wTotalLength)) + { + pdesc = USBH_GetNextDesc((uint8_t *)(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 *)(void *)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 = ((((uint16_t)psrc[0] - 2U) <= length) ? ((uint16_t)psrc[0] - 2U) : length); + + /* Adjust the offset ignoring the String Len and Descriptor type */ + psrc += 2U; + + for (idx = 0U; idx < strlength; idx += 2U) + { + /* Copy Only the string and ignore the UNICODE ID, hence add the src */ + *pdest = psrc[idx]; + pdest++; + } + *pdest = 0U; /* 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 pointer 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 *)(void *)pbuf)->bLength; + pnext = (USBH_DescHeader_t *)(void *)((uint8_t *)(void *)pbuf + \ + ((USBH_DescHeader_t *)(void *)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 == 1U) + phost->os_msg = (uint32_t)USBH_CONTROL_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 + break; + + case CMD_WAIT: + status = USBH_HandleControl(phost); + if ((status == USBH_OK) || (status == USBH_NOT_SUPPORTED)) + { + /* Transaction completed, move control state to idle */ + phost->RequestState = CMD_SEND; + phost->Control.state = CTRL_IDLE; + } + else if (status == USBH_FAIL) + { + /* Failure Mode */ + phost->RequestState = CMD_SEND; + } + else + { + /* .. */ + } +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_CONTROL_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 + 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 *)(void *)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 != 0U) + { + 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 == 1U) + phost->os_msg = (uint32_t)USBH_CONTROL_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 + } + else + { + if ((URB_Status == USBH_URB_ERROR) || (URB_Status == USBH_URB_NOTREADY)) + { + phost->Control.state = CTRL_ERROR; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_CONTROL_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 + } + } + break; + + case CTRL_DATA_IN: + /* Issue an IN token */ + phost->Control.timer = (uint16_t)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 transferred successfully */ + if (URB_Status == USBH_URB_DONE) + { + phost->Control.state = CTRL_STATUS_OUT; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_CONTROL_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 + } + + /* 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 == 1U) + phost->os_msg = (uint32_t)USBH_CONTROL_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 + } + else + { + if (URB_Status == USBH_URB_ERROR) + { + /* Device error */ + phost->Control.state = CTRL_ERROR; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_CONTROL_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 + } + } + break; + + case CTRL_DATA_OUT: + + USBH_CtlSendData(phost, phost->Control.buff, phost->Control.length, + phost->Control.pipe_out, 1U); + + phost->Control.timer = (uint16_t)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 == 1U) + phost->os_msg = (uint32_t)USBH_CONTROL_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 + } + + /* 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 == 1U) + phost->os_msg = (uint32_t)USBH_CONTROL_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 + } + else if (URB_Status == USBH_URB_NOTREADY) + { + /* Nack received from device */ + phost->Control.state = CTRL_DATA_OUT; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_CONTROL_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 + } + else + { + if (URB_Status == USBH_URB_ERROR) + { + /* device error */ + phost->Control.state = CTRL_ERROR; + status = USBH_FAIL; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_CONTROL_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 + } + } + break; + + case CTRL_STATUS_IN: + /* Send 0 bytes out packet */ + USBH_CtlReceiveData(phost, 0U, 0U, phost->Control.pipe_in); + + phost->Control.timer = (uint16_t)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 == 1U) + phost->os_msg = (uint32_t)USBH_CONTROL_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 + } + else if (URB_Status == USBH_URB_ERROR) + { + phost->Control.state = CTRL_ERROR; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_CONTROL_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 + } + else + { + if (URB_Status == USBH_URB_STALL) + { + /* Control transfers completed, Exit the State Machine */ + status = USBH_NOT_SUPPORTED; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_CONTROL_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 + } + } + break; + + case CTRL_STATUS_OUT: + USBH_CtlSendData(phost, 0U, 0U, phost->Control.pipe_out, 1U); + + phost->Control.timer = (uint16_t)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 == 1U) + phost->os_msg = (uint32_t)USBH_CONTROL_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 + } + else if (URB_Status == USBH_URB_NOTREADY) + { + phost->Control.state = CTRL_STATUS_OUT; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_CONTROL_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 + } + else + { + if (URB_Status == USBH_URB_ERROR) + { + phost->Control.state = CTRL_ERROR; + +#if (USBH_USE_OS == 1U) + phost->os_msg = (uint32_t)USBH_CONTROL_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 + } + } + 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) + { + /* Do the transmission again, starting from SETUP Packet */ + phost->Control.state = CTRL_SETUP; + phost->RequestState = CMD_SEND; + } + else + { + phost->pUser(phost, HOST_USER_UNRECOVERED_ERROR); + phost->Control.errorcount = 0U; + USBH_ErrLog("Control error: Device not responding"); + + /* Free control pipes */ + USBH_FreePipe(phost, phost->Control.pipe_out); + USBH_FreePipe(phost, phost->Control.pipe_in); + + phost->gState = HOST_IDLE; + status = USBH_FAIL; + } + break; + + default: + break; + } + + return status; +} + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + +#endif // USB_HOST_MSC_FLASH_SUPPORT +#endif // STM32 diff --git a/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Src/usbh_ioreq.cpp b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Src/usbh_ioreq.cpp new file mode 100644 index 000000000000..65fc89e15560 --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Src/usbh_ioreq.cpp @@ -0,0 +1,356 @@ +/** + ****************************************************************************** + * @file usbh_ioreq.c + * @author MCD Application Team + * @brief This file handles the issuing of the USB transactions + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 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 + * + ****************************************************************************** + */ + +#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC) + +#include "../../../../../../inc/MarlinConfig.h" + +#if ENABLED(USB_HOST_MSC_FLASH_SUPPORT) + +/* Includes ------------------------------------------------------------------*/ +#include "../Inc/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 */ + 0U, /* Direction : OUT */ + USBH_EP_CONTROL, /* EP type */ + USBH_PID_SETUP, /* Type setup */ + buff, /* data buffer */ + USBH_SETUP_PKT_SIZE, /* data length */ + 0U); + 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 = 0U; + } + + USBH_LL_SubmitURB(phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 0U, /* 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 */ + 1U, /* Direction : IN */ + USBH_EP_CONTROL, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0U); + 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 = 0U; + } + + USBH_LL_SubmitURB(phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 0U, /* 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 */ + 1U, /* Direction : IN */ + USBH_EP_BULK, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0U); + 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 */ + 1U, /* Direction : IN */ + USBH_EP_INTERRUPT, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + (uint16_t)length, /* data length */ + 0U); + + 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 */ + 0U, /* Direction : OUT */ + USBH_EP_INTERRUPT, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + (uint16_t)length, /* data length */ + 0U); + + 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 */ + 1U, /* Direction : IN */ + USBH_EP_ISO, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + (uint16_t)length, /* data length */ + 0U); + + + 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 */ + 0U, /* Direction : OUT */ + USBH_EP_ISO, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + (uint16_t)length, /* data length */ + 0U); + + return USBH_OK; +} +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + +#endif // USB_HOST_MSC_FLASH_SUPPORT +#endif // STM32 diff --git a/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Src/usbh_pipes.cpp b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Src/usbh_pipes.cpp new file mode 100644 index 000000000000..30f97f052610 --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Core/Src/usbh_pipes.cpp @@ -0,0 +1,195 @@ +/** + ****************************************************************************** + * @file usbh_pipes.c + * @author MCD Application Team + * @brief This file implements functions for opening and closing Pipes + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 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 + * + ****************************************************************************** + */ + +#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC) + +#include "../../../../../../inc/MarlinConfig.h" + +#if ENABLED(USB_HOST_MSC_FLASH_SUPPORT) + +/* Includes ------------------------------------------------------------------*/ +#include "../Inc/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 != 0xFFFFU) + { + phost->Pipes[pipe & 0xFU] = 0x8000U | ep_addr; + } + + return (uint8_t)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 < 11U) + { + phost->Pipes[idx] &= 0x7FFFU; + } + + 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 = 0U; + + for (idx = 0U ; idx < 11U ; idx++) + { + if ((phost->Pipes[idx] & 0x8000U) == 0U) + { + return (uint16_t)idx; + } + } + + return 0xFFFFU; +} +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + +#endif // USB_HOST_MSC_FLASH_SUPPORT +#endif // STM32 diff --git a/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Release_Notes.html b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Release_Notes.html new file mode 100644 index 000000000000..beaf93952316 --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/STM32_USB_Host_Library/Release_Notes.html @@ -0,0 +1,1235 @@ + + + + + + + + + + + + + +Release Notes for STM32 USB Host Library + + + + + + + + + +
+ +

 

+ +
+ + + + + +
+ + + + + + + +
+

Back to Release page

+
+

Release Notes for STM32 USB Host Library

+

Copyright + 2015 STMicroelectronics

+

+
+

 

+ + + + +
+

Update History

V3.3.4 / 08-January-2020

Main Changes

  • Core driver:
    • Improve enumeration phase and avoid silent responses.
    • Add device reset trial mechanism during enumeration phase.
  • MSC Class
    • usbh_msc.c
      • update max_lun field to be uint8_t instead of  uint32_t.
  • HID Class
    • Get +HID descriptor by parsing the device descriptor in order to improve +interoperability with buggy devices that Stall host Get HID descriptor +request.

V3.3.3 / 29-April-2019

Main Changes

  • Fix misra-C 2012 high severity violations
  • Core driver:
    • usbh_core.c: Rework USB host Core process in order to improve Device connection / disconnection robustness
  • MSC Class
    • usbh_msc.c
      • Update USBH_MSC_GetMaxLUN() to prevent corruption of supported LUNs
  • HID Class
    • prevent +race between USB buffer and Application fifo buffer, this was ensured +by allocating a dedicated buffer for received report
    • Prevent overflow on USB buffer for devices that could have report size greater than 4bytes

V3.3.2 / 24-January-2019

Main Changes

  • Core driver:
    • usbh_core.c: +fix on USBH_Deinit() API, prevent freeing pActiveClass->pData +pointer during host Deinit, this is manged by the Class drivers.

V3.3.1 / 09-July-2018

Main Changes

  • Fix interoperability issue with HP mouse
  • Add compatibility with FreeRTOS CMSIS V2 API changes
  • Update License section and add link to get copy of ST Ultimate Liberty license SLA0044

V3.3.0 / 23-january-2018 +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Main Changes

  • Update license section to Ultimate Liberty
  • Update some functions to be MISRA-C 2004 compliant
  • Improve USB Core enumeration state machine
  • Fix Device fast plug/unplug issue
  • Improve interoperability with non compliant USB devices
  • Add support of Host set remote wakeup enable feature
  • Fix USB Host MSC  set correct sector size
  • MSC: Set correct LUN number if returned LUN number exceeds max supported value

V3.2.2 / 07-July-2015
+

+ + + + + + + + + + + + + + + +

Main +Changes

+ + + + + + + + + + + + + + + + + + + +
  • MSC Class
    • usbh_msc.c
      • Fix MSC Get Ready Delay issue

V3.2.1 / 26-June-2015
+

+ + + + + + + + + + + + + + + +

Main +Changes

+ + + + + + + + + + + + + + + + + + + +
    +
  • Core driver
  • +
      +
    • usbh_def.h: +update USBH_MAX_PIPES_NBR literal definition to be conditioned by +#ifndef directive, to allow application code to change its value (i.e. +in the compiler preprocessor)
      +
    • +
    +
  • MSC Class
  • +
      +
    • usbh_msc.c
    • +
        +
      • Update USBH_MSC_GetMaxLUN() to  return the correct number of supported LUNs (was returning 0xFF)
      • +
      • Fix timeout calculation issue
      • +
      + +
    +
      +
    • usbh_msc.h: +update MAX_SUPPORTED_LUN literal definition to be conditioned by +#ifndef directive, to allow application code to change its value +(i.e.in the compiler preprocessor)
    • +
    +
  • HID Class
  • +
      +
    • usbh_hid.h: fix HID's handle “timer” type to uint32_t instead of uint16_t
    +
  • MTP Class
  • +
      +
    • usbh_mtp.c : Fix timeout calculation issue
    • + + +
    + +
+ +

V3.2.0 / 04-November-2014
+

+ + + + + + + + + + + + + +

Main +Changes

+ + + + + + + + + + + + + + + + + +
    +
  • Update all drivers to be C++ compliant
    +
  • +
  • Core driver
  • +
      +
    • usbh_core.c: remove HOST_IDLE state in USBH_LL_Connect() function
      +
    • +
    +
  • MSC class
  • +
      +
    • Update to manage correctly older USB Keys that do not support GetMaxLun request
    • +
    +
  • Miscellaneous source code comments update
  • +
+ +

V3.1.0 / 19-June-2014

+ + + + + +

Main +Changes

+ + + + + + + + + +
    +
  • Core driver
  • +
      +
    • Add a new define USBH_PROCESS_STACK_SIZE in the usbh_conf.h +file to change the default internal USB host process stack. Note that +by omitting this define, the default stack size (2KB) is used
      +
    • +
    • Add a user callback to handle unrecoverable error case in the application
    • +
    +
      +
    • Remove the wrong check on the interface descriptor index in the USBH_FindInterface() function
      +
    • +
    +
  • All classes
  • +
      +
    • Update class description in files comment by adding reference to the used USB class specification revision
    • +
    +
  • Audio, CDC and MTP classes
    +
  • +
      +
    • Add full RTOS support by handling state transitions through OS messages
      +
    • +
    +
  • HID class
  • +
      +
    • Add new API USBH_HID_GetPollInterval() to allow user to retrieve the needed poll time (interval between two USBD_HID_SendReport())
    • +
    +
  • Audio class
  • +
      +
    • Add a new weak callback USBH_AUDIO_BufferEmptyCallback() to indicate the end of audio data processing on the user buffer
    • +
    +
  • MSC class
  • +
      +
    • Return mass storage device capacity in Bytes in the user log message instead of MBytes
    • +
    +
+ + + +

V3.0.0 / 18-February-2014

+ + + +

Main +Changes

+ + + + + + + +
    +
  • Major update +based on STM32Cube specification: Library Core, Classes architecture and APIs +modified vs. V2.1.0, and thus the 2 versions are not compatible.
    +
  • +
  • This version has to be used only with STM32Cube based development
  • +
+

V2.1.0 / 19-March-2012

+

Main +Changes

+ +
  • Official support of STM32F4xx devices
  • All source files: license disclaimer text update and add link to the License file on ST Internet
  • Add ISR structure to link the low level driver to the Host library
  • Change length parameter in the I/O operations to handle large amount of data
  • Enhance the configuration descriptor parsing method to take into account multi interface devices
  • HID class
    • Remove blocking even frame synchronization loop
  • MSC class
    • Handle correctly the BOT transfer with length < max length
    • Handle multi sector length data in the FAT FS interface
  • Miscellaneous bug fix

V2.0.0 / 22-July-2011

Main +Changes

+
  • Second official version supporting STM32F105/7 and STM32F2xx devices
  • Add support for STM32F2xx devices
  • Add multi interface feature
  • Add dynamic configuration parsing
  • Add +USBH_DeAllocate_AllChannel function in the Host channel management +layer to clean up channels allocation table when de-initializing the +library
  • Change the core layer to stop correctly the host core and free all allocated channels
  • Add usbh_conf.h file in the application layer to customize some user parameters

V1.0.0 - 11/29/2010

+
  • Created 

License

This +software component is licensed by ST under Ultimate Liberty license +SLA0044, the "License"; You may not use this component except in +compliance with the License. You may obtain a copy of the License at:

http://www.st.com/SLA0044

+
+
+
+

For + complete documentation on STM32 + Microcontrollers visit www.st.com/STM32

+
+

+
+ +
+ +

 

+ +
+ + \ No newline at end of file diff --git a/Marlin/src/HAL/STM32/usb_hostlib/usbh_conf.cpp b/Marlin/src/HAL/STM32/usb_hostlib/usbh_conf.cpp new file mode 100644 index 000000000000..70ab4d76b0fe --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/usbh_conf.cpp @@ -0,0 +1,482 @@ +/** + ****************************************************************************** + * @file usbh_conf.cpp + * @author MCD Application Team + * @brief This file implements the board support package for the USB host library + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 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 + * + ****************************************************************************** + */ + +#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC) + +/* Includes ------------------------------------------------------------------*/ + +#include "../../../inc/MarlinConfig.h" + +#if ENABLED(USB_HOST_MSC_FLASH_SUPPORT) + +#include "STM32_USB_Host_Library/Core/Inc/usbh_core.h" +#include "usbh_pins.h" + +HCD_HandleTypeDef Marlinhcd; + +/** + * @brief SOF callback. + * @param hhcd HCD handle + * @retval None + */ +void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_IncTimer((USBH_HandleTypeDef *)(hhcd->pData)); +} + +/** + * @brief Connection Event callback. + * @param hhcd HCD handle + * @retval None + */ +void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_DbgLog("Connected!\r\n"); + USBH_LL_Connect((USBH_HandleTypeDef *)(hhcd->pData)); +} + +/** + * @brief Disconnection Event callback. + * @param hhcd HCD handle + * @retval None + */ +void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_DbgLog("Disconnected!\r\n"); + USBH_LL_Disconnect((USBH_HandleTypeDef *)(hhcd->pData)); +} + +/** + * @brief Port Enabled Event callback. + * @param hhcd HCD handle + * @retval None + */ +void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_DbgLog("Prot enabled!\r\n"); + USBH_LL_PortEnabled((USBH_HandleTypeDef *)(hhcd->pData)); +} + +/** + * @brief Port Disabled Event callback. + * @param hhcd HCD handle + * @retval None + */ +void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_DbgLog("Prot disabled!\r\n"); + USBH_LL_PortDisabled((USBH_HandleTypeDef *)(hhcd->pData)); +} + +/** + * @brief Notify URB state change callback. + * @param hhcd HCD handle + * @param chnum Channel number. + * This parameter can be a value from 1 to 15 + * @param urb_state: + * This parameter can be one of these values: + * URB_IDLE/ + * URB_DONE/ + * URB_NOTREADY/ + * URB_NYET/ + * URB_ERROR/ + * URB_STALL/ + * @retval None + */ +void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hhcd); + UNUSED(chnum); + UNUSED(urb_state); +} + +/** + * @brief Initialize the HCD MSP. + * @param hhcd HCD handle + * @retval None + */ +void HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd) +{ + if(hhcd->Instance==USB_OTG_FS) + { + GPIO_InitTypeDef GPIO_InitStruct; + + __HAL_RCC_GPIOA_CLK_ENABLE(); + GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12); + 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); + + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + HAL_NVIC_SetPriority(OTG_FS_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(OTG_FS_IRQn); + } + else if (hhcd->Instance == USB_OTG_HS) + { + GPIO_InitTypeDef GPIO_InitStruct; + + __HAL_RCC_GPIOB_CLK_ENABLE(); + GPIO_InitStruct.Pin = (GPIO_PIN_14 | GPIO_PIN_15); + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_OTG_HS_FS; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); + HAL_NVIC_SetPriority(OTG_HS_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(OTG_HS_IRQn); + } +} + +/** + * @brief DeInitialize the HCD MSP. + * @param hhcd HCD handle + * @retval None + */ +void HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hhcd); +} + +// OTG host IRQ +extern "C" USB_OTG_ISR() +{ + HAL_HCD_IRQHandler(&Marlinhcd); +} + +/** + * @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) +{ + Marlinhcd.Instance = USB_OTG_INSTANCE; + Marlinhcd.Init.Host_channels = 12; + Marlinhcd.Init.dma_enable = DISABLE; + Marlinhcd.Init.low_power_enable = DISABLE; + Marlinhcd.Init.phy_itface = HCD_PHY_EMBEDDED; + Marlinhcd.Init.Sof_enable = DISABLE; + Marlinhcd.Init.speed = HCD_SPEED_FULL; + Marlinhcd.Init.vbus_sensing_enable = DISABLE; + Marlinhcd.Init.lpm_enable = DISABLE; + + Marlinhcd.pData = phost; + phost->pData = &Marlinhcd; + + HAL_HCD_Init(&Marlinhcd); + + USBH_LL_SetTimer(phost, HAL_HCD_GetCurrentFrame(&Marlinhcd)); + + 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) +{ + HAL_HCD_DeInit((HCD_HandleTypeDef *)(phost->pData)); + + 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) +{ + HAL_HCD_Start((HCD_HandleTypeDef *)(phost->pData)); + + 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) +{ + HAL_HCD_Stop((HCD_HandleTypeDef *)(phost->pData)); + + 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; + + switch (HAL_HCD_GetCurrentSpeed((HCD_HandleTypeDef *)(phost->pData))) + { + case 0: + speed = USBH_SPEED_HIGH; + USBH_DbgLog("USB Host [HS]\r\n"); + break; + + case 1: + speed = USBH_SPEED_FULL; + USBH_DbgLog("USB Host [FS]\r\n"); + break; + + case 2: + speed = USBH_SPEED_LOW; + USBH_DbgLog("USB Host [LS]\r\n"); + break; + + default: + speed = USBH_SPEED_FULL; + USBH_DbgLog("USB Host [FS]\r\n"); + break; + } + + 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) +{ + HAL_HCD_ResetPort((HCD_HandleTypeDef *)(phost->pData)); + USBH_DbgLog("USB Reset Port\r\n"); + + return USBH_OK; +} + +/** + * @brief USBH_LL_GetLastXferSize + * Return the last transferred 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((HCD_HandleTypeDef *)(phost->pData), 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) +{ + HAL_HCD_HC_Init((HCD_HandleTypeDef *)(phost->pData), pipe_num, epnum, dev_address, speed, ep_type, 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) +{ + HAL_HCD_HC_Halt((HCD_HandleTypeDef *)(phost->pData), pipe); + + return USBH_OK; +} + +/** + * @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: Isochronous 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_HCD_HC_SubmitRequest((HCD_HandleTypeDef *)(phost->pData), pipe, direction, ep_type, token, pbuff, length, 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) +{ + return (USBH_URBStateTypeDef) HAL_HCD_HC_GetURBState((HCD_HandleTypeDef *)(phost->pData), 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) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(phost); + UNUSED(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) +{ + if (Marlinhcd.hc[pipe].ep_is_in) + { + Marlinhcd.hc[pipe].toggle_in = toggle; + } + else + { + Marlinhcd.hc[pipe].toggle_out = 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) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(phost); + UNUSED(pipe); + + uint8_t toggle = 0U; + + if (Marlinhcd.hc[pipe].ep_is_in) + { + toggle = Marlinhcd.hc[pipe].toggle_in; + } + else + { + toggle = Marlinhcd.hc[pipe].toggle_out; + } + + 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) +{ + HAL_Delay(Delay); +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + +#endif // USB_HOST_MSC_FLASH_SUPPORT +#endif // STM32 diff --git a/Marlin/src/HAL/STM32/usb_hostlib/usbh_conf.h b/Marlin/src/HAL/STM32/usb_hostlib/usbh_conf.h new file mode 100644 index 000000000000..e1f935e7e71f --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/usbh_conf.h @@ -0,0 +1,149 @@ +/** + ****************************************************************************** + * @file usbh_conf_template.h + * @author MCD Application Team + * @brief Header file for usbh_conf_template.c + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 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 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBH_CONF_H +#define __USBH_CONF_H + +/* Includes ------------------------------------------------------------------*/ +// #include "stm32fxxx.h" /* replace 'stm32xxx' with your HAL driver header filename, ex: stm32f4xx.h */ +#ifdef STM32F4 + #include "stm32f4xx_hal.h" +#else + #error "For now USB host MSC is only supported on STM32F4." +#endif +#include +#include +#include + +/** @addtogroup STM32_USB_HOST_LIBRARY + * @{ + */ + +/** @defgroup USBH_CONF + * @brief usb host low level driver configuration file + * @{ + */ + +/** @defgroup USBH_CONF_Exported_Defines + * @{ + */ + +#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 0x200U +#define USBH_MAX_DATA_BUFFER 0x200U +#define USBH_DEBUG_LEVEL 0U +#define USBH_USE_OS 0U + +/** @defgroup USBH_Exported_Macros + * @{ + */ + +/* Memory management macros */ +#define USBH_malloc malloc +#define USBH_free free +#define USBH_memset memset +#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 + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_CONF_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_CONF_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_CONF_Exported_FunctionsPrototype + * @{ + */ +/** + * @} + */ + +#endif /* __USBH_CONF_TEMPLATE_H */ + + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Marlin/src/HAL/STM32/usb_hostlib/usbh_pins.h b/Marlin/src/HAL/STM32/usb_hostlib/usbh_pins.h new file mode 100644 index 000000000000..7172a1173418 --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/usbh_pins.h @@ -0,0 +1,45 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#pragma once + +/** + * Define USB HOST Pins: OTG_DM, OTG_DP + */ +#ifndef USB_OTG_DM_PIN + #define USB_OTG_DM_PIN PA11 +#endif +#ifndef USB_OTG_DP_PIN + #define USB_OTG_DP_PIN PA12 +#endif + +#if USB_OTG_DM_PIN == PA11 && USB_OTG_DP_PIN == PA12 + #define USB_OTG_ID FS +#elif USB_OTG_DM_PIN == PB14 && USB_OTG_DP_PIN == PB15 + #define USB_OTG_ID HS // HS port used for FS function +#else + #error "USB OTG pins error!" +#endif + +#define __USB_OTG_ISR(n) void OTG_##n##_IRQHandler(void) +#define _USB_OTG_ISR(n) __USB_OTG_ISR(n) +#define USB_OTG_ISR() _USB_OTG_ISR(USB_OTG_ID) + +#define __USB_OTG_INSTANCE(n) USB_OTG_##n +#define _USB_OTG_INSTANCE(n) __USB_OTG_INSTANCE(n) +#define USB_OTG_INSTANCE _USB_OTG_INSTANCE(USB_OTG_ID) diff --git a/Marlin/src/HAL/STM32/usb_hostlib/usbh_usr.cpp b/Marlin/src/HAL/STM32/usb_hostlib/usbh_usr.cpp new file mode 100644 index 000000000000..14882ef8e203 --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/usbh_usr.cpp @@ -0,0 +1,178 @@ +/** + ****************************************************************************** + * @file usbh_usr.cpp + * @author MCD Application Team + * @brief This file implements the board support package for the USB host library + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 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 + * + ****************************************************************************** + */ + +#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC) + +#include "../../../inc/MarlinConfig.h" + +#if ENABLED(USB_HOST_MSC_FLASH_SUPPORT) + +#include "usbh_usr.h" +#include "STM32_USB_Host_Library/Core/Inc/usbh_def.h" +#include "STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc.h" + +USBH_HandleTypeDef MarlinUSB_Host; + +uint8_t usbh_media_ready = 0; + +/* + * user callback definition + */ +static void USBH_UserProcess (USBH_HandleTypeDef *phost, uint8_t id) +{ + /* USER CODE BEGIN CALL_BACK_1 */ + switch(id) + { + case HOST_USER_CLASS_ACTIVE: + usbh_media_ready = 1; + break; + + case HOST_USER_SELECT_CONFIGURATION: + case HOST_USER_DISCONNECTION: + case HOST_USER_CONNECTION: + default: + usbh_media_ready = 0; + break; + } + /* USER CODE END CALL_BACK_1 */ +} + +void USBH_HAL_Init(void) +{ + USBH_Init(&MarlinUSB_Host, USBH_UserProcess, 0); + USBH_RegisterClass(&MarlinUSB_Host, USBH_MSC_CLASS); + USBH_Start(&MarlinUSB_Host); +} + +void USB_HAL_Loop(void) +{ + USBH_Process(&MarlinUSB_Host); +} + +uint8_t USBH_IsConnected(void) +{ + return usbh_media_ready; +} + +/** + * @brief Gets Disk Status + * @param lun : lun id + * @retval DSTATUS: Operation status, 0:ok 1:error + */ +uint8_t USBH_status(uint8_t lun) +{ + if(USBH_MSC_UnitIsReady(&MarlinUSB_Host, lun)) + { + return 0; // Media ready + } + else + { + return 1; // Error + } +} + +/** + * @brief Reads Sector(s) + * @param lun : lun id + * @param *buff: Data buffer to store read data + * @param sector: Sector address (LBA) + * @param count: Number of sectors to read (1..128) + * @retval DRESULT: Operation result, 0:ok 1:error + */ +uint8_t USBH_read(uint8_t lun, uint8_t *buff, uint32_t sector, uint32_t count) +{ + uint8_t res = 1; + MSC_LUNTypeDef info; + + if(USBH_MSC_Read(&MarlinUSB_Host, lun, sector, buff, count) == USBH_OK) + { + res = 0; // Read successful + } + else + { + USBH_MSC_GetLUNInfo(&MarlinUSB_Host, lun, &info); + + switch (info.sense.asc) + { + case SCSI_ASC_LOGICAL_UNIT_NOT_READY: + case SCSI_ASC_MEDIUM_NOT_PRESENT: + case SCSI_ASC_NOT_READY_TO_READY_CHANGE: + USBH_ErrLog ("USB Disk is not ready!"); + res = 3; // Media not ready + break; + + default: + res = 1; // Error + break; + } + } + + return res; +} + +/* USER CODE BEGIN beforeWriteSection */ +/* can be used to modify previous code / undefine following code / add new code */ +/* USER CODE END beforeWriteSection */ + +/** + * @brief Writes Sector(s) + * @param lun : lun id + * @param *buff: Data to be written + * @param sector: Sector address (LBA) + * @param count: Number of sectors to write (1..128) + * @retval DRESULT: Operation result, 0:ok 1:error + */ +uint8_t USBH_write(uint8_t lun, const uint8_t *buff, uint32_t sector, uint32_t count) +{ + uint8_t res = 1; + MSC_LUNTypeDef info; + + if(USBH_MSC_Write(&MarlinUSB_Host, lun, sector, (uint8_t *)buff, count) == USBH_OK) + { + res = 0; // Write successful + } + else + { + USBH_MSC_GetLUNInfo(&MarlinUSB_Host, lun, &info); + + switch (info.sense.asc) + { + case SCSI_ASC_WRITE_PROTECTED: + USBH_ErrLog("USB Disk is Write protected!"); + res = 2; // Write protected + break; + + case SCSI_ASC_LOGICAL_UNIT_NOT_READY: + case SCSI_ASC_MEDIUM_NOT_PRESENT: + case SCSI_ASC_NOT_READY_TO_READY_CHANGE: + USBH_ErrLog("USB Disk is not ready!"); + res = 3; // Media not ready + break; + + default: + res = 1; // Error + break; + } + } + + return res; +} + +#endif // USB_HOST_MSC_FLASH_SUPPORT +#endif // STM32 diff --git a/Marlin/src/HAL/STM32/usb_hostlib/usbh_usr.h b/Marlin/src/HAL/STM32/usb_hostlib/usbh_usr.h new file mode 100644 index 000000000000..68a6414d12f1 --- /dev/null +++ b/Marlin/src/HAL/STM32/usb_hostlib/usbh_usr.h @@ -0,0 +1,28 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#pragma once + +#include + +void USBH_HAL_Init(void); +void USB_HAL_Loop(void); + +uint8_t USBH_IsConnected(void); +uint8_t USBH_read(uint8_t lun, uint8_t *buff, uint32_t sector, uint32_t count); +uint8_t USBH_write(uint8_t lun, const uint8_t *buff, uint32_t sector, uint32_t count); diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index b6282cb09835..8a3dbef1854a 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -740,7 +740,9 @@ void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) { TERN_(SDSUPPORT, card.manage_media()); // Handle USB Flash Drive insert / remove - TERN_(USB_FLASH_DRIVE_SUPPORT, Sd2Card::idle()); + #if EITHER(USB_FLASH_DRIVE_SUPPORT, USB_HOST_MSC_FLASH_SUPPORT) + Sd2Card::idle(); + #endif // Announce Host Keepalive state (if any) TERN_(HOST_KEEPALIVE_FEATURE, gcode.host_keepalive()); diff --git a/Marlin/src/pins/stm32f4/pins_BTT_GTR_V1_0.h b/Marlin/src/pins/stm32f4/pins_BTT_GTR_V1_0.h index bfa4007658db..2f664f81d48d 100644 --- a/Marlin/src/pins/stm32f4/pins_BTT_GTR_V1_0.h +++ b/Marlin/src/pins/stm32f4/pins_BTT_GTR_V1_0.h @@ -29,6 +29,15 @@ #error "Marlin extruder/hotends limit! Increase MAX_E_STEPPERS to continue." #endif +#if ENABLED(USB_HOST_MSC_FLASH_SUPPORT) + #if ENABLED(USBCON) + #error "For USB host MSC make sure USBCON is not defined. Remove -DUSBCON if present." + #endif + #if SERIAL_PORT == -1 || SERIAL_PORT_2 == -1 + #error "USB host MSC and USB emulated serial port can't be enabled on GTR V1.0 at the same time." + #endif +#endif + #define BOARD_INFO_NAME "BTT GTR V1.0" // Onboard I2C EEPROM @@ -37,6 +46,12 @@ #define TP // Enable to define servo and probe pins +// +// USB OTG Host +// +#define USB_OTG_DM_PIN PA11 +#define USB_OTG_DP_PIN PA12 + // // Servos // diff --git a/Marlin/src/pins/stm32f4/pins_BTT_SKR_PRO_V1_1.h b/Marlin/src/pins/stm32f4/pins_BTT_SKR_PRO_V1_1.h index fb4b17b6fb22..71af9329f93f 100644 --- a/Marlin/src/pins/stm32f4/pins_BTT_SKR_PRO_V1_1.h +++ b/Marlin/src/pins/stm32f4/pins_BTT_SKR_PRO_V1_1.h @@ -25,6 +25,15 @@ #error "BIGTREE SKR Pro V1.1 supports up to 3 hotends / E-steppers." #endif +#if ENABLED(USB_HOST_MSC_FLASH_SUPPORT) + #if ENABLED(USBCON) + #error "For USB host MSC make sure USBCON is not defined. Remove -DUSBCON if present." + #endif + #if SERIAL_PORT == -1 || SERIAL_PORT_2 == -1 + #error "USB host MSC and USB emulated serial port can't be enabled on BTT SKR Pro V1.1 at the same time." + #endif +#endif + #define BOARD_INFO_NAME "BTT SKR Pro V1.1" #include "pins_BTT_SKR_PRO_common.h" diff --git a/Marlin/src/pins/stm32f4/pins_BTT_SKR_PRO_V1_2.h b/Marlin/src/pins/stm32f4/pins_BTT_SKR_PRO_V1_2.h index 615751b62d37..520461e6e3b7 100644 --- a/Marlin/src/pins/stm32f4/pins_BTT_SKR_PRO_V1_2.h +++ b/Marlin/src/pins/stm32f4/pins_BTT_SKR_PRO_V1_2.h @@ -25,6 +25,15 @@ #error "BIGTREE SKR Pro V1.2 supports up to 3 hotends / E-steppers." #endif +#if ENABLED(USB_HOST_MSC_FLASH_SUPPORT) + #if ENABLED(USBCON) + #error "For USB host MSC make sure USBCON is not defined. Remove -DUSBCON if present." + #endif + #if SERIAL_PORT == -1 || SERIAL_PORT_2 == -1 + #error "USB host MSC and USB emulated serial port can't be enabled on BTT SKR Pro V1.2 at the same time." + #endif +#endif + #define BOARD_INFO_NAME "BTT SKR Pro V1.2" #include "pins_BTT_SKR_PRO_common.h" diff --git a/Marlin/src/pins/stm32f4/pins_BTT_SKR_PRO_common.h b/Marlin/src/pins/stm32f4/pins_BTT_SKR_PRO_common.h index 235ed1edcc4c..aaa5a26b10ba 100644 --- a/Marlin/src/pins/stm32f4/pins_BTT_SKR_PRO_common.h +++ b/Marlin/src/pins/stm32f4/pins_BTT_SKR_PRO_common.h @@ -44,6 +44,12 @@ #define FLASH_EEPROM_LEVELING #endif +// +// USB OTG Host +// +#define USB_OTG_DM_PIN PA11 +#define USB_OTG_DP_PIN PA12 + // // Servos // diff --git a/Marlin/src/sd/Sd2Card.cpp b/Marlin/src/sd/Sd2Card.cpp index 491c0692c72f..47eb676e7c75 100644 --- a/Marlin/src/sd/Sd2Card.cpp +++ b/Marlin/src/sd/Sd2Card.cpp @@ -30,7 +30,7 @@ #include "../inc/MarlinConfig.h" -#if ENABLED(SDSUPPORT) && NONE(USB_FLASH_DRIVE_SUPPORT, SDIO_SUPPORT) +#if ENABLED(SDSUPPORT) && NONE(USB_FLASH_DRIVE_SUPPORT, USB_HOST_MSC_FLASH_SUPPORT, SDIO_SUPPORT) /* Enable FAST CRC computations - You can trade speed for FLASH space if * needed by disabling the following define */ diff --git a/Marlin/src/sd/SdVolume.h b/Marlin/src/sd/SdVolume.h index 2d57c681c494..9a702c239f3f 100644 --- a/Marlin/src/sd/SdVolume.h +++ b/Marlin/src/sd/SdVolume.h @@ -36,6 +36,8 @@ #if ENABLED(USB_FLASH_DRIVE_SUPPORT) #include "usb_flashdrive/Sd2Card_FlashDrive.h" +#elif ENABLED(USB_HOST_MSC_FLASH_SUPPORT) + #include "usb_hostmsc/Sd2Card_usbhost_msc.h" #elif ENABLED(SDIO_SUPPORT) #include "Sd2Card_sdio.h" #else diff --git a/Marlin/src/sd/cardreader.cpp b/Marlin/src/sd/cardreader.cpp index bce84bbd3921..9c2bff55f349 100644 --- a/Marlin/src/sd/cardreader.cpp +++ b/Marlin/src/sd/cardreader.cpp @@ -394,7 +394,7 @@ void CardReader::mount() { if (flag.mounted) cdroot(); - #if ENABLED(USB_FLASH_DRIVE_SUPPORT) || PIN_EXISTS(SD_DETECT) + #if EITHER(USB_FLASH_DRIVE_SUPPORT, USB_HOST_MSC_FLASH_SUPPORT) || PIN_EXISTS(SD_DETECT) else if (marlin_state != MF_INITIALIZING) ui.set_status_P(GET_TEXT(MSG_SD_INIT_FAIL), -1); #endif diff --git a/Marlin/src/sd/cardreader.h b/Marlin/src/sd/cardreader.h index dabbf719f92b..867cb0fd420f 100644 --- a/Marlin/src/sd/cardreader.h +++ b/Marlin/src/sd/cardreader.h @@ -281,7 +281,7 @@ class CardReader { #endif }; -#if ENABLED(USB_FLASH_DRIVE_SUPPORT) +#if EITHER(USB_FLASH_DRIVE_SUPPORT, USB_HOST_MSC_FLASH_SUPPORT) #define IS_SD_INSERTED() Sd2Card::isInserted() #elif PIN_EXISTS(SD_DETECT) #define IS_SD_INSERTED() (READ(SD_DETECT_PIN) == SD_DETECT_STATE) diff --git a/Marlin/src/sd/usb_hostmsc/Sd2Card_usbhost_msc.cpp b/Marlin/src/sd/usb_hostmsc/Sd2Card_usbhost_msc.cpp new file mode 100644 index 000000000000..93731c72417e --- /dev/null +++ b/Marlin/src/sd/usb_hostmsc/Sd2Card_usbhost_msc.cpp @@ -0,0 +1,70 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "../../inc/MarlinConfigPre.h" + +#if ENABLED(USB_HOST_MSC_FLASH_SUPPORT) + +#include "Sd2Card_usbhost_msc.h" +#include HAL_PATH(../../HAL, usb_hostlib/usbh_usr.h) + +#include "../../MarlinCore.h" +#include "../../core/serial.h" +#include "../../module/temperature.h" + +// idle() is always called in Marlin idle() +void Sd2Card::idle() { + + // Hareware IO init once time after startup + static uint8_t firstCall = 1; + if (firstCall) { + USBH_HAL_Init(); + firstCall = 0; + } + + USB_HAL_Loop(); +} + +// Marlin calls this function to check whether an USB drive is inserted. +// This is equivalent to polling the SD_DETECT when using SD cards. +bool Sd2Card::isInserted() { + return USBH_IsConnected(); +} + +// Marlin calls this to initialize an SD card once it is inserted. +bool Sd2Card::init(const uint8_t, const pin_t) { + return isInserted(); +} + +bool Sd2Card::readBlock(uint32_t block, uint8_t* dst) { + if (!isInserted()) return false; + + return (USBH_read(0, dst, block, 1) == 0); +} + +bool Sd2Card::writeBlock(uint32_t block, const uint8_t* src) { + if (!isInserted()) return false; + + return (USBH_write(0, src, block, 1) == 0); +} + +#endif // USB_HOST_MSC_FLASH_SUPPORT diff --git a/Marlin/src/sd/usb_hostmsc/Sd2Card_usbhost_msc.h b/Marlin/src/sd/usb_hostmsc/Sd2Card_usbhost_msc.h new file mode 100644 index 000000000000..443be4a61932 --- /dev/null +++ b/Marlin/src/sd/usb_hostmsc/Sd2Card_usbhost_msc.h @@ -0,0 +1,43 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#pragma once + +/** + * \file + * \brief Sd2Card class for V2 SD/SDHC cards + */ + +#include "../SdFatConfig.h" +#include "../SdInfo.h" + +class Sd2Card { + public: + + bool init(const uint8_t sckRateID=0, const pin_t chipSelectPin=0); + + static void idle(); + + bool readBlock(uint32_t block, uint8_t* dst); + bool writeBlock(uint32_t blockNumber, const uint8_t* src); + + static bool isInserted(); +}; diff --git a/buildroot/share/PlatformIO/variants/BIGTREE_BTT002/ldscript.ld b/buildroot/share/PlatformIO/variants/BIGTREE_BTT002/ldscript.ld index 0c060d175180..f96475d465da 100644 --- a/buildroot/share/PlatformIO/variants/BIGTREE_BTT002/ldscript.ld +++ b/buildroot/share/PlatformIO/variants/BIGTREE_BTT002/ldscript.ld @@ -21,7 +21,7 @@ ***************************************************************************** ** @attention ** -**

© COPYRIGHT(c) 2014 Ac6

+** © COPYRIGHT(c) 2014 Ac6 ** ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: diff --git a/buildroot/share/PlatformIO/variants/BIGTREE_GTR_V1/ldscript.ld b/buildroot/share/PlatformIO/variants/BIGTREE_GTR_V1/ldscript.ld index 0c060d175180..f96475d465da 100644 --- a/buildroot/share/PlatformIO/variants/BIGTREE_GTR_V1/ldscript.ld +++ b/buildroot/share/PlatformIO/variants/BIGTREE_GTR_V1/ldscript.ld @@ -21,7 +21,7 @@ ***************************************************************************** ** @attention ** -**

© COPYRIGHT(c) 2014 Ac6

+** © COPYRIGHT(c) 2014 Ac6 ** ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: diff --git a/buildroot/share/PlatformIO/variants/BIGTREE_SKR_PRO_1v1/hal_conf_extra.h b/buildroot/share/PlatformIO/variants/BIGTREE_SKR_PRO_1v1/hal_conf_extra.h index e0e8239aac08..afe6e308e7b8 100644 --- a/buildroot/share/PlatformIO/variants/BIGTREE_SKR_PRO_1v1/hal_conf_extra.h +++ b/buildroot/share/PlatformIO/variants/BIGTREE_SKR_PRO_1v1/hal_conf_extra.h @@ -13,6 +13,7 @@ #define HAL_TIM_MODULE_ENABLED #define HAL_USART_MODULE_ENABLED #define HAL_CORTEX_MODULE_ENABLED +#define HAL_HCD_MODULE_ENABLED // USB Host //#define HAL_UART_MODULE_ENABLED // by default //#define HAL_PCD_MODULE_ENABLED // Since STM32 v3.10700.191028 this is automatically added if any type of USB is enabled (as in Arduino IDE) @@ -44,7 +45,6 @@ #undef HAL_IRDA_MODULE_ENABLED #undef HAL_SMARTCARD_MODULE_ENABLED #undef HAL_WWDG_MODULE_ENABLED -#undef HAL_HCD_MODULE_ENABLED #undef HAL_FMPI2C_MODULE_ENABLED #undef HAL_SPDIFRX_MODULE_ENABLED #undef HAL_DFSDM_MODULE_ENABLED diff --git a/buildroot/share/PlatformIO/variants/BIGTREE_SKR_PRO_1v1/ldscript.ld b/buildroot/share/PlatformIO/variants/BIGTREE_SKR_PRO_1v1/ldscript.ld index 0c060d175180..f96475d465da 100644 --- a/buildroot/share/PlatformIO/variants/BIGTREE_SKR_PRO_1v1/ldscript.ld +++ b/buildroot/share/PlatformIO/variants/BIGTREE_SKR_PRO_1v1/ldscript.ld @@ -21,7 +21,7 @@ ***************************************************************************** ** @attention ** -**

© COPYRIGHT(c) 2014 Ac6

+** © COPYRIGHT(c) 2014 Ac6 ** ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: diff --git a/buildroot/share/PlatformIO/variants/FLY_F407ZG/ldscript.ld b/buildroot/share/PlatformIO/variants/FLY_F407ZG/ldscript.ld index 40abfe19b574..35c0d3daffea 100644 --- a/buildroot/share/PlatformIO/variants/FLY_F407ZG/ldscript.ld +++ b/buildroot/share/PlatformIO/variants/FLY_F407ZG/ldscript.ld @@ -21,7 +21,7 @@ ***************************************************************************** ** @attention ** -**

© COPYRIGHT(c) 2014 Ac6

+** © COPYRIGHT(c) 2014 Ac6 ** ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: diff --git a/buildroot/share/PlatformIO/variants/MARLIN_F103Vx/ldscript.ld b/buildroot/share/PlatformIO/variants/MARLIN_F103Vx/ldscript.ld index c9197c8b451a..7f1a34f45681 100644 --- a/buildroot/share/PlatformIO/variants/MARLIN_F103Vx/ldscript.ld +++ b/buildroot/share/PlatformIO/variants/MARLIN_F103Vx/ldscript.ld @@ -23,7 +23,7 @@ ***************************************************************************** ** @attention ** -**

© COPYRIGHT(c) 2019 STMicroelectronics

+** © COPYRIGHT(c) 2019 STMicroelectronics ** ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: diff --git a/buildroot/share/PlatformIO/variants/MARLIN_F103Zx/hal_conf_custom.h b/buildroot/share/PlatformIO/variants/MARLIN_F103Zx/hal_conf_custom.h index 014943f311ed..b14a6bd0969d 100644 --- a/buildroot/share/PlatformIO/variants/MARLIN_F103Zx/hal_conf_custom.h +++ b/buildroot/share/PlatformIO/variants/MARLIN_F103Zx/hal_conf_custom.h @@ -5,8 +5,8 @@ ****************************************************************************** * @attention * - *

© Copyright (c) 2017 STMicroelectronics. - * All rights reserved.

+ * Copyright (c) 2017 STMicroelectronics. + * All rights reserved. * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the diff --git a/buildroot/share/PlatformIO/variants/MARLIN_F103Zx/ldscript.ld b/buildroot/share/PlatformIO/variants/MARLIN_F103Zx/ldscript.ld index 09088b622c87..7b553e12439a 100644 --- a/buildroot/share/PlatformIO/variants/MARLIN_F103Zx/ldscript.ld +++ b/buildroot/share/PlatformIO/variants/MARLIN_F103Zx/ldscript.ld @@ -23,7 +23,7 @@ ***************************************************************************** ** @attention ** -**

© COPYRIGHT(c) 2019 STMicroelectronics

+** © COPYRIGHT(c) 2019 STMicroelectronics ** ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: diff --git a/buildroot/share/PlatformIO/variants/MARLIN_F407VE/hal_conf_custom.h b/buildroot/share/PlatformIO/variants/MARLIN_F407VE/hal_conf_custom.h index 92e9fecb4d63..8a8930be667a 100644 --- a/buildroot/share/PlatformIO/variants/MARLIN_F407VE/hal_conf_custom.h +++ b/buildroot/share/PlatformIO/variants/MARLIN_F407VE/hal_conf_custom.h @@ -5,8 +5,8 @@ ****************************************************************************** * @attention * - *

© Copyright (c) 2017 STMicroelectronics. - * All rights reserved.

+ * Copyright (c) 2017 STMicroelectronics. + * All rights reserved. * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the diff --git a/buildroot/share/PlatformIO/variants/MARLIN_F407VE/ldscript.ld b/buildroot/share/PlatformIO/variants/MARLIN_F407VE/ldscript.ld index efe2db5cd472..c4da3ba1fad3 100644 --- a/buildroot/share/PlatformIO/variants/MARLIN_F407VE/ldscript.ld +++ b/buildroot/share/PlatformIO/variants/MARLIN_F407VE/ldscript.ld @@ -21,7 +21,7 @@ ***************************************************************************** ** @attention ** -**

© COPYRIGHT(c) 2014 Ac6

+** © COPYRIGHT(c) 2014 Ac6 ** ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: diff --git a/buildroot/share/PlatformIO/variants/MARLIN_FYSETC_S6/ldscript.ld b/buildroot/share/PlatformIO/variants/MARLIN_FYSETC_S6/ldscript.ld index 2a61072cb17e..5dfe50afee19 100644 --- a/buildroot/share/PlatformIO/variants/MARLIN_FYSETC_S6/ldscript.ld +++ b/buildroot/share/PlatformIO/variants/MARLIN_FYSETC_S6/ldscript.ld @@ -21,7 +21,7 @@ ***************************************************************************** ** @attention ** -**

© COPYRIGHT(c) 2014 Ac6

+** © COPYRIGHT(c) 2014 Ac6 ** ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: diff --git a/buildroot/share/PlatformIO/variants/STEVAL_F401VE/hal_conf_custom.h b/buildroot/share/PlatformIO/variants/STEVAL_F401VE/hal_conf_custom.h index 0c7781997fef..188be7b327e6 100644 --- a/buildroot/share/PlatformIO/variants/STEVAL_F401VE/hal_conf_custom.h +++ b/buildroot/share/PlatformIO/variants/STEVAL_F401VE/hal_conf_custom.h @@ -5,8 +5,8 @@ ****************************************************************************** * @attention * - *

© Copyright (c) 2017 STMicroelectronics. - * All rights reserved.

+ * Copyright (c) 2017 STMicroelectronics. + * All rights reserved. * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the diff --git a/buildroot/share/PlatformIO/variants/STEVAL_F401VE/ldscript.ld b/buildroot/share/PlatformIO/variants/STEVAL_F401VE/ldscript.ld index f20a047c6574..31d16fd30201 100644 --- a/buildroot/share/PlatformIO/variants/STEVAL_F401VE/ldscript.ld +++ b/buildroot/share/PlatformIO/variants/STEVAL_F401VE/ldscript.ld @@ -20,7 +20,7 @@ ***************************************************************************** ** @attention ** -**

© COPYRIGHT(c) 2014 Ac6

+** © COPYRIGHT(c) 2014 Ac6 ** ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: diff --git a/platformio.ini b/platformio.ini index 52310e6b8198..47493f2d1be3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -60,6 +60,7 @@ default_src_filter = + - - + - - - + - - - - - @@ -273,6 +274,7 @@ TOUCH_UI_FTDI_EVE = src_filter=+ EXTUI_EXAMPLE = src_filter=+ MALYAN_LCD = src_filter=+ USB_FLASH_DRIVE_SUPPORT = src_filter=+ +USB_HOST_MSC_FLASH_SUPPORT = src_filter=+ + AUTO_BED_LEVELING_BILINEAR = src_filter=+ AUTO_BED_LEVELING_(3POINT|(BI)?LINEAR) = src_filter=+ MESH_BED_LEVELING = src_filter=+ +