From ec7a84c54047d84e83022f927599fde59bfde58f Mon Sep 17 00:00:00 2001 From: jnosky Date: Sat, 12 Nov 2011 16:20:02 -0500 Subject: [PATCH] Added USB Host library sources --- .../Class/HID/inc/usbh_hid_core.h | 195 ++++ .../Class/HID/inc/usbh_hid_keybd.h | 122 +++ .../Class/HID/inc/usbh_hid_mouse.h | 114 +++ .../Class/HID/src/usbh_hid_core.c | 640 +++++++++++++ .../Class/HID/src/usbh_hid_keybd.c | 338 +++++++ .../Class/HID/src/usbh_hid_mouse.c | 155 ++++ .../Class/MSC/inc/usbh_msc_bot.h | 221 +++++ .../Class/MSC/inc/usbh_msc_core.h | 141 +++ .../Class/MSC/inc/usbh_msc_scsi.h | 163 ++++ .../Class/MSC/src/usbh_msc_bot.c | 613 +++++++++++++ .../Class/MSC/src/usbh_msc_core.c | 559 ++++++++++++ .../Class/MSC/src/usbh_msc_fatfs.c | 186 ++++ .../Class/MSC/src/usbh_msc_scsi.c | 674 ++++++++++++++ .../Core/inc/usbh_conf_template.h | 94 ++ .../Core/inc/usbh_core.h | 289 ++++++ .../Core/inc/usbh_def.h | 280 ++++++ .../Core/inc/usbh_hcs.h | 125 +++ .../Core/inc/usbh_ioreq.h | 140 +++ .../Core/inc/usbh_stdreq.h | 148 +++ .../Core/src/usbh_core.c | 842 ++++++++++++++++++ .../Core/src/usbh_hcs.c | 253 ++++++ .../Core/src/usbh_ioreq.c | 419 +++++++++ .../Core/src/usbh_stdreq.c | 551 ++++++++++++ 23 files changed, 7262 insertions(+) create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Class/HID/inc/usbh_hid_core.h create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Class/HID/inc/usbh_hid_keybd.h create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Class/HID/inc/usbh_hid_mouse.h create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Class/HID/src/usbh_hid_core.c create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Class/HID/src/usbh_hid_keybd.c create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Class/HID/src/usbh_hid_mouse.c create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Class/MSC/inc/usbh_msc_bot.h create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Class/MSC/inc/usbh_msc_core.h create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Class/MSC/inc/usbh_msc_scsi.h create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_bot.c create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_core.c create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_fatfs.c create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_scsi.c create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_conf_template.h create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_core.h create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_def.h create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_hcs.h create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_ioreq.h create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_stdreq.h create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Core/src/usbh_core.c create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Core/src/usbh_hcs.c create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Core/src/usbh_ioreq.c create mode 100644 example/stm32f4/STM32_USB_HOST_Library/Core/src/usbh_stdreq.c diff --git a/example/stm32f4/STM32_USB_HOST_Library/Class/HID/inc/usbh_hid_core.h b/example/stm32f4/STM32_USB_HOST_Library/Class/HID/inc/usbh_hid_core.h new file mode 100644 index 0000000..e6d0b79 --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Class/HID/inc/usbh_hid_core.h @@ -0,0 +1,195 @@ +/** + ****************************************************************************** + * @file usbh_hid_core.h + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief This file contains all the prototypes for the usbh_hid_core.c + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_HID_CORE_H +#define __USBH_HID_CORE_H + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_core.h" +#include "usbh_stdreq.h" +#include "usb_bsp.h" +#include "usbh_ioreq.h" +#include "usbh_hcs.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_CLASS + * @{ + */ + +/** @addtogroup USBH_HID_CLASS + * @{ + */ + +/** @defgroup USBH_HID_CORE + * @brief This file is the Header file for USBH_HID_CORE.c + * @{ + */ + + +/** @defgroup USBH_HID_CORE_Exported_Types + * @{ + */ + + +/* States for HID State Machine */ +typedef enum +{ + HID_IDLE= 0, + HID_SEND_DATA, + HID_BUSY, + HID_GET_DATA, + HID_POLL, + HID_ERROR, +} +HID_State; + +typedef enum +{ + HID_REQ_IDLE = 0, + HID_REQ_GET_REPORT_DESC, + HID_REQ_GET_HID_DESC, + HID_REQ_SET_IDLE, + HID_REQ_SET_PROTOCOL, + HID_REQ_SET_REPORT, + +} +HID_CtlState; + +typedef struct HID_cb +{ + void (*Init) (void); + void (*Decode) (uint8_t *data); + +} HID_cb_TypeDef; + +typedef struct _HID_Report +{ + uint8_t ReportID; + uint8_t ReportType; + uint16_t UsagePage; + uint32_t Usage[2]; + uint32_t NbrUsage; + uint32_t UsageMin; + uint32_t UsageMax; + int32_t LogMin; + int32_t LogMax; + int32_t PhyMin; + int32_t PhyMax; + int32_t UnitExp; + uint32_t Unit; + uint32_t ReportSize; + uint32_t ReportCnt; + uint32_t Flag; + uint32_t PhyUsage; + uint32_t AppUsage; + uint32_t LogUsage; +} +HID_Report_TypeDef; + +/* Structure for HID process */ +typedef struct _HID_Process +{ + uint8_t buff[64]; + uint8_t hc_num_in; + uint8_t hc_num_out; + HID_State state; + uint8_t HIDIntOutEp; + uint8_t HIDIntInEp; + HID_CtlState ctl_state; + uint16_t length; + uint8_t ep_addr; + uint16_t poll; + __IO uint16_t timer; + HID_cb_TypeDef *cb; +} +HID_Machine_TypeDef; + +/** + * @} + */ + +/** @defgroup USBH_HID_CORE_Exported_Defines + * @{ + */ + +#define USB_HID_REQ_GET_REPORT 0x01 +#define USB_HID_GET_IDLE 0x02 +#define USB_HID_GET_PROTOCOL 0x03 +#define USB_HID_SET_REPORT 0x09 +#define USB_HID_SET_IDLE 0x0A +#define USB_HID_SET_PROTOCOL 0x0B +/** + * @} + */ + +/** @defgroup USBH_HID_CORE_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_HID_CORE_Exported_Variables + * @{ + */ +extern USBH_Class_cb_TypeDef HID_cb; +/** + * @} + */ + +/** @defgroup USBH_HID_CORE_Exported_FunctionsPrototype + * @{ + */ + +USBH_Status USBH_Set_Report (USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t reportType, + uint8_t reportId, + uint8_t reportLen, + uint8_t* reportBuff); +/** + * @} + */ + + +#endif /* __USBH_HID_CORE_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + diff --git a/example/stm32f4/STM32_USB_HOST_Library/Class/HID/inc/usbh_hid_keybd.h b/example/stm32f4/STM32_USB_HOST_Library/Class/HID/inc/usbh_hid_keybd.h new file mode 100644 index 0000000..08f6b9f --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Class/HID/inc/usbh_hid_keybd.h @@ -0,0 +1,122 @@ +/** + ****************************************************************************** + * @file usbh_hid_keybd.h + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief This file contains all the prototypes for the usbh_hid_keybd.c + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive -----------------------------------------------*/ +#ifndef __USBH_HID_KEYBD_H +#define __USBH_HID_KEYBD_H + +/* Includes ------------------------------------------------------------------*/ +#include "usb_conf.h" +#include "usbh_hid_core.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_CLASS + * @{ + */ + +/** @addtogroup USBH_HID_CLASS + * @{ + */ + +/** @defgroup USBH_HID_KEYBD + * @brief This file is the Header file for USBH_HID_KEYBD.c + * @{ + */ + + +/** @defgroup USBH_HID_KEYBD_Exported_Types + * @{ + */ + + +/** + * @} + */ + +/** @defgroup USBH_HID_KEYBD_Exported_Defines + * @{ + */ +//#define QWERTY_KEYBOARD +#define AZERTY_KEYBOARD + +#define KBD_LEFT_CTRL 0x01 +#define KBD_LEFT_SHIFT 0x02 +#define KBD_LEFT_ALT 0x04 +#define KBD_LEFT_GUI 0x08 +#define KBD_RIGHT_CTRL 0x10 +#define KBD_RIGHT_SHIFT 0x20 +#define KBD_RIGHT_ALT 0x40 +#define KBD_RIGHT_GUI 0x80 + +#define KBR_MAX_NBR_PRESSED 6 + +/** + * @} + */ + +/** @defgroup USBH_HID_KEYBD_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_HID_KEYBD_Exported_Variables + * @{ + */ + +extern HID_cb_TypeDef HID_KEYBRD_cb; +/** + * @} + */ + +/** @defgroup USBH_HID_KEYBD_Exported_FunctionsPrototype + * @{ + */ +void USR_KEYBRD_Init (void); +void USR_KEYBRD_ProcessData (uint8_t pbuf); +/** + * @} + */ + +#endif /* __USBH_HID_KEYBD_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + diff --git a/example/stm32f4/STM32_USB_HOST_Library/Class/HID/inc/usbh_hid_mouse.h b/example/stm32f4/STM32_USB_HOST_Library/Class/HID/inc/usbh_hid_mouse.h new file mode 100644 index 0000000..eb2c2ae --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Class/HID/inc/usbh_hid_mouse.h @@ -0,0 +1,114 @@ +/** + ****************************************************************************** + * @file usbh_hid_mouse.h + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief This file contains all the prototypes for the usbh_hid_mouse.c + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_HID_MOUSE_H +#define __USBH_HID_MOUSE_H + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_hid_core.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_CLASS + * @{ + */ + +/** @addtogroup USBH_HID_CLASS + * @{ + */ + +/** @defgroup USBH_HID_MOUSE + * @brief This file is the Header file for USBH_HID_MOUSE.c + * @{ + */ + + +/** @defgroup USBH_HID_MOUSE_Exported_Types + * @{ + */ +typedef struct _HID_MOUSE_Data +{ + uint8_t x; + uint8_t y; + uint8_t z; /* Not Supported */ + uint8_t button; +} +HID_MOUSE_Data_TypeDef; + +/** + * @} + */ + +/** @defgroup USBH_HID_MOUSE_Exported_Defines + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_HID_MOUSE_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_HID_MOUSE_Exported_Variables + * @{ + */ + +extern HID_cb_TypeDef HID_MOUSE_cb; +extern HID_MOUSE_Data_TypeDef HID_MOUSE_Data; +/** + * @} + */ + +/** @defgroup USBH_HID_MOUSE_Exported_FunctionsPrototype + * @{ + */ +void USR_MOUSE_Init (void); +void USR_MOUSE_ProcessData (HID_MOUSE_Data_TypeDef *data); +/** + * @} + */ + +#endif /* __USBH_HID_MOUSE_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/example/stm32f4/STM32_USB_HOST_Library/Class/HID/src/usbh_hid_core.c b/example/stm32f4/STM32_USB_HOST_Library/Class/HID/src/usbh_hid_core.c new file mode 100644 index 0000000..53cb196 --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Class/HID/src/usbh_hid_core.c @@ -0,0 +1,640 @@ +/** + ****************************************************************************** + * @file usbh_hid_core.c + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief This file is the HID Layer Handlers for USB Host HID class. + * + * @verbatim + * + * =================================================================== + * HID Class Description + * =================================================================== + * This module manages the MSC class V1.11 following the "Device Class Definition + * for Human Interface Devices (HID) Version 1.11 Jun 27, 2001". + * This driver implements the following aspects of the specification: + * - The Boot Interface Subclass + * - The Mouse and Keyboard protocols + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_hid_core.h" +#include "usbh_hid_mouse.h" +#include "usbh_hid_keybd.h" + +/** @addtogroup USBH_LIB +* @{ +*/ + +/** @addtogroup USBH_CLASS +* @{ +*/ + +/** @addtogroup USBH_HID_CLASS +* @{ +*/ + +/** @defgroup USBH_HID_CORE +* @brief This file includes HID Layer Handlers for USB Host HID class. +* @{ +*/ + +/** @defgroup USBH_HID_CORE_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_HID_CORE_Private_Defines +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_HID_CORE_Private_Macros +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_HID_CORE_Private_Variables +* @{ +*/ +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN HID_Machine_TypeDef HID_Machine __ALIGN_END ; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN HID_Report_TypeDef HID_Report __ALIGN_END ; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN USB_Setup_TypeDef HID_Setup __ALIGN_END ; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN USBH_HIDDesc_TypeDef HID_Desc __ALIGN_END ; + +__IO uint8_t flag = 0; +/** +* @} +*/ + + +/** @defgroup USBH_HID_CORE_Private_FunctionPrototypes +* @{ +*/ + +static USBH_Status USBH_HID_InterfaceInit (USB_OTG_CORE_HANDLE *pdev , + void *phost); + +static void USBH_ParseHIDDesc (USBH_HIDDesc_TypeDef *desc, uint8_t *buf); + +static void USBH_HID_InterfaceDeInit (USB_OTG_CORE_HANDLE *pdev , + void *phost); + +static USBH_Status USBH_HID_Handle(USB_OTG_CORE_HANDLE *pdev , + void *phost); + +static USBH_Status USBH_HID_ClassRequest(USB_OTG_CORE_HANDLE *pdev , + void *phost); + +static USBH_Status USBH_Get_HID_ReportDescriptor (USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint16_t length); + +static USBH_Status USBH_Get_HID_Descriptor (USB_OTG_CORE_HANDLE *pdev,\ + USBH_HOST *phost, + uint16_t length); + +static USBH_Status USBH_Set_Idle (USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t duration, + uint8_t reportId); + +static USBH_Status USBH_Set_Protocol (USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t protocol); + + +USBH_Class_cb_TypeDef HID_cb = +{ + USBH_HID_InterfaceInit, + USBH_HID_InterfaceDeInit, + USBH_HID_ClassRequest, + USBH_HID_Handle +}; +/** +* @} +*/ + + +/** @defgroup USBH_HID_CORE_Private_Functions +* @{ +*/ + +/** +* @brief USBH_HID_InterfaceInit +* The function init the HID class. +* @param pdev: Selected device +* @param hdev: Selected device property +* @retval USBH_Status :Response for USB HID driver intialization +*/ +static USBH_Status USBH_HID_InterfaceInit ( USB_OTG_CORE_HANDLE *pdev, + void *phost) +{ + uint8_t maxEP; + USBH_HOST *pphost = phost; + + uint8_t num =0; + USBH_Status status = USBH_BUSY ; + HID_Machine.state = HID_ERROR; + + + if(pphost->device_prop.Itf_Desc[0].bInterfaceSubClass == HID_BOOT_CODE) + { + /*Decode Bootclass Protocl: Mouse or Keyboard*/ + if(pphost->device_prop.Itf_Desc[0].bInterfaceProtocol == HID_KEYBRD_BOOT_CODE) + { + HID_Machine.cb = &HID_KEYBRD_cb; + } + else if(pphost->device_prop.Itf_Desc[0].bInterfaceProtocol == HID_MOUSE_BOOT_CODE) + { + HID_Machine.cb = &HID_MOUSE_cb; + } + + HID_Machine.state = HID_IDLE; + HID_Machine.ctl_state = HID_REQ_IDLE; + HID_Machine.ep_addr = pphost->device_prop.Ep_Desc[0][0].bEndpointAddress; + HID_Machine.length = pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize; + HID_Machine.poll = pphost->device_prop.Ep_Desc[0][0].bInterval ; + + /* Check fo available number of endpoints */ + /* Find the number of EPs in the Interface Descriptor */ + /* Choose the lower number in order not to overrun the buffer allocated */ + maxEP = ( (pphost->device_prop.Itf_Desc[0].bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) ? + pphost->device_prop.Itf_Desc[0].bNumEndpoints : + USBH_MAX_NUM_ENDPOINTS); + + + /* Decode endpoint IN and OUT address from interface descriptor */ + for (num=0; num < maxEP; num++) + { + if(pphost->device_prop.Ep_Desc[0][num].bEndpointAddress & 0x80) + { + HID_Machine.HIDIntInEp = (pphost->device_prop.Ep_Desc[0][num].bEndpointAddress); + HID_Machine.hc_num_in =\ + USBH_Alloc_Channel(pdev, + pphost->device_prop.Ep_Desc[0][num].bEndpointAddress); + + /* Open channel for IN endpoint */ + USBH_Open_Channel (pdev, + HID_Machine.hc_num_in, + pphost->device_prop.address, + pphost->device_prop.speed, + EP_TYPE_INTR, + HID_Machine.length); + } + else + { + HID_Machine.HIDIntOutEp = (pphost->device_prop.Ep_Desc[0][num].bEndpointAddress); + HID_Machine.hc_num_out =\ + USBH_Alloc_Channel(pdev, + pphost->device_prop.Ep_Desc[0][num].bEndpointAddress); + + /* Open channel for OUT endpoint */ + USBH_Open_Channel (pdev, + HID_Machine.hc_num_out, + pphost->device_prop.address, + pphost->device_prop.speed, + EP_TYPE_INTR, + HID_Machine.length); + } + + } + + flag =0; + status = USBH_OK; + } + else + { + pphost->usr_cb->USBH_USR_DeviceNotSupported(); + } + + return status; + +} + + + +/** +* @brief USBH_HID_InterfaceDeInit +* The function DeInit the Host Channels used for the HID class. +* @param pdev: Selected device +* @param hdev: Selected device property +* @retval None +*/ +void USBH_HID_InterfaceDeInit ( USB_OTG_CORE_HANDLE *pdev, + void *phost) +{ + //USBH_HOST *pphost = phost; + + if(HID_Machine.hc_num_in != 0x00) + { + USB_OTG_HC_Halt(pdev, HID_Machine.hc_num_in); + USBH_Free_Channel (pdev, HID_Machine.hc_num_in); + HID_Machine.hc_num_in = 0; /* Reset the Channel as Free */ + } + + if(HID_Machine.hc_num_out != 0x00) + { + USB_OTG_HC_Halt(pdev, HID_Machine.hc_num_out); + USBH_Free_Channel (pdev, HID_Machine.hc_num_out); + HID_Machine.hc_num_out = 0; /* Reset the Channel as Free */ + } + + flag = 0; +} + +/** +* @brief USBH_HID_ClassRequest +* The function is responsible for handling HID Class requests +* for HID class. +* @param pdev: Selected device +* @param hdev: Selected device property +* @retval USBH_Status :Response for USB Set Protocol request +*/ +static USBH_Status USBH_HID_ClassRequest(USB_OTG_CORE_HANDLE *pdev , + void *phost) +{ + USBH_HOST *pphost = phost; + + USBH_Status status = USBH_BUSY; + USBH_Status classReqStatus = USBH_BUSY; + + + /* Switch HID state machine */ + switch (HID_Machine.ctl_state) + { + case HID_IDLE: + case HID_REQ_GET_HID_DESC: + + /* Get HID Desc */ + if (USBH_Get_HID_Descriptor (pdev, pphost, USB_HID_DESC_SIZE)== USBH_OK) + { + + USBH_ParseHIDDesc(&HID_Desc, pdev->host.Rx_Buffer); + HID_Machine.ctl_state = HID_REQ_GET_REPORT_DESC; + } + + break; + case HID_REQ_GET_REPORT_DESC: + + + /* Get Report Desc */ + if (USBH_Get_HID_ReportDescriptor(pdev , pphost, HID_Desc.wItemLength) == USBH_OK) + { + HID_Machine.ctl_state = HID_REQ_SET_IDLE; + } + + break; + + case HID_REQ_SET_IDLE: + + classReqStatus = USBH_Set_Idle (pdev, pphost, 0, 0); + + /* set Idle */ + if (classReqStatus == USBH_OK) + { + HID_Machine.ctl_state = HID_REQ_SET_PROTOCOL; + } + else if(classReqStatus == USBH_NOT_SUPPORTED) + { + HID_Machine.ctl_state = HID_REQ_SET_PROTOCOL; + } + break; + + case HID_REQ_SET_PROTOCOL: + /* set protocol */ + if (USBH_Set_Protocol (pdev ,pphost, 0) == USBH_OK) + { + HID_Machine.ctl_state = HID_REQ_IDLE; + + /* all requests performed*/ + status = USBH_OK; + } + break; + + default: + break; + } + + return status; +} + + +/** +* @brief USBH_HID_Handle +* The function is for managing state machine for HID data transfers +* @param pdev: Selected device +* @param hdev: Selected device property +* @retval USBH_Status +*/ +static USBH_Status USBH_HID_Handle(USB_OTG_CORE_HANDLE *pdev , + void *phost) +{ + USBH_HOST *pphost = phost; + USBH_Status status = USBH_OK; + + switch (HID_Machine.state) + { + + case HID_IDLE: + HID_Machine.cb->Init(); + HID_Machine.state = HID_GET_DATA; + break; + + case HID_GET_DATA: + + /* Sync with start of Even Frame */ + while(USB_OTG_IsEvenFrame(pdev) == FALSE); + + USBH_InterruptReceiveData(pdev, + HID_Machine.buff, + HID_Machine.length, + HID_Machine.hc_num_in); + flag = 1; + + HID_Machine.state = HID_POLL; + HID_Machine.timer = HCD_GetCurrentFrame(pdev); + break; + + case HID_POLL: + if(( HCD_GetCurrentFrame(pdev) - HID_Machine.timer) >= HID_Machine.poll) + { + HID_Machine.state = HID_GET_DATA; + } + else if(HCD_GetURB_State(pdev , HID_Machine.hc_num_in) == URB_DONE) + { + if(flag == 1) /* handle data once */ + { + flag = 0; + HID_Machine.cb->Decode(HID_Machine.buff); + } + } + else if(HCD_GetURB_State(pdev, HID_Machine.hc_num_in) == URB_STALL) /* IN Endpoint Stalled */ + { + + /* Issue Clear Feature on interrupt IN endpoint */ + if( (USBH_ClrFeature(pdev, + pphost, + HID_Machine.ep_addr, + HID_Machine.hc_num_in)) == USBH_OK) + { + /* Change state to issue next IN token */ + HID_Machine.state = HID_GET_DATA; + + } + + } + break; + + default: + break; + } + return status; +} + + +/** +* @brief USBH_Get_HID_ReportDescriptor +* Issue report Descriptor command to the device. Once the response +* received, parse the report descriptor and update the status. +* @param pdev : Selected device +* @param Length : HID Report Descriptor Length +* @retval USBH_Status : Response for USB HID Get Report Descriptor Request +*/ +static USBH_Status USBH_Get_HID_ReportDescriptor (USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint16_t length) +{ + + USBH_Status status; + + status = USBH_GetDescriptor(pdev, + phost, + USB_REQ_RECIPIENT_INTERFACE + | USB_REQ_TYPE_STANDARD, + USB_DESC_HID_REPORT, + pdev->host.Rx_Buffer, + length); + + /* HID report descriptor is available in pdev->host.Rx_Buffer. + In case of USB Boot Mode devices for In report handling , + HID report descriptor parsing is not required. + In case, for supporting Non-Boot Protocol devices and output reports, + user may parse the report descriptor*/ + + + return status; +} + +/** +* @brief USBH_Get_HID_Descriptor +* Issue HID Descriptor command to the device. Once the response +* received, parse the report descriptor and update the status. +* @param pdev : Selected device +* @param Length : HID Descriptor Length +* @retval USBH_Status : Response for USB HID Get Report Descriptor Request +*/ +static USBH_Status USBH_Get_HID_Descriptor (USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint16_t length) +{ + + USBH_Status status; + + status = USBH_GetDescriptor(pdev, + phost, + USB_REQ_RECIPIENT_INTERFACE + | USB_REQ_TYPE_STANDARD, + USB_DESC_HID, + pdev->host.Rx_Buffer, + length); + + return status; +} + +/** +* @brief USBH_Set_Idle +* Set Idle State. +* @param pdev: Selected device +* @param duration: Duration for HID Idle request +* @param reportID : Targetted report ID for Set Idle request +* @retval USBH_Status : Response for USB Set Idle request +*/ +static USBH_Status USBH_Set_Idle (USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t duration, + uint8_t reportId) +{ + + phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\ + USB_REQ_TYPE_CLASS; + + + phost->Control.setup.b.bRequest = USB_HID_SET_IDLE; + phost->Control.setup.b.wValue.w = (duration << 8 ) | reportId; + + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = 0; + + return USBH_CtlReq(pdev, phost, 0 , 0 ); +} + + +/** +* @brief USBH_Set_Report +* Issues Set Report +* @param pdev: Selected device +* @param reportType : Report type to be sent +* @param reportID : Targetted report ID for Set Report request +* @param reportLen : Length of data report to be send +* @param reportBuff : Report Buffer +* @retval USBH_Status : Response for USB Set Idle request +*/ +USBH_Status USBH_Set_Report (USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t reportType, + uint8_t reportId, + uint8_t reportLen, + uint8_t* reportBuff) +{ + + phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\ + USB_REQ_TYPE_CLASS; + + + phost->Control.setup.b.bRequest = USB_HID_SET_REPORT; + phost->Control.setup.b.wValue.w = (reportType << 8 ) | reportId; + + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = reportLen; + + return USBH_CtlReq(pdev, phost, reportBuff , reportLen ); +} + + +/** +* @brief USBH_Set_Protocol +* Set protocol State. +* @param pdev: Selected device +* @param protocol : Set Protocol for HID : boot/report protocol +* @retval USBH_Status : Response for USB Set Protocol request +*/ +static USBH_Status USBH_Set_Protocol(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t protocol) +{ + + + phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\ + USB_REQ_TYPE_CLASS; + + + phost->Control.setup.b.bRequest = USB_HID_SET_PROTOCOL; + + if(protocol != 0) + { + /* Boot Protocol */ + phost->Control.setup.b.wValue.w = 0; + } + else + { + /*Report Protocol*/ + phost->Control.setup.b.wValue.w = 1; + } + + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = 0; + + return USBH_CtlReq(pdev, phost, 0 , 0 ); + +} + +/** +* @brief USBH_ParseHIDDesc +* This function Parse the HID descriptor +* @param buf: Buffer where the source descriptor is available +* @retval None +*/ +static void USBH_ParseHIDDesc (USBH_HIDDesc_TypeDef *desc, uint8_t *buf) +{ + + desc->bLength = *(uint8_t *) (buf + 0); + desc->bDescriptorType = *(uint8_t *) (buf + 1); + desc->bcdHID = LE16 (buf + 2); + desc->bCountryCode = *(uint8_t *) (buf + 4); + desc->bNumDescriptors = *(uint8_t *) (buf + 5); + desc->bReportDescriptorType = *(uint8_t *) (buf + 6); + desc->wItemLength = LE16 (buf + 7); + +} +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + + +/** +* @} +*/ + + +/** +* @} +*/ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/example/stm32f4/STM32_USB_HOST_Library/Class/HID/src/usbh_hid_keybd.c b/example/stm32f4/STM32_USB_HOST_Library/Class/HID/src/usbh_hid_keybd.c new file mode 100644 index 0000000..ae0df34 --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Class/HID/src/usbh_hid_keybd.c @@ -0,0 +1,338 @@ +/** + ****************************************************************************** + * @file usbh_hid_keybd.c + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief This file is the application layer for USB Host HID Keyboard handling + * QWERTY and AZERTY Keyboard are supported as per the selection in + * usbh_hid_keybd.h + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_hid_keybd.h" + +/** @addtogroup USBH_LIB +* @{ +*/ + +/** @addtogroup USBH_CLASS +* @{ +*/ + +/** @addtogroup USBH_HID_CLASS +* @{ +*/ + +/** @defgroup USBH_HID_KEYBD +* @brief This file includes HID Layer Handlers for USB Host HID class. +* @{ +*/ + +/** @defgroup USBH_HID_KEYBD_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_HID_KEYBD_Private_Defines +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_HID_KEYBD_Private_Macros +* @{ +*/ +/** +* @} +*/ + +/** @defgroup USBH_HID_KEYBD_Private_FunctionPrototypes +* @{ +*/ +static void KEYBRD_Init (void); +static void KEYBRD_Decode(uint8_t *data); + +/** +* @} +*/ + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined (__CC_ARM) /*!< ARM Compiler */ + __align(4) + #elif defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #elif defined (__GNUC__) /*!< GNU Compiler */ + #pragma pack(4) + #elif defined (__TASKING__) /*!< TASKING Compiler */ + __align(4) + #endif /* __CC_ARM */ +#endif + +/** @defgroup USBH_HID_KEYBD_Private_Variables +* @{ +*/ +HID_cb_TypeDef HID_KEYBRD_cb= +{ + KEYBRD_Init, + KEYBRD_Decode +}; + +/* +******************************************************************************* +* LOCAL CONSTANTS +******************************************************************************* +*/ + +static const uint8_t HID_KEYBRD_Codes[] = { + 0, 0, 0, 0, 31, 50, 48, 33, + 19, 34, 35, 36, 24, 37, 38, 39, /* 0x00 - 0x0F */ + 52, 51, 25, 26, 17, 20, 32, 21, + 23, 49, 18, 47, 22, 46, 2, 3, /* 0x10 - 0x1F */ + 4, 5, 6, 7, 8, 9, 10, 11, + 43, 110, 15, 16, 61, 12, 13, 27, /* 0x20 - 0x2F */ + 28, 29, 42, 40, 41, 1, 53, 54, + 55, 30, 112, 113, 114, 115, 116, 117, /* 0x30 - 0x3F */ + 118, 119, 120, 121, 122, 123, 124, 125, + 126, 75, 80, 85, 76, 81, 86, 89, /* 0x40 - 0x4F */ + 79, 84, 83, 90, 95, 100, 105, 106, + 108, 93, 98, 103, 92, 97, 102, 91, /* 0x50 - 0x5F */ + 96, 101, 99, 104, 45, 129, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7F */ + 0, 0, 0, 0, 0, 107, 0, 56, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xAF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 - 0xBF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xCF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xDF */ + 58, 44, 60, 127, 64, 57, 62, 128 /* 0xE0 - 0xE7 */ +}; + +#ifdef QWERTY_KEYBOARD +static const int8_t HID_KEYBRD_Key[] = { + '\0', '`', '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', '\0', '\r', + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', + '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', + 'k', 'l', ';', '\'', '\0', '\n', + '\0', '\0', 'z', 'x', 'c', 'v', 'b', 'n', + 'm', ',', '.', '/', '\0', '\0', + '\0', '\0', '\0', ' ', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '7', '4', '1', + '\0', '/', '8', '5', '2', + '0', '*', '9', '6', '3', + '.', '-', '+', '\0', '\n', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0' +}; + +static const int8_t HID_KEYBRD_ShiftKey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', + '_', '+', '\0', '\0', '\0', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', + 'I', 'O', 'P', '{', '}', '|', '\0', 'A', 'S', 'D', 'F', 'G', + 'H', 'J', 'K', 'L', ':', '"', '\0', '\n', '\0', '\0', 'Z', 'X', + 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#else + +static const int8_t HID_KEYBRD_Key[] = { + '\0', '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + '-', '=', '\0', '\r', '\t', 'a', 'z', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', '\0', 'q', 's', 'd', 'f', 'g', + 'h', 'j', 'k', 'l', 'm', '\0', '\0', '\n', '\0', '\0', 'w', 'x', + 'c', 'v', 'b', 'n', ',', ';', ':', '!', '\0', '\0', '\0', '\0', + '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '4', '1','\0', '/', + '8', '5', '2', '0', '*', '9', '6', '3', '.', '-', '+', '\0', + '\n', '\0', '\0', '\0', '\0', '\0', '\0','\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +static const int8_t HID_KEYBRD_ShiftKey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', + '+', '\0', '\0', '\0', 'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', + 'P', '{', '}', '*', '\0', 'Q', 'S', 'D', 'F', 'G', 'H', 'J', 'K', + 'L', 'M', '%', '\0', '\n', '\0', '\0', 'W', 'X', 'C', 'V', 'B', 'N', + '?', '.', '/', '\0', '\0', '\0','\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; +#endif + +/** +* @} +*/ + + +/** @defgroup USBH_HID_KEYBD_Private_Functions +* @{ +*/ + + +/** +* @brief KEYBRD_Init. +* Initialize the keyboard function. +* @param None +* @retval None +*/ +static void KEYBRD_Init (void) +{ + /* Call User Init*/ + USR_KEYBRD_Init(); +} + +/** +* @brief KEYBRD_ProcessData. +* The function is to decode the pressed keys. +* @param pbuf : Pointer to the HID IN report data buffer +* @retval None +*/ + +static void KEYBRD_Decode(uint8_t *pbuf) +{ + static uint8_t shift; + static uint8_t keys[KBR_MAX_NBR_PRESSED]; + static uint8_t keys_new[KBR_MAX_NBR_PRESSED]; + static uint8_t keys_last[KBR_MAX_NBR_PRESSED]; + static uint8_t key_newest; + static uint8_t nbr_keys; + static uint8_t nbr_keys_new; + static uint8_t nbr_keys_last; + uint8_t ix; + uint8_t jx; + uint8_t error; + uint8_t output; + + nbr_keys = 0; + nbr_keys_new = 0; + nbr_keys_last = 0; + key_newest = 0x00; + + + /* Check if Shift key is pressed */ + if ((pbuf[0] == KBD_LEFT_SHIFT) || (pbuf[0] == KBD_RIGHT_SHIFT)) { + shift = TRUE; + } else { + shift = FALSE; + } + + error = FALSE; + + /* Check for the value of pressed key */ + for (ix = 2; ix < 2 + KBR_MAX_NBR_PRESSED; ix++) { + if ((pbuf[ix] == 0x01) || + (pbuf[ix] == 0x02) || + (pbuf[ix] == 0x03)) { + error = TRUE; + } + } + + if (error == TRUE) { + return; + } + + nbr_keys = 0; + nbr_keys_new = 0; + for (ix = 2; ix < 2 + KBR_MAX_NBR_PRESSED; ix++) { + if (pbuf[ix] != 0) { + keys[nbr_keys] = pbuf[ix]; + nbr_keys++; + for (jx = 0; jx < nbr_keys_last; jx++) { + if (pbuf[ix] == keys_last[jx]) { + break; + } + } + + if (jx == nbr_keys_last) { + keys_new[nbr_keys_new] = pbuf[ix]; + nbr_keys_new++; + } + } + } + + if (nbr_keys_new == 1) { + key_newest = keys_new[0]; + + if (shift == TRUE) { + output = HID_KEYBRD_ShiftKey[HID_KEYBRD_Codes[key_newest]]; + } else { + output = HID_KEYBRD_Key[HID_KEYBRD_Codes[key_newest]]; + } + + /* call user process handle */ + USR_KEYBRD_ProcessData(output); + } else { + key_newest = 0x00; + } + + + nbr_keys_last = nbr_keys; + for (ix = 0; ix < KBR_MAX_NBR_PRESSED; ix++) { + keys_last[ix] = keys[ix]; + } +} + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + + +/** +* @} +*/ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + diff --git a/example/stm32f4/STM32_USB_HOST_Library/Class/HID/src/usbh_hid_mouse.c b/example/stm32f4/STM32_USB_HOST_Library/Class/HID/src/usbh_hid_mouse.c new file mode 100644 index 0000000..f3ec2fc --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Class/HID/src/usbh_hid_mouse.c @@ -0,0 +1,155 @@ +/** + ****************************************************************************** + * @file usbh_hid_mouse.c + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief This file is the application layer for USB Host HID Mouse Handling. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_hid_mouse.h" + + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_CLASS + * @{ + */ + +/** @addtogroup USBH_HID_CLASS + * @{ + */ + +/** @defgroup USBH_HID_MOUSE + * @brief This file includes HID Layer Handlers for USB Host HID class. + * @{ + */ + +/** @defgroup USBH_HID_MOUSE_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_HID_MOUSE_Private_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_HID_MOUSE_Private_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_HID_MOUSE_Private_FunctionPrototypes + * @{ + */ +static void MOUSE_Init (void); +static void MOUSE_Decode(uint8_t *data); +/** + * @} + */ + + +/** @defgroup USBH_HID_MOUSE_Private_Variables + * @{ + */ +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined (__CC_ARM) /*!< ARM Compiler */ + __align(4) + #elif defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #elif defined (__GNUC__) /*!< GNU Compiler */ + #pragma pack(4) + #elif defined (__TASKING__) /*!< TASKING Compiler */ + __align(4) + #endif /* __CC_ARM */ +#endif + + +HID_MOUSE_Data_TypeDef HID_MOUSE_Data; +HID_cb_TypeDef HID_MOUSE_cb = +{ + MOUSE_Init, + MOUSE_Decode, +}; +/** + * @} + */ + + +/** @defgroup USBH_HID_MOUSE_Private_Functions + * @{ + */ + +/** +* @brief MOUSE_Init +* Init Mouse State. +* @param None +* @retval None +*/ +static void MOUSE_Init ( void) +{ + /* Call User Init*/ + USR_MOUSE_Init(); +} + +/** +* @brief MOUSE_Decode +* Decode Mouse data +* @param data : Pointer to Mouse HID data buffer +* @retval None +*/ +static void MOUSE_Decode(uint8_t *data) +{ + HID_MOUSE_Data.button = data[0]; + + HID_MOUSE_Data.x = data[1]; + HID_MOUSE_Data.y = data[2]; + + USR_MOUSE_ProcessData(&HID_MOUSE_Data); + +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + + +/** + * @} + */ +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/inc/usbh_msc_bot.h b/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/inc/usbh_msc_bot.h new file mode 100644 index 0000000..27e9659 --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/inc/usbh_msc_bot.h @@ -0,0 +1,221 @@ +/** + ****************************************************************************** + * @file usbh_msc_bot.h + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief Header file for usbh_msc_bot.c + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_MSC_BOT_H__ +#define __USBH_MSC_BOT_H__ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_stdreq.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_core.c + * @{ + */ + + +/** @defgroup USBH_MSC_BOT_Exported_Types + * @{ + */ + +typedef union _USBH_CBW_Block +{ + struct __CBW + { + uint32_t CBWSignature; + uint32_t CBWTag; + uint32_t CBWTransferLength; + uint8_t CBWFlags; + uint8_t CBWLUN; + uint8_t CBWLength; + uint8_t CBWCB[16]; +}field; + uint8_t CBWArray[31]; +}HostCBWPkt_TypeDef; + +typedef enum +{ + USBH_MSC_BOT_INIT_STATE = 0, + USBH_MSC_BOT_RESET, + USBH_MSC_GET_MAX_LUN, + USBH_MSC_TEST_UNIT_READY, + USBH_MSC_READ_CAPACITY10, + USBH_MSC_MODE_SENSE6, + USBH_MSC_REQUEST_SENSE, + USBH_MSC_BOT_USB_TRANSFERS, + USBH_MSC_DEFAULT_APPLI_STATE, + USBH_MSC_CTRL_ERROR_STATE, + USBH_MSC_UNRECOVERED_STATE +} +MSCState; + + +typedef struct _BOTXfer +{ +uint8_t MSCState; +uint8_t MSCStateBkp; +uint8_t MSCStateCurrent; +uint8_t CmdStateMachine; +uint8_t BOTState; +uint8_t BOTStateBkp; +uint8_t* pRxTxBuff; +uint16_t DataLength; +uint8_t BOTXferErrorCount; +uint8_t BOTXferStatus; +} USBH_BOTXfer_TypeDef; + + +typedef union _USBH_CSW_Block +{ + struct __CSW + { + uint32_t CSWSignature; + uint32_t CSWTag; + uint32_t CSWDataResidue; + uint8_t CSWStatus; + }field; + uint8_t CSWArray[13]; +}HostCSWPkt_TypeDef; + +/** + * @} + */ + + + +/** @defgroup USBH_MSC_BOT_Exported_Defines + * @{ + */ +#define USBH_MSC_SEND_CBW 1 +#define USBH_MSC_SENT_CBW 2 +#define USBH_MSC_BOT_DATAIN_STATE 3 +#define USBH_MSC_BOT_DATAOUT_STATE 4 +#define USBH_MSC_RECEIVE_CSW_STATE 5 +#define USBH_MSC_DECODE_CSW 6 +#define USBH_MSC_BOT_ERROR_IN 7 +#define USBH_MSC_BOT_ERROR_OUT 8 + + +#define USBH_MSC_BOT_CBW_SIGNATURE 0x43425355 +#define USBH_MSC_BOT_CBW_TAG 0x20304050 +#define USBH_MSC_BOT_CSW_SIGNATURE 0x53425355 +#define USBH_MSC_CSW_DATA_LENGTH 0x000D +#define USBH_MSC_BOT_CBW_PACKET_LENGTH 31 +#define USBH_MSC_CSW_LENGTH 13 +#define USBH_MSC_CSW_MAX_LENGTH 63 + +/* CSW Status Definitions */ +#define USBH_MSC_CSW_CMD_PASSED 0x00 +#define USBH_MSC_CSW_CMD_FAILED 0x01 +#define USBH_MSC_CSW_PHASE_ERROR 0x02 + +#define USBH_MSC_SEND_CSW_DISABLE 0 +#define USBH_MSC_SEND_CSW_ENABLE 1 + +#define USBH_MSC_DIR_IN 0 +#define USBH_MSC_DIR_OUT 1 +#define USBH_MSC_BOTH_DIR 2 + +//#define USBH_MSC_PAGE_LENGTH 0x40 +#define USBH_MSC_PAGE_LENGTH 512 + + +#define CBW_CB_LENGTH 16 +#define CBW_LENGTH 10 +#define CBW_LENGTH_TEST_UNIT_READY 6 + +#define USB_REQ_BOT_RESET 0xFF +#define USB_REQ_GET_MAX_LUN 0xFE + +#define MAX_BULK_STALL_COUNT_LIMIT 0x04 /* If STALL is seen on Bulk + Endpoint continously, 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 + * @{ + */ +extern USBH_BOTXfer_TypeDef USBH_MSC_BOTXferParam; +extern HostCBWPkt_TypeDef USBH_MSC_CBWData; +extern HostCSWPkt_TypeDef USBH_MSC_CSWData; +/** + * @} + */ + +/** @defgroup USBH_MSC_BOT_Exported_FunctionsPrototype + * @{ + */ +void USBH_MSC_HandleBOTXfer(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost); +uint8_t USBH_MSC_DecodeCSW(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost); +void USBH_MSC_Init(USB_OTG_CORE_HANDLE *pdev); +USBH_Status USBH_MSC_BOT_Abort(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t direction); +/** + * @} + */ + +#endif //__USBH_MSC_BOT_H__ + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + diff --git a/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/inc/usbh_msc_core.h b/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/inc/usbh_msc_core.h new file mode 100644 index 0000000..72ab4ce --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/inc/usbh_msc_core.h @@ -0,0 +1,141 @@ +/** + ****************************************************************************** + * @file usbh_msc_core.h + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief This file contains all the prototypes for the usbh_msc_core.c + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_MSC_CORE_H +#define __USBH_MSC_CORE_H + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_core.h" +#include "usbh_stdreq.h" +#include "usb_bsp.h" +#include "usbh_ioreq.h" +#include "usbh_hcs.h" +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bot.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_core.c + * @{ + */ + + +/** @defgroup USBH_MSC_CORE_Exported_Types + * @{ + */ + + +/* Structure for MSC process */ +typedef struct _MSC_Process +{ + uint8_t hc_num_in; + uint8_t hc_num_out; + uint8_t MSBulkOutEp; + uint8_t MSBulkInEp; + uint16_t MSBulkInEpSize; + uint16_t MSBulkOutEpSize; + uint8_t buff[USBH_MSC_MPS_SIZE]; + uint8_t maxLun; +} +MSC_Machine_TypeDef; + + +/** + * @} + */ + + + +/** @defgroup USBH_MSC_CORE_Exported_Defines + * @{ + */ + +#define USB_REQ_BOT_RESET 0xFF +#define USB_REQ_GET_MAX_LUN 0xFE + + +/** + * @} + */ + +/** @defgroup USBH_MSC_CORE_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_MSC_CORE_Exported_Variables + * @{ + */ +extern USBH_Class_cb_TypeDef USBH_MSC_cb; +extern MSC_Machine_TypeDef MSC_Machine; +extern uint8_t MSCErrorCount; + +/** + * @} + */ + +/** @defgroup USBH_MSC_CORE_Exported_FunctionsPrototype + * @{ + */ + + + +/** + * @} + */ + +#endif /* __USBH_MSC_CORE_H */ + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + + + diff --git a/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/inc/usbh_msc_scsi.h b/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/inc/usbh_msc_scsi.h new file mode 100644 index 0000000..3bdf4ec --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/inc/usbh_msc_scsi.h @@ -0,0 +1,163 @@ +/** + ****************************************************************************** + * @file usbh_msc_scsi.h + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief Header file for usbh_msc_scsi.c + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_MSC_SCSI_H__ +#define __USBH_MSC_SCSI_H__ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_stdreq.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 + * @{ + */ + + +/** @defgroup USBH_MSC_SCSI_Exported_Types + * @{ + */ +typedef enum { + USBH_MSC_OK = 0, + USBH_MSC_FAIL = 1, + USBH_MSC_PHASE_ERROR = 2, + USBH_MSC_BUSY = 3 +}USBH_MSC_Status_TypeDef; + +typedef enum { + CMD_UNINITIALIZED_STATE =0, + CMD_SEND_STATE, + CMD_WAIT_STATUS +} CMD_STATES_TypeDef; + + + +typedef struct __MassStorageParameter +{ + uint32_t MSCapacity; + uint32_t MSSenseKey; + uint16_t MSPageLength; + uint8_t MSBulkOutEp; + uint8_t MSBulkInEp; + uint8_t MSWriteProtect; +} MassStorageParameter_TypeDef; +/** + * @} + */ + + + +/** @defgroup USBH_MSC_SCSI_Exported_Defines + * @{ + */ + + + +#define OPCODE_TEST_UNIT_READY 0X00 +#define OPCODE_READ_CAPACITY10 0x25 +#define OPCODE_MODE_SENSE6 0x1A +#define OPCODE_READ10 0x28 +#define OPCODE_WRITE10 0x2A +#define OPCODE_REQUEST_SENSE 0x03 + +#define DESC_REQUEST_SENSE 0X00 +#define ALLOCATION_LENGTH_REQUEST_SENSE 63 +#define XFER_LEN_READ_CAPACITY10 8 +#define XFER_LEN_MODE_SENSE6 63 + +#define MASK_MODE_SENSE_WRITE_PROTECT 0x80 +#define MODE_SENSE_PAGE_CONTROL_FIELD 0x00 +#define MODE_SENSE_PAGE_CODE 0x3F +#define DISK_WRITE_PROTECTED 0x01 +/** + * @} + */ + +/** @defgroup USBH_MSC_SCSI_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup _Exported_Variables + * @{ + */ +extern MassStorageParameter_TypeDef USBH_MSC_Param; +/** + * @} + */ + +/** @defgroup USBH_MSC_SCSI_Exported_FunctionsPrototype + * @{ + */ +uint8_t USBH_MSC_TestUnitReady(USB_OTG_CORE_HANDLE *pdev); +uint8_t USBH_MSC_ReadCapacity10(USB_OTG_CORE_HANDLE *pdev); +uint8_t USBH_MSC_ModeSense6(USB_OTG_CORE_HANDLE *pdev); +uint8_t USBH_MSC_RequestSense(USB_OTG_CORE_HANDLE *pdev); +uint8_t USBH_MSC_Write10(USB_OTG_CORE_HANDLE *pdev, + uint8_t *, + uint32_t , + uint32_t ); +uint8_t USBH_MSC_Read10(USB_OTG_CORE_HANDLE *pdev, + uint8_t *, + uint32_t , + uint32_t ); +void USBH_MSC_StateMachine(USB_OTG_CORE_HANDLE *pdev); + +/** + * @} + */ + +#endif //__USBH_MSC_SCSI_H__ + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + diff --git a/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_bot.c b/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_bot.c new file mode 100644 index 0000000..eeb1075 --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_bot.c @@ -0,0 +1,613 @@ +/** + ****************************************************************************** + * @file usbh_msc_bot.c + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief This file includes the mass storage related functions + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bot.h" +#include "usbh_ioreq.h" +#include "usbh_def.h" +#include "usb_hcd_int.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 +* @{ +*/ + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN HostCBWPkt_TypeDef USBH_MSC_CBWData __ALIGN_END ; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN HostCSWPkt_TypeDef USBH_MSC_CSWData __ALIGN_END ; + + +static uint32_t BOTStallErrorCount; /* Keeps count of STALL Error Cases*/ + +/** +* @} +*/ + + +/** @defgroup USBH_MSC_BOT_Private_FunctionPrototypes +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_MSC_BOT_Exported_Variables +* @{ +*/ +USBH_BOTXfer_TypeDef USBH_MSC_BOTXferParam; +/** +* @} +*/ + + +/** @defgroup USBH_MSC_BOT_Private_Functions +* @{ +*/ + + +/** +* @brief USBH_MSC_Init +* Initializes the mass storage parameters +* @param None +* @retval None +*/ +void USBH_MSC_Init(USB_OTG_CORE_HANDLE *pdev ) +{ + if(HCD_IsDeviceConnected(pdev)) + { + USBH_MSC_CBWData.field.CBWSignature = USBH_MSC_BOT_CBW_SIGNATURE; + USBH_MSC_CBWData.field.CBWTag = USBH_MSC_BOT_CBW_TAG; + USBH_MSC_CBWData.field.CBWLUN = 0; /*Only one LUN is supported*/ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + } + + BOTStallErrorCount = 0; + MSCErrorCount = 0; +} + +/** +* @brief USBH_MSC_HandleBOTXfer +* This function manages the different states of BOT transfer and +* updates the status to upper layer. +* @param None +* @retval None +* +*/ +void USBH_MSC_HandleBOTXfer (USB_OTG_CORE_HANDLE *pdev ,USBH_HOST *phost) +{ + uint8_t xferDirection, index; + static uint32_t remainingDataLength; + static uint8_t *datapointer; + static uint8_t error_direction; + USBH_Status status; + + URB_STATE URB_Status = URB_IDLE; + + if(HCD_IsDeviceConnected(pdev)) + { + + switch (USBH_MSC_BOTXferParam.BOTState) + { + case USBH_MSC_SEND_CBW: + /* send CBW */ + USBH_BulkSendData (pdev, + &USBH_MSC_CBWData.CBWArray[0], + USBH_MSC_BOT_CBW_PACKET_LENGTH , + MSC_Machine.hc_num_out); + + USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_SEND_CBW; + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SENT_CBW; + + break; + + case USBH_MSC_SENT_CBW: + URB_Status = HCD_GetURB_State(pdev , MSC_Machine.hc_num_out); + + if(URB_Status == URB_DONE) + { + BOTStallErrorCount = 0; + USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_SENT_CBW; + + /* If the CBW Pkt is sent successful, then change the state */ + xferDirection = (USBH_MSC_CBWData.field.CBWFlags & USB_REQ_DIR_MASK); + + if ( USBH_MSC_CBWData.field.CBWTransferLength != 0 ) + { + remainingDataLength = USBH_MSC_CBWData.field.CBWTransferLength ; + datapointer = USBH_MSC_BOTXferParam.pRxTxBuff; + + /* If there is Data Transfer Stage */ + if (xferDirection == USB_D2H) + { + /* Data Direction is IN */ + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_DATAIN_STATE; + } + else + { + /* Data Direction is OUT */ + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_DATAOUT_STATE; + } + } + + else + {/* If there is NO Data Transfer Stage */ + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_RECEIVE_CSW_STATE; + } + + } + else if(URB_Status == URB_NOTREADY) + { + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp; + } + else if(URB_Status == URB_STALL) + { + error_direction = USBH_MSC_DIR_OUT; + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_OUT; + } + break; + + case USBH_MSC_BOT_DATAIN_STATE: + + URB_Status = HCD_GetURB_State(pdev , MSC_Machine.hc_num_in); + /* BOT DATA IN stage */ + if((URB_Status == URB_DONE) ||(USBH_MSC_BOTXferParam.BOTStateBkp != USBH_MSC_BOT_DATAIN_STATE)) + { + BOTStallErrorCount = 0; + USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_BOT_DATAIN_STATE; + + if(remainingDataLength > USBH_MSC_MPS_SIZE) + { + USBH_BulkReceiveData (pdev, + datapointer, + USBH_MSC_MPS_SIZE , + MSC_Machine.hc_num_in); + + remainingDataLength -= USBH_MSC_MPS_SIZE; + datapointer = datapointer + USBH_MSC_MPS_SIZE; + } + else if ( remainingDataLength == 0) + { + /* If value was 0, and successful transfer, then change the state */ + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_RECEIVE_CSW_STATE; + } + else + { + USBH_BulkReceiveData (pdev, + datapointer, + remainingDataLength , + MSC_Machine.hc_num_in); + + remainingDataLength = 0; /* Reset this value and keep in same state */ + } + } + else if(URB_Status == URB_STALL) + { + /* This is Data Stage STALL Condition */ + + error_direction = USBH_MSC_DIR_IN; + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_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. + + USBH_MSC_BOTXferParam.BOTStateBkp is used to switch to the Original + state after the ClearFeature Command is issued. + */ + USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE; + + } + break; + + + case USBH_MSC_BOT_DATAOUT_STATE: + /* BOT DATA OUT stage */ + URB_Status = HCD_GetURB_State(pdev , MSC_Machine.hc_num_out); + if(URB_Status == URB_DONE) + { + BOTStallErrorCount = 0; + USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_BOT_DATAOUT_STATE; + if(remainingDataLength > USBH_MSC_MPS_SIZE) + { + USBH_BulkSendData (pdev, + datapointer, + USBH_MSC_MPS_SIZE , + MSC_Machine.hc_num_out); + datapointer = datapointer + USBH_MSC_MPS_SIZE; + remainingDataLength = remainingDataLength - USBH_MSC_MPS_SIZE; + } + else if ( remainingDataLength == 0) + { + /* If value was 0, and successful transfer, then change the state */ + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_RECEIVE_CSW_STATE; + } + else + { + USBH_BulkSendData (pdev, + datapointer, + remainingDataLength , + MSC_Machine.hc_num_out); + + remainingDataLength = 0; /* Reset this value and keep in same state */ + } + } + + else if(URB_Status == URB_NOTREADY) + { + USBH_BulkSendData (pdev, + (datapointer - USBH_MSC_MPS_SIZE), + USBH_MSC_MPS_SIZE , + MSC_Machine.hc_num_out); + } + + else if(URB_Status == URB_STALL) + { + error_direction = USBH_MSC_DIR_OUT; + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_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. + + The Above statement will do the clear the Bulk-Out pipe. + The Below statement will help in Getting the CSW. + + USBH_MSC_BOTXferParam.BOTStateBkp is used to switch to the Original + state after the ClearFeature Command is issued. + */ + + USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE; + + } + break; + + case USBH_MSC_RECEIVE_CSW_STATE: + /* BOT CSW stage */ + /* NOTE: We cannot reset the BOTStallErrorCount here as it may come from + the clearFeature from previous command */ + + USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE; + + USBH_MSC_BOTXferParam.pRxTxBuff = USBH_MSC_CSWData.CSWArray; + USBH_MSC_BOTXferParam.DataLength = USBH_MSC_CSW_MAX_LENGTH; + + for(index = USBH_MSC_CSW_LENGTH; index != 0; index--) + { + USBH_MSC_CSWData.CSWArray[index] = 0; + } + + USBH_MSC_CSWData.CSWArray[0] = 0; + + USBH_BulkReceiveData (pdev, + USBH_MSC_BOTXferParam.pRxTxBuff, + USBH_MSC_CSW_MAX_LENGTH , + MSC_Machine.hc_num_in); + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_DECODE_CSW; + + break; + + case USBH_MSC_DECODE_CSW: + URB_Status = HCD_GetURB_State(pdev , MSC_Machine.hc_num_in); + /* Decode CSW */ + if(URB_Status == URB_DONE) + { + BOTStallErrorCount = 0; + USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE; + + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOTXferParam.MSCStateCurrent ; + + USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_DecodeCSW(pdev , phost); + } + else if(URB_Status == URB_STALL) + { + error_direction = USBH_MSC_DIR_IN; + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_IN; + } + break; + + case USBH_MSC_BOT_ERROR_IN: + status = USBH_MSC_BOT_Abort(pdev, phost, USBH_MSC_DIR_IN); + if (status == USBH_OK) + { + /* Check if the error was due in Both the directions */ + if (error_direction == USBH_MSC_BOTH_DIR) + {/* If Both directions are Needed, Switch to OUT Direction */ + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_OUT; + } + else + { + /* Switch Back to the Original State, In many cases this will be + USBH_MSC_RECEIVE_CSW_STATE state */ + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp; + } + } + else if (status == USBH_UNRECOVERED_ERROR) + { + /* This means that there is a STALL Error limit, Do Reset Recovery */ + USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_PHASE_ERROR; + } + break; + + case USBH_MSC_BOT_ERROR_OUT: + status = USBH_MSC_BOT_Abort(pdev, phost, USBH_MSC_DIR_OUT); + if ( status == USBH_OK) + { /* Switch Back to the Original State */ + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp; + } + else if (status == USBH_UNRECOVERED_ERROR) + { + /* This means that there is a STALL Error limit, Do Reset Recovery */ + USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_PHASE_ERROR; + } + break; + + default: + break; + } + } +} + +/** +* @brief USBH_MSC_BOT_Abort +* This function manages the different Error handling for STALL +* @param direction : IN / OUT +* @retval None +*/ +USBH_Status USBH_MSC_BOT_Abort(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t direction) +{ + USBH_Status status; + + status = USBH_BUSY; + + switch (direction) + { + case USBH_MSC_DIR_IN : + /* send ClrFeture on Bulk IN endpoint */ + status = USBH_ClrFeature(pdev, + phost, + MSC_Machine.MSBulkInEp, + MSC_Machine.hc_num_in); + + break; + + case USBH_MSC_DIR_OUT : + /*send ClrFeature on Bulk OUT endpoint */ + status = USBH_ClrFeature(pdev, + phost, + MSC_Machine.MSBulkOutEp, + MSC_Machine.hc_num_out); + break; + + default: + break; + } + + BOTStallErrorCount++; /* Check Continous Number of times, STALL has Occured */ + if (BOTStallErrorCount > MAX_BULK_STALL_COUNT_LIMIT ) + { + status = USBH_UNRECOVERED_ERROR; + } + + return status; +} + +/** +* @brief USBH_MSC_DecodeCSW +* This function decodes the CSW received by the device and updates the +* same to upper layer. +* @param None +* @retval On success USBH_MSC_OK, on failure USBH_MSC_FAIL +* @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. +*/ + +uint8_t USBH_MSC_DecodeCSW(USB_OTG_CORE_HANDLE *pdev , USBH_HOST *phost) +{ + uint8_t status; + uint32_t dataXferCount = 0; + status = USBH_MSC_FAIL; + + if(HCD_IsDeviceConnected(pdev)) + { + /*Checking if the transfer length is diffrent than 13*/ + dataXferCount = HCD_GetXferCnt(pdev, MSC_Machine.hc_num_in); + + if(dataXferCount != USBH_MSC_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 = USBH_MSC_PHASE_ERROR; + } + else + { /* CSW length is Correct */ + + /* Check validity of the CSW Signature and CSWStatus */ + if(USBH_MSC_CSWData.field.CSWSignature == USBH_MSC_BOT_CSW_SIGNATURE) + {/* Check Condition 1. dCSWSignature is equal to 53425355h */ + + if(USBH_MSC_CSWData.field.CSWTag == USBH_MSC_CBWData.field.CBWTag) + { + /* Check Condition 3. dCSWTag matches the dCBWTag from the + corresponding CBW */ + + if(USBH_MSC_CSWData.field.CSWStatus == USBH_MSC_OK) + { + /* 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 = USBH_MSC_OK; + } + else if(USBH_MSC_CSWData.field.CSWStatus == USBH_MSC_FAIL) + { + status = USBH_MSC_FAIL; + } + + else if(USBH_MSC_CSWData.field.CSWStatus == USBH_MSC_PHASE_ERROR) + { + /* 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 = USBH_MSC_PHASE_ERROR; + } + } /* 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 = USBH_MSC_PHASE_ERROR; + } + } /* CSW Length Check*/ + } + + USBH_MSC_BOTXferParam.BOTXferStatus = status; + return status; +} + + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + + + diff --git a/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_core.c b/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_core.c new file mode 100644 index 0000000..466399e --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_core.c @@ -0,0 +1,559 @@ +/** + ****************************************************************************** + * @file usbh_msc_core.c + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @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 + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+*/ + +/* Includes ------------------------------------------------------------------*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bot.h" +#include "usbh_core.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 + * @{ + */ +#define USBH_MSC_ERROR_RETRY_LIMIT 10 +/** + * @} + */ + +/** @defgroup USBH_MSC_CORE_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_MSC_CORE_Private_Variables + * @{ + */ +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN MSC_Machine_TypeDef MSC_Machine __ALIGN_END ; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN USB_Setup_TypeDef MSC_Setup __ALIGN_END ; +uint8_t MSCErrorCount = 0; + + +/** + * @} + */ + + +/** @defgroup USBH_MSC_CORE_Private_FunctionPrototypes + * @{ + */ + +static USBH_Status USBH_MSC_InterfaceInit (USB_OTG_CORE_HANDLE *pdev , + void *phost); + +static void USBH_MSC_InterfaceDeInit (USB_OTG_CORE_HANDLE *pdev , + void *phost); + +static USBH_Status USBH_MSC_Handle(USB_OTG_CORE_HANDLE *pdev , + void *phost); + +static USBH_Status USBH_MSC_ClassRequest(USB_OTG_CORE_HANDLE *pdev , + void *phost); + +static USBH_Status USBH_MSC_BOTReset(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost); +static USBH_Status USBH_MSC_GETMaxLUN(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost); + + +USBH_Class_cb_TypeDef USBH_MSC_cb = +{ + USBH_MSC_InterfaceInit, + USBH_MSC_InterfaceDeInit, + USBH_MSC_ClassRequest, + USBH_MSC_Handle, +}; + +void USBH_MSC_ErrorHandle(uint8_t status); + +/** + * @} + */ + + +/** @defgroup USBH_MSC_CORE_Exported_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBH_MSC_CORE_Private_Functions + * @{ + */ + + +/** + * @brief USBH_MSC_InterfaceInit + * Interface initialization for MSC class. + * @param pdev: Selected device + * @param hdev: Selected device property + * @retval USBH_Status : Status of class request handled. + */ +static USBH_Status USBH_MSC_InterfaceInit ( USB_OTG_CORE_HANDLE *pdev, + void *phost) +{ + USBH_HOST *pphost = phost; + + if((pphost->device_prop.Itf_Desc[0].bInterfaceClass == MSC_CLASS) && \ + (pphost->device_prop.Itf_Desc[0].bInterfaceProtocol == MSC_PROTOCOL)) + { + if(pphost->device_prop.Ep_Desc[0][0].bEndpointAddress & 0x80) + { + MSC_Machine.MSBulkInEp = (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress); + MSC_Machine.MSBulkInEpSize = pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize; + } + else + { + MSC_Machine.MSBulkOutEp = (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress); + MSC_Machine.MSBulkOutEpSize = pphost->device_prop.Ep_Desc[0] [0].wMaxPacketSize; + } + + if(pphost->device_prop.Ep_Desc[0][1].bEndpointAddress & 0x80) + { + MSC_Machine.MSBulkInEp = (pphost->device_prop.Ep_Desc[0][1].bEndpointAddress); + MSC_Machine.MSBulkInEpSize = pphost->device_prop.Ep_Desc[0][1].wMaxPacketSize; + } + else + { + MSC_Machine.MSBulkOutEp = (pphost->device_prop.Ep_Desc[0][1].bEndpointAddress); + MSC_Machine.MSBulkOutEpSize = pphost->device_prop.Ep_Desc[0][1].wMaxPacketSize; + } + + MSC_Machine.hc_num_out = USBH_Alloc_Channel(pdev, + MSC_Machine.MSBulkOutEp); + MSC_Machine.hc_num_in = USBH_Alloc_Channel(pdev, + MSC_Machine.MSBulkInEp); + + /* Open the new channels */ + USBH_Open_Channel (pdev, + MSC_Machine.hc_num_out, + pphost->device_prop.address, + pphost->device_prop.speed, + EP_TYPE_BULK, + MSC_Machine.MSBulkOutEpSize); + + USBH_Open_Channel (pdev, + MSC_Machine.hc_num_in, + pphost->device_prop.address, + pphost->device_prop.speed, + EP_TYPE_BULK, + MSC_Machine.MSBulkInEpSize); + + } + + else + { + pphost->usr_cb->USBH_USR_DeviceNotSupported(); + } + + return USBH_OK ; + +} + + +/** + * @brief USBH_MSC_InterfaceDeInit + * De-Initialize interface by freeing host channels allocated to interface + * @param pdev: Selected device + * @param hdev: Selected device property + * @retval None + */ +void USBH_MSC_InterfaceDeInit ( USB_OTG_CORE_HANDLE *pdev, + void *phost) +{ + if ( MSC_Machine.hc_num_out) + { + USB_OTG_HC_Halt(pdev, MSC_Machine.hc_num_out); + USBH_Free_Channel (pdev, MSC_Machine.hc_num_out); + MSC_Machine.hc_num_out = 0; /* Reset the Channel as Free */ + } + + if ( MSC_Machine.hc_num_in) + { + USB_OTG_HC_Halt(pdev, MSC_Machine.hc_num_in); + USBH_Free_Channel (pdev, MSC_Machine.hc_num_in); + MSC_Machine.hc_num_in = 0; /* Reset the Channel as Free */ + } +} + +/** + * @brief USBH_MSC_ClassRequest + * This function will only initialize the MSC state machine + * @param pdev: Selected device + * @param hdev: Selected device property + * @retval USBH_Status : Status of class request handled. + */ + +static USBH_Status USBH_MSC_ClassRequest(USB_OTG_CORE_HANDLE *pdev , + void *phost) +{ + + USBH_Status status = USBH_OK ; + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_INIT_STATE; + + return status; +} + + +/** + * @brief USBH_MSC_Handle + * MSC state machine handler + * @param pdev: Selected device + * @param hdev: Selected device property + * @retval USBH_Status + */ + +static USBH_Status USBH_MSC_Handle(USB_OTG_CORE_HANDLE *pdev , + void *phost) +{ + USBH_HOST *pphost = phost; + + USBH_Status status = USBH_BUSY; + uint8_t mscStatus = USBH_MSC_BUSY; + uint8_t appliStatus = 0; + + static uint8_t maxLunExceed = FALSE; + + + if(HCD_IsDeviceConnected(pdev)) + { + switch(USBH_MSC_BOTXferParam.MSCState) + { + case USBH_MSC_BOT_INIT_STATE: + USBH_MSC_Init(pdev); + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_RESET; + break; + + case USBH_MSC_BOT_RESET: + /* Issue BOT RESET request */ + status = USBH_MSC_BOTReset(pdev, phost); + if(status == USBH_OK ) + { + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_GET_MAX_LUN; + } + + if(status == USBH_NOT_SUPPORTED ) + { + /* If the Command has failed, then we need to move to Next State, after + STALL condition is cleared by Control-Transfer */ + USBH_MSC_BOTXferParam.MSCStateBkp = USBH_MSC_GET_MAX_LUN; + + /* a Clear Feature should be issued here */ + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_CTRL_ERROR_STATE; + } + break; + + case USBH_MSC_GET_MAX_LUN: + /* Issue GetMaxLUN request */ + status = USBH_MSC_GETMaxLUN(pdev, phost); + + if(status == USBH_OK ) + { + MSC_Machine.maxLun = *(MSC_Machine.buff) ; + + /* If device has more that one logical unit then it is not supported */ + if((MSC_Machine.maxLun > 0) && (maxLunExceed == FALSE)) + { + maxLunExceed = TRUE; + pphost->usr_cb->USBH_USR_DeviceNotSupported(); + + break; + } + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_TEST_UNIT_READY; + } + + if(status == USBH_NOT_SUPPORTED ) + { + /* If the Command has failed, then we need to move to Next State, after + STALL condition is cleared by Control-Transfer */ + USBH_MSC_BOTXferParam.MSCStateBkp = USBH_MSC_TEST_UNIT_READY; + + /* a Clear Feature should be issued here */ + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_CTRL_ERROR_STATE; + } + break; + + case USBH_MSC_CTRL_ERROR_STATE: + /* Issue Clearfeature request */ + status = USBH_ClrFeature(pdev, + phost, + 0x00, + pphost->Control.hc_num_out); + if(status == USBH_OK ) + { + /* If GetMaxLun Request not support, assume Single LUN configuration */ + MSC_Machine.maxLun = 0; + + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOTXferParam.MSCStateBkp; + } + break; + + case USBH_MSC_TEST_UNIT_READY: + /* Issue SCSI command TestUnitReady */ + mscStatus = USBH_MSC_TestUnitReady(pdev); + + if(mscStatus == USBH_MSC_OK ) + { + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_READ_CAPACITY10; + MSCErrorCount = 0; + status = USBH_OK; + } + else + { + USBH_MSC_ErrorHandle(mscStatus); + } + break; + + case USBH_MSC_READ_CAPACITY10: + /* Issue READ_CAPACITY10 SCSI command */ + mscStatus = USBH_MSC_ReadCapacity10(pdev); + if(mscStatus == USBH_MSC_OK ) + { + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_MODE_SENSE6; + MSCErrorCount = 0; + status = USBH_OK; + } + else + { + USBH_MSC_ErrorHandle(mscStatus); + } + break; + + case USBH_MSC_MODE_SENSE6: + /* Issue ModeSense6 SCSI command for detecting if device is write-protected */ + mscStatus = USBH_MSC_ModeSense6(pdev); + if(mscStatus == USBH_MSC_OK ) + { + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_DEFAULT_APPLI_STATE; + MSCErrorCount = 0; + status = USBH_OK; + } + else + { + USBH_MSC_ErrorHandle(mscStatus); + } + break; + + case USBH_MSC_REQUEST_SENSE: + /* Issue RequestSense SCSI command for retreiving error code */ + mscStatus = USBH_MSC_RequestSense(pdev); + if(mscStatus == USBH_MSC_OK ) + { + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOTXferParam.MSCStateBkp; + status = USBH_OK; + } + else + { + USBH_MSC_ErrorHandle(mscStatus); + } + break; + + case USBH_MSC_BOT_USB_TRANSFERS: + /* Process the BOT state machine */ + USBH_MSC_HandleBOTXfer(pdev , phost); + break; + + case USBH_MSC_DEFAULT_APPLI_STATE: + /* Process Application callback for MSC */ + appliStatus = pphost->usr_cb->USBH_USR_MSC_Application(); + if(appliStatus == 0) + { + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_DEFAULT_APPLI_STATE; + } + else if (appliStatus == 1) + { + /* De-init requested from application layer */ + status = USBH_APPLY_DEINIT; + } + break; + + case USBH_MSC_UNRECOVERED_STATE: + + status = USBH_UNRECOVERED_ERROR; + + break; + + default: + break; + + } + } + return status; +} + + + +/** + * @brief USBH_MSC_BOTReset + * This request is used to reset the mass storage device and its + * associated interface. This class-specific request shall ready the + * device for the next CBW from the host. + * @param pdev: Selected device + * @retval USBH_Status : Status of class request handled. + */ +static USBH_Status USBH_MSC_BOTReset(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *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 = 0; + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = 0; + + return USBH_CtlReq(pdev, phost, 0 , 0 ); +} + + +/** + * @brief USBH_MSC_GETMaxLUN + * This request is used to reset the mass storage device and its + * associated interface. This class-specific request shall ready the + * device for the next CBW from the host. + * @param pdev: Selected device + * @retval USBH_Status : USB ctl xfer status + */ +static USBH_Status USBH_MSC_GETMaxLUN(USB_OTG_CORE_HANDLE *pdev , USBH_HOST *phost) +{ + 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 = 0; + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = 1; + + return USBH_CtlReq(pdev, phost, MSC_Machine.buff , 1 ); +} + +/** + * @brief USBH_MSC_ErrorHandle + * The function is for handling errors occuring during the MSC + * state machine + * @param status + * @retval None + */ + +void USBH_MSC_ErrorHandle(uint8_t status) +{ + if(status == USBH_MSC_FAIL) + { + MSCErrorCount++; + if(MSCErrorCount < USBH_MSC_ERROR_RETRY_LIMIT) + { /* Try MSC level error recovery, Issue the request Sense to get + Drive error reason */ + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_REQUEST_SENSE; + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + } + else + { + /* Error trials exceeded the limit, go to unrecovered state */ + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_UNRECOVERED_STATE; + } + } + else if(status == USBH_MSC_PHASE_ERROR) + { + /* Phase error, Go to Unrecoovered state */ + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_UNRECOVERED_STATE; + } + else if(status == USBH_MSC_BUSY) + { + /*No change in state*/ + } +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_fatfs.c b/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_fatfs.c new file mode 100644 index 0000000..57a3c9c --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_fatfs.c @@ -0,0 +1,186 @@ + +#include "usb_conf.h" +#include "diskio.h" +#include "usbh_msc_core.h" +/*-------------------------------------------------------------------------- + +Module Private Functions and Variables + +---------------------------------------------------------------------------*/ + +static volatile DSTATUS Stat = STA_NOINIT; /* Disk status */ + +extern USB_OTG_CORE_HANDLE USB_OTG_Core; +extern USBH_HOST USB_Host; + +/*-----------------------------------------------------------------------*/ +/* Initialize Disk Drive */ +/*-----------------------------------------------------------------------*/ + +DSTATUS disk_initialize ( + BYTE drv /* Physical drive number (0) */ + ) +{ + + if(HCD_IsDeviceConnected(&USB_OTG_Core)) + { + Stat &= ~STA_NOINIT; + } + + return Stat; + + +} + + + +/*-----------------------------------------------------------------------*/ +/* Get Disk Status */ +/*-----------------------------------------------------------------------*/ + +DSTATUS disk_status ( + BYTE drv /* Physical drive number (0) */ + ) +{ + if (drv) return STA_NOINIT; /* Supports only single drive */ + return Stat; +} + + + +/*-----------------------------------------------------------------------*/ +/* Read Sector(s) */ +/*-----------------------------------------------------------------------*/ + +DRESULT disk_read ( + BYTE drv, /* Physical drive number (0) */ + BYTE *buff, /* Pointer to the data buffer to store read data */ + DWORD sector, /* Start sector number (LBA) */ + BYTE count /* Sector count (1..255) */ + ) +{ + BYTE status = USBH_MSC_OK; + + if (drv || !count) return RES_PARERR; + if (Stat & STA_NOINIT) return RES_NOTRDY; + + + if(HCD_IsDeviceConnected(&USB_OTG_Core)) + { + + do + { + status = USBH_MSC_Read10(&USB_OTG_Core, buff,sector,512); + USBH_MSC_HandleBOTXfer(&USB_OTG_Core ,&USB_Host); + + if(!HCD_IsDeviceConnected(&USB_OTG_Core)) + { + return RES_ERROR; + } + } + while(status == USBH_MSC_BUSY ); + } + + if(status == USBH_MSC_OK) + return RES_OK; + return RES_ERROR; + +} + + + +/*-----------------------------------------------------------------------*/ +/* Write Sector(s) */ +/*-----------------------------------------------------------------------*/ + +#if _READONLY == 0 +DRESULT disk_write ( + BYTE drv, /* Physical drive number (0) */ + const BYTE *buff, /* Pointer to the data to be written */ + DWORD sector, /* Start sector number (LBA) */ + BYTE count /* Sector count (1..255) */ + ) +{ + BYTE status = USBH_MSC_OK; + if (drv || !count) return RES_PARERR; + if (Stat & STA_NOINIT) return RES_NOTRDY; + if (Stat & STA_PROTECT) return RES_WRPRT; + + + if(HCD_IsDeviceConnected(&USB_OTG_Core)) + { + do + { + status = USBH_MSC_Write10(&USB_OTG_Core,(BYTE*)buff,sector,512); + USBH_MSC_HandleBOTXfer(&USB_OTG_Core, &USB_Host); + + if(!HCD_IsDeviceConnected(&USB_OTG_Core)) + { + return RES_ERROR; + } + } + + while(status == USBH_MSC_BUSY ); + + } + + if(status == USBH_MSC_OK) + return RES_OK; + return RES_ERROR; +} +#endif /* _READONLY == 0 */ + + + +/*-----------------------------------------------------------------------*/ +/* Miscellaneous Functions */ +/*-----------------------------------------------------------------------*/ + +#if _USE_IOCTL != 0 +DRESULT disk_ioctl ( + BYTE drv, /* Physical drive number (0) */ + BYTE ctrl, /* Control code */ + void *buff /* Buffer to send/receive control data */ + ) +{ + DRESULT res = RES_OK; + + if (drv) return RES_PARERR; + + res = RES_ERROR; + + if (Stat & STA_NOINIT) return RES_NOTRDY; + + switch (ctrl) { + case CTRL_SYNC : /* Make sure that no pending write process */ + + res = RES_OK; + break; + + case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */ + + *(DWORD*)buff = (DWORD) USBH_MSC_Param.MSCapacity; + res = RES_OK; + break; + + case GET_SECTOR_SIZE : /* Get R/W sector size (WORD) */ + *(WORD*)buff = 512; + res = RES_OK; + break; + + case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */ + + *(DWORD*)buff = 512; + + break; + + + default: + res = RES_PARERR; + } + + + + return res; +} +#endif /* _USE_IOCTL != 0 */ diff --git a/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_scsi.c b/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_scsi.c new file mode 100644 index 0000000..f6bb7c4 --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_scsi.c @@ -0,0 +1,674 @@ +/** + ****************************************************************************** + * @file usbh_msc_scsi.c + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief This file implements the SCSI commands + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bot.h" +#include "usbh_ioreq.h" +#include "usbh_def.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 + * @{ + */ + +MassStorageParameter_TypeDef USBH_MSC_Param; +/** + * @} + */ + +/** @defgroup USBH_MSC_SCSI_Private_Defines + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_MSC_SCSI_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_MSC_SCSI_Private_Variables + * @{ + */ + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN uint8_t USBH_DataInBuffer[512] __ALIGN_END ; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN uint8_t USBH_DataOutBuffer[512] __ALIGN_END ; +/** + * @} + */ + + +/** @defgroup USBH_MSC_SCSI_Private_FunctionPrototypes + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_MSC_SCSI_Exported_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBH_MSC_SCSI_Private_Functions + * @{ + */ + + + + +/** + * @brief USBH_MSC_TestUnitReady + * Issues 'Test unit ready' command to the device. Once the response + * received, it updates the status to upper layer. + * @param None + * @retval Status + */ +uint8_t USBH_MSC_TestUnitReady (USB_OTG_CORE_HANDLE *pdev) +{ + uint8_t index; + USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY; + + if(HCD_IsDeviceConnected(pdev)) + { + switch(USBH_MSC_BOTXferParam.CmdStateMachine) + { + case CMD_SEND_STATE: + /*Prepare the CBW and relevent field*/ + USBH_MSC_CBWData.field.CBWTransferLength = 0; /* No Data Transfer */ + USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_OUT; + USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH_TEST_UNIT_READY; + USBH_MSC_BOTXferParam.pRxTxBuff = USBH_MSC_CSWData.CSWArray; + USBH_MSC_BOTXferParam.DataLength = USBH_MSC_CSW_MAX_LENGTH; + USBH_MSC_BOTXferParam.MSCStateCurrent = USBH_MSC_TEST_UNIT_READY; + + for(index = CBW_CB_LENGTH; index != 0; index--) + { + USBH_MSC_CBWData.field.CBWCB[index] = 0x00; + } + + USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_TEST_UNIT_READY; + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW; + /* Start the transfer, then let the state + machine magage the other transactions */ + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS; + USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY; + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS; + + status = USBH_MSC_BUSY; + break; + + case CMD_WAIT_STATUS: + if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK) + { + /* Commands successfully sent and Response Received */ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + + status = USBH_MSC_OK; + } + else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL ) + { + /* Failure Mode */ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + status = USBH_MSC_FAIL; + } + + else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR ) + { + /* Failure Mode */ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + status = USBH_MSC_PHASE_ERROR; + } + break; + + default: + break; + } + } + return status; +} + + +/** + * @brief USBH_MSC_ReadCapacity10 + * Issue the read capacity command to the device. Once the response + * received, it updates the status to upper layer + * @param None + * @retval Status + */ +uint8_t USBH_MSC_ReadCapacity10(USB_OTG_CORE_HANDLE *pdev) +{ + uint8_t index; + USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY; + + if(HCD_IsDeviceConnected(pdev)) + { + switch(USBH_MSC_BOTXferParam.CmdStateMachine) + { + case CMD_SEND_STATE: + /*Prepare the CBW and relevent field*/ + USBH_MSC_CBWData.field.CBWTransferLength = XFER_LEN_READ_CAPACITY10; + USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN; + USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH; + + USBH_MSC_BOTXferParam.pRxTxBuff = USBH_DataInBuffer; + USBH_MSC_BOTXferParam.MSCStateCurrent = USBH_MSC_READ_CAPACITY10; + + for(index = CBW_CB_LENGTH; index != 0; index--) + { + USBH_MSC_CBWData.field.CBWCB[index] = 0x00; + } + + USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_READ_CAPACITY10; + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW; + + /* Start the transfer, then let the state machine manage the other + transactions */ + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS; + USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY; + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS; + + status = USBH_MSC_BUSY; + break; + + case CMD_WAIT_STATUS: + if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK) + { + /*assign the capacity*/ + (((uint8_t*)&USBH_MSC_Param.MSCapacity )[3]) = USBH_DataInBuffer[0]; + (((uint8_t*)&USBH_MSC_Param.MSCapacity )[2]) = USBH_DataInBuffer[1]; + (((uint8_t*)&USBH_MSC_Param.MSCapacity )[1]) = USBH_DataInBuffer[2]; + (((uint8_t*)&USBH_MSC_Param.MSCapacity )[0]) = USBH_DataInBuffer[3]; + + /*assign the page length*/ + (((uint8_t*)&USBH_MSC_Param.MSPageLength )[1]) = USBH_DataInBuffer[6]; + (((uint8_t*)&USBH_MSC_Param.MSPageLength )[0]) = USBH_DataInBuffer[7]; + + /* Commands successfully sent and Response Received */ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + status = USBH_MSC_OK; + } + else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL ) + { + /* Failure Mode */ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + status = USBH_MSC_FAIL; + } + else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR ) + { + /* Failure Mode */ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + status = USBH_MSC_PHASE_ERROR; + } + else + { + /* Wait for the Commands to get Completed */ + /* NO Change in state Machine */ + } + break; + + default: + break; + } + } + return status; +} + + +/** + * @brief USBH_MSC_ModeSense6 + * Issue the Mode Sense6 Command to the device. This function is used + * for reading the WriteProtect Status of the Mass-Storage device. + * @param None + * @retval Status + */ +uint8_t USBH_MSC_ModeSense6(USB_OTG_CORE_HANDLE *pdev) +{ + uint8_t index; + USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY; + + if(HCD_IsDeviceConnected(pdev)) + { + switch(USBH_MSC_BOTXferParam.CmdStateMachine) + { + case CMD_SEND_STATE: + /*Prepare the CBW and relevent field*/ + USBH_MSC_CBWData.field.CBWTransferLength = XFER_LEN_MODE_SENSE6; + USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN; + USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH; + + USBH_MSC_BOTXferParam.pRxTxBuff = USBH_DataInBuffer; + USBH_MSC_BOTXferParam.MSCStateCurrent = USBH_MSC_MODE_SENSE6; + + for(index = CBW_CB_LENGTH; index != 0; index--) + { + USBH_MSC_CBWData.field.CBWCB[index] = 0x00; + } + + USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_MODE_SENSE6; + USBH_MSC_CBWData.field.CBWCB[2] = MODE_SENSE_PAGE_CONTROL_FIELD | \ + MODE_SENSE_PAGE_CODE; + + USBH_MSC_CBWData.field.CBWCB[4] = XFER_LEN_MODE_SENSE6; + + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW; + + /* Start the transfer, then let the state machine manage the other + transactions */ + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS; + USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY; + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS; + + status = USBH_MSC_BUSY; + break; + + case CMD_WAIT_STATUS: + if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK) + { + /* Assign the Write Protect status */ + /* If WriteProtect = 0, Writing is allowed + If WriteProtect != 0, Disk is Write Protected */ + if ( USBH_DataInBuffer[2] & MASK_MODE_SENSE_WRITE_PROTECT) + { + USBH_MSC_Param.MSWriteProtect = DISK_WRITE_PROTECTED; + } + else + { + USBH_MSC_Param.MSWriteProtect = 0; + } + + /* Commands successfully sent and Response Received */ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + status = USBH_MSC_OK; + } + else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL ) + { + /* Failure Mode */ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + status = USBH_MSC_FAIL; + } + else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR ) + { + /* Failure Mode */ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + status = USBH_MSC_PHASE_ERROR; + } + else + { + /* Wait for the Commands to get Completed */ + /* NO Change in state Machine */ + } + break; + + default: + break; + } + } + return status; +} + +/** + * @brief USBH_MSC_RequestSense + * Issues the Request Sense command to the device. Once the response + * received, it updates the status to upper layer + * @param None + * @retval Status + */ +uint8_t USBH_MSC_RequestSense(USB_OTG_CORE_HANDLE *pdev) +{ + USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY; + + uint8_t index; + + + if(HCD_IsDeviceConnected(pdev)) + { + switch(USBH_MSC_BOTXferParam.CmdStateMachine) + { + case CMD_SEND_STATE: + + /*Prepare the CBW and relevent field*/ + USBH_MSC_CBWData.field.CBWTransferLength = \ + ALLOCATION_LENGTH_REQUEST_SENSE; + USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN; + USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH; + + USBH_MSC_BOTXferParam.pRxTxBuff = USBH_DataInBuffer; + USBH_MSC_BOTXferParam.MSCStateBkp = USBH_MSC_BOTXferParam.MSCStateCurrent; + USBH_MSC_BOTXferParam.MSCStateCurrent = USBH_MSC_REQUEST_SENSE; + + + for(index = CBW_CB_LENGTH; index != 0; index--) + { + USBH_MSC_CBWData.field.CBWCB[index] = 0x00; + } + + USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_REQUEST_SENSE; + USBH_MSC_CBWData.field.CBWCB[1] = DESC_REQUEST_SENSE; + USBH_MSC_CBWData.field.CBWCB[4] = ALLOCATION_LENGTH_REQUEST_SENSE; + + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW; + /* Start the transfer, then let the state machine magage + the other transactions */ + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS; + USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY; + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS; + + status = USBH_MSC_BUSY; + + break; + + case CMD_WAIT_STATUS: + + if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK) + { + /* Get Sense data*/ + (((uint8_t*)&USBH_MSC_Param.MSSenseKey )[3]) = USBH_DataInBuffer[0]; + (((uint8_t*)&USBH_MSC_Param.MSSenseKey )[2]) = USBH_DataInBuffer[1]; + (((uint8_t*)&USBH_MSC_Param.MSSenseKey )[1]) = USBH_DataInBuffer[2]; + (((uint8_t*)&USBH_MSC_Param.MSSenseKey )[0]) = USBH_DataInBuffer[3]; + + /* Commands successfully sent and Response Received */ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + status = USBH_MSC_OK; + } + else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL ) + { + /* Failure Mode */ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + status = USBH_MSC_FAIL; + } + + else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR ) + { + /* Failure Mode */ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + status = USBH_MSC_PHASE_ERROR; + } + + else + { + /* Wait for the Commands to get Completed */ + /* NO Change in state Machine */ + } + break; + + default: + break; + } + } + return status; +} + + +/** + * @brief USBH_MSC_Write10 + * Issue the write command to the device. Once the response received, + * it updates the status to upper layer + * @param dataBuffer : DataBuffer contains the data to write + * @param address : Address to which the data will be written + * @param nbOfbytes : NbOfbytes to be written + * @retval Status + */ +uint8_t USBH_MSC_Write10(USB_OTG_CORE_HANDLE *pdev, + uint8_t *dataBuffer, + uint32_t address, + uint32_t nbOfbytes) +{ + uint8_t index; + USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY; + uint16_t nbOfPages; + + if(HCD_IsDeviceConnected(pdev)) + { + switch(USBH_MSC_BOTXferParam.CmdStateMachine) + { + case CMD_SEND_STATE: + USBH_MSC_CBWData.field.CBWTransferLength = nbOfbytes; + USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_OUT; + USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH; + USBH_MSC_BOTXferParam.pRxTxBuff = dataBuffer; + + + for(index = CBW_CB_LENGTH; index != 0; index--) + { + USBH_MSC_CBWData.field.CBWCB[index] = 0x00; + } + + USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_WRITE10; + + /*logical block address*/ + USBH_MSC_CBWData.field.CBWCB[2] = (((uint8_t*)&address)[3]) ; + USBH_MSC_CBWData.field.CBWCB[3] = (((uint8_t*)&address)[2]); + USBH_MSC_CBWData.field.CBWCB[4] = (((uint8_t*)&address)[1]); + USBH_MSC_CBWData.field.CBWCB[5] = (((uint8_t*)&address)[0]); + + /*USBH_MSC_PAGE_LENGTH = 512*/ + nbOfPages = nbOfbytes/ USBH_MSC_PAGE_LENGTH; + + /*Tranfer length */ + USBH_MSC_CBWData.field.CBWCB[7] = (((uint8_t *)&nbOfPages)[1]) ; + USBH_MSC_CBWData.field.CBWCB[8] = (((uint8_t *)&nbOfPages)[0]) ; + + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW; + /* Start the transfer, then let the state machine + magage the other transactions */ + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS; + USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY; + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS; + + status = USBH_MSC_BUSY; + + break; + + case CMD_WAIT_STATUS: + if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK) + { + /* Commands successfully sent and Response Received */ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + status = USBH_MSC_OK; + } + else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL ) + { + /* Failure Mode */ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + } + + else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR ) + { + /* Failure Mode */ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + status = USBH_MSC_PHASE_ERROR; + } + break; + + default: + break; + } + } + return status; +} + +/** + * @brief USBH_MSC_Read10 + * Issue the read command to the device. Once the response received, + * it updates the status to upper layer + * @param dataBuffer : DataBuffer will contain the data to be read + * @param address : Address from which the data will be read + * @param nbOfbytes : NbOfbytes to be read + * @retval Status + */ +uint8_t USBH_MSC_Read10(USB_OTG_CORE_HANDLE *pdev, + uint8_t *dataBuffer, + uint32_t address, + uint32_t nbOfbytes) +{ + uint8_t index; + static USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY; + uint16_t nbOfPages; + status = USBH_MSC_BUSY; + + if(HCD_IsDeviceConnected(pdev)) + { + switch(USBH_MSC_BOTXferParam.CmdStateMachine) + { + case CMD_SEND_STATE: + /*Prepare the CBW and relevent field*/ + USBH_MSC_CBWData.field.CBWTransferLength = nbOfbytes; + USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN; + USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH; + + USBH_MSC_BOTXferParam.pRxTxBuff = dataBuffer; + + for(index = CBW_CB_LENGTH; index != 0; index--) + { + USBH_MSC_CBWData.field.CBWCB[index] = 0x00; + } + + USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_READ10; + + /*logical block address*/ + + USBH_MSC_CBWData.field.CBWCB[2] = (((uint8_t*)&address)[3]); + USBH_MSC_CBWData.field.CBWCB[3] = (((uint8_t*)&address)[2]); + USBH_MSC_CBWData.field.CBWCB[4] = (((uint8_t*)&address)[1]); + USBH_MSC_CBWData.field.CBWCB[5] = (((uint8_t*)&address)[0]); + + /*USBH_MSC_PAGE_LENGTH = 512*/ + nbOfPages = nbOfbytes/ USBH_MSC_PAGE_LENGTH; + + /*Tranfer length */ + USBH_MSC_CBWData.field.CBWCB[7] = (((uint8_t *)&nbOfPages)[1]) ; + USBH_MSC_CBWData.field.CBWCB[8] = (((uint8_t *)&nbOfPages)[0]) ; + + + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW; + /* Start the transfer, then let the state machine + magage the other transactions */ + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS; + USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY; + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS; + + status = USBH_MSC_BUSY; + + break; + + case CMD_WAIT_STATUS: + + if((USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK) && \ + (HCD_IsDeviceConnected(pdev))) + { + /* Commands successfully sent and Response Received */ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + status = USBH_MSC_OK; + } + else if (( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL ) && \ + (HCD_IsDeviceConnected(pdev))) + { + /* Failure Mode */ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + } + + else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR ) + { + /* Failure Mode */ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + status = USBH_MSC_PHASE_ERROR; + } + else + { + /* Wait for the Commands to get Completed */ + /* NO Change in state Machine */ + } + break; + + default: + break; + } + } + return status; +} + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + + + diff --git a/example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_conf_template.h b/example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_conf_template.h new file mode 100644 index 0000000..7e41bf8 --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_conf_template.h @@ -0,0 +1,94 @@ +/** + ****************************************************************************** + * @file usbh_conf_template + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief General USB Host library configuration + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBH_CONF__H__ +#define __USBH_CONF__H__ + +/* Includes ------------------------------------------------------------------*/ +/** @addtogroup USBH_OTG_DRIVER + * @{ + */ + +/** @defgroup USBH_CONF + * @brief usb otg low level driver configuration file + * @{ + */ + +/** @defgroup USBH_CONF_Exported_Defines + * @{ + */ + +#define USBH_MAX_NUM_ENDPOINTS 2 +#define USBH_MAX_NUM_INTERFACES 2 +#ifdef USE_USB_OTG_FS +#define USBH_MSC_MPS_SIZE 0x40 +#else +#define USBH_MSC_MPS_SIZE 0x200 +#endif + +/** + * @} + */ + + +/** @defgroup USBH_CONF_Exported_Types + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_CONF_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_CONF_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_CONF_Exported_FunctionsPrototype + * @{ + */ +/** + * @} + */ + + +#endif //__USBH_CONF__H__ + + +/** + * @} + */ + +/** + * @} + */ +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + diff --git a/example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_core.h b/example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_core.h new file mode 100644 index 0000000..3a8de2c --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_core.h @@ -0,0 +1,289 @@ +/** + ****************************************************************************** + * @file usbh_core.h + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief Header file for usbh_core.c + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_CORE_H +#define __USBH_CORE_H + +/* Includes ------------------------------------------------------------------*/ +#include "usb_hcd.h" +#include "usbh_def.h" +#include "usbh_conf.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 MSC_CLASS 0x08 +#define HID_CLASS 0x03 +#define MSC_PROTOCOL 0x50 +#define CBI_PROTOCOL 0x01 + + +#define USBH_MAX_ERROR_COUNT 2 +#define USBH_DEVICE_ADDRESS_DEFAULT 0 +#define USBH_DEVICE_ADDRESS 1 + + +/** + * @} + */ + + +/** @defgroup USBH_CORE_Exported_Types + * @{ + */ + +typedef enum { + USBH_OK = 0, + USBH_BUSY, + USBH_FAIL, + USBH_NOT_SUPPORTED, + USBH_UNRECOVERED_ERROR, + USBH_ERROR_SPEED_UNKNOWN, + USBH_APPLY_DEINIT +}USBH_Status; + +/* Following states are used for gState */ +typedef enum { + HOST_IDLE =0, + HOST_ISSUE_CORE_RESET, + HOST_DEV_ATTACHED, + HOST_DEV_DISCONNECTED, + HOST_ISSUE_RESET, + HOST_DETECT_DEVICE_SPEED, + HOST_ENUMERATION, + HOST_CLASS_REQUEST, + HOST_CLASS, + HOST_CTRL_XFER, + HOST_USR_INPUT, + HOST_SUSPENDED, + HOST_ERROR_STATE +}HOST_State; + +/* Following states are used for EnumerationState */ +typedef enum { + ENUM_IDLE = 0, + 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_SET_CONFIGURATION, + ENUM_DEV_CONFIGURED +} ENUM_State; + + + +/* Following states are used for CtrlXferStateMachine */ +typedef enum { + CTRL_IDLE =0, + 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_State; + +typedef enum { + USBH_USR_NO_RESP = 0, + USBH_USR_RESP_OK = 1, +} +USBH_USR_Status; + +/* Following states are used for RequestState */ +typedef enum { + CMD_IDLE =0, + CMD_SEND, + CMD_WAIT +} CMD_State; + + + +typedef struct _Ctrl +{ + uint8_t hc_num_in; + uint8_t hc_num_out; + uint8_t ep0size; + uint8_t *buff; + uint16_t length; + uint8_t errorcount; + uint16_t timer; + CTRL_STATUS status; + USB_Setup_TypeDef setup; + CTRL_State state; + +} USBH_Ctrl_TypeDef; + + + +typedef struct _DeviceProp +{ + + uint8_t address; + uint8_t speed; + USBH_DevDesc_TypeDef Dev_Desc; + USBH_CfgDesc_TypeDef Cfg_Desc; + USBH_InterfaceDesc_TypeDef Itf_Desc[USBH_MAX_NUM_INTERFACES]; + USBH_EpDesc_TypeDef Ep_Desc[USBH_MAX_NUM_INTERFACES][USBH_MAX_NUM_ENDPOINTS]; + USBH_HIDDesc_TypeDef HID_Desc; + +}USBH_Device_TypeDef; + +typedef struct _USBH_Class_cb +{ + USBH_Status (*Init)\ + (USB_OTG_CORE_HANDLE *pdev , void *phost); + void (*DeInit)\ + (USB_OTG_CORE_HANDLE *pdev , void *phost); + USBH_Status (*Requests)\ + (USB_OTG_CORE_HANDLE *pdev , void *phost); + USBH_Status (*Machine)\ + (USB_OTG_CORE_HANDLE *pdev , void *phost); + +} USBH_Class_cb_TypeDef; + + +typedef struct _USBH_USR_PROP +{ + void (*Init)(void); /* HostLibInitialized */ + void (*DeInit)(void); /* HostLibInitialized */ + void (*DeviceAttached)(void); /* DeviceAttached */ + void (*ResetDevice)(void); + void (*DeviceDisconnected)(void); + void (*OverCurrentDetected)(void); + void (*DeviceSpeedDetected)(uint8_t DeviceSpeed); /* DeviceSpeed */ + void (*DeviceDescAvailable)(void *); /* DeviceDescriptor is available */ + void (*DeviceAddressAssigned)(void); /* Address is assigned to USB Device */ + void (*ConfigurationDescAvailable)(USBH_CfgDesc_TypeDef *, + USBH_InterfaceDesc_TypeDef *, + USBH_EpDesc_TypeDef *); + /* Configuration Descriptor available */ + void (*ManufacturerString)(void *); /* ManufacturerString*/ + void (*ProductString)(void *); /* ProductString*/ + void (*SerialNumString)(void *); /* SerialNubString*/ + void (*EnumerationDone)(void); /* Enumeration finished */ + USBH_USR_Status (*UserInput)(void); + int (*USBH_USR_MSC_Application) (void); + void (*USBH_USR_DeviceNotSupported)(void); /* Device is not supported*/ + void (*UnrecoveredError)(void); + +} +USBH_Usr_cb_TypeDef; + +typedef struct _Host_TypeDef +{ + HOST_State gState; /* Host State Machine Value */ + HOST_State gStateBkp; /* backup of previous State machine value */ + ENUM_State EnumState; /* Enumeration state Machine */ + CMD_State RequestState; + USBH_Ctrl_TypeDef Control; + + USBH_Device_TypeDef device_prop; + + USBH_Class_cb_TypeDef *class_cb; + USBH_Usr_cb_TypeDef *usr_cb; + + +} USBH_HOST, *pUSBH_HOST; + +/** + * @} + */ + + + +/** @defgroup USBH_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBH_CORE_Exported_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBH_CORE_Exported_FunctionsPrototype + * @{ + */ +void USBH_Init(USB_OTG_CORE_HANDLE *pdev, + USB_OTG_CORE_ID_TypeDef coreID, + USBH_HOST *phost, + USBH_Class_cb_TypeDef *class_cb, + USBH_Usr_cb_TypeDef *usr_cb); + +USBH_Status USBH_DeInit(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost); +void USBH_Process(USB_OTG_CORE_HANDLE *pdev , + USBH_HOST *phost); +void USBH_ErrorHandle(USBH_HOST *phost, + USBH_Status errType); + +/** + * @} + */ + +#endif /* __USBH_CORE_H */ +/** + * @} + */ + +/** + * @} + */ + +/** +* @} +*/ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + + + diff --git a/example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_def.h b/example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_def.h new file mode 100644 index 0000000..35ebeb4 --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_def.h @@ -0,0 +1,280 @@ +/** + ****************************************************************************** + * @file usbh_def.h + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief Definitions used in the USB host library + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_DEF + * @brief This file is includes USB descriptors + * @{ + */ + +#ifndef USBH_DEF_H +#define USBH_DEF_H + +#ifndef USBH_NULL +#define USBH_NULL ((void *)0) +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#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) (((u16)(*((u8 *)(addr))))\ + + (((u16)(*(((u8 *)(addr)) + 1))) << 8)) + +#define USB_LEN_DESC_HDR 0x02 +#define USB_LEN_DEV_DESC 0x12 +#define USB_LEN_CFG_DESC 0x09 +#define USB_LEN_IF_DESC 0x09 +#define USB_LEN_EP_DESC 0x07 +#define USB_LEN_OTG_DESC 0x03 +#define USB_LEN_SETUP_PKT 0x08 + +/* bmRequestType :D7 Data Phase Transfer Direction */ +#define USB_REQ_DIR_MASK 0x80 +#define USB_H2D 0x00 +#define USB_D2H 0x80 + +/* bmRequestType D6..5 Type */ +#define USB_REQ_TYPE_STANDARD 0x00 +#define USB_REQ_TYPE_CLASS 0x20 +#define USB_REQ_TYPE_VENDOR 0x40 +#define USB_REQ_TYPE_RESERVED 0x60 + +/* bmRequestType D4..0 Recipient */ +#define USB_REQ_RECIPIENT_DEVICE 0x00 +#define USB_REQ_RECIPIENT_INTERFACE 0x01 +#define USB_REQ_RECIPIENT_ENDPOINT 0x02 +#define USB_REQ_RECIPIENT_OTHER 0x03 + +/* Table 9-4. Standard Request Codes */ +/* bRequest , Value */ +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +#define USB_REQ_SET_FEATURE 0x03 +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_DESCRIPTOR 0x07 +#define USB_REQ_GET_CONFIGURATION 0x08 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_GET_INTERFACE 0x0A +#define USB_REQ_SET_INTERFACE 0x0B +#define USB_REQ_SYNCH_FRAME 0x0C + +/* Table 9-5. Descriptor Types of USB Specifications */ +#define USB_DESC_TYPE_DEVICE 1 +#define USB_DESC_TYPE_CONFIGURATION 2 +#define USB_DESC_TYPE_STRING 3 +#define USB_DESC_TYPE_INTERFACE 4 +#define USB_DESC_TYPE_ENDPOINT 5 +#define USB_DESC_TYPE_DEVICE_QUALIFIER 6 +#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 7 +#define USB_DESC_TYPE_INTERFACE_POWER 8 +#define USB_DESC_TYPE_HID 0x21 +#define USB_DESC_TYPE_HID_REPORT 0x22 + + +#define USB_DEVICE_DESC_SIZE 18 +#define USB_CONFIGURATION_DESC_SIZE 9 +#define USB_HID_DESC_SIZE 9 +#define USB_INTERFACE_DESC_SIZE 9 +#define USB_ENDPOINT_DESC_SIZE 7 + +/* Descriptor Type and Descriptor Index */ +/* Use the following values when calling the function USBH_GetDescriptor */ +#define USB_DESC_DEVICE ((USB_DESC_TYPE_DEVICE << 8) & 0xFF00) +#define USB_DESC_CONFIGURATION ((USB_DESC_TYPE_CONFIGURATION << 8) & 0xFF00) +#define USB_DESC_STRING ((USB_DESC_TYPE_STRING << 8) & 0xFF00) +#define USB_DESC_INTERFACE ((USB_DESC_TYPE_INTERFACE << 8) & 0xFF00) +#define USB_DESC_ENDPOINT ((USB_DESC_TYPE_INTERFACE << 8) & 0xFF00) +#define USB_DESC_DEVICE_QUALIFIER ((USB_DESC_TYPE_DEVICE_QUALIFIER << 8) & 0xFF00) +#define USB_DESC_OTHER_SPEED_CONFIGURATION ((USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION << 8) & 0xFF00) +#define USB_DESC_INTERFACE_POWER ((USB_DESC_TYPE_INTERFACE_POWER << 8) & 0xFF00) +#define USB_DESC_HID_REPORT ((USB_DESC_TYPE_HID_REPORT << 8) & 0xFF00) +#define USB_DESC_HID ((USB_DESC_TYPE_HID << 8) & 0xFF00) + + +#define USB_EP_TYPE_CTRL 0x00 +#define USB_EP_TYPE_ISOC 0x01 +#define USB_EP_TYPE_BULK 0x02 +#define USB_EP_TYPE_INTR 0x03 + +#define USB_EP_DIR_OUT 0x00 +#define USB_EP_DIR_IN 0x80 +#define USB_EP_DIR_MSK 0x80 + +/* supported classes */ +#define USB_MSC_CLASS 0x08 +#define USB_HID_CLASS 0x03 + +/* Interface Descriptor field values for HID Boot Protocol */ +#define HID_BOOT_CODE 0x01 +#define HID_KEYBRD_BOOT_CODE 0x01 +#define HID_MOUSE_BOOT_CODE 0x02 + +/* As per USB specs 9.2.6.4 :Standard request with data request timeout: 5sec + Standard request with no data stage timeout : 50ms */ +#define DATA_STAGE_TIMEOUT 5000 +#define NODATA_STAGE_TIMEOUT 50 + +/** + * @} + */ + + +#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) + + +/* This Union is copied from usb_core.h */ +typedef union +{ + uint16_t w; + struct BW + { + uint8_t msb; + uint8_t lsb; + } + bw; +} +uint16_t_uint8_t; + + +typedef union _USB_Setup +{ + uint8_t d8[8]; + + 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_DevDesc_TypeDef; + + +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_CfgDesc_TypeDef; + + +typedef struct _HIDDescriptor +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdHID; /* indicates what endpoint this descriptor is describing */ + uint8_t bCountryCode; /* specifies the transfer type. */ + uint8_t bNumDescriptors; /* specifies the transfer type. */ + uint8_t bReportDescriptorType; /* Maximum Packet Size this endpoint is capable of sending or receiving */ + uint16_t wItemLength; /* is used to specify the polling interval of certain transfers. */ +} +USBH_HIDDesc_TypeDef; + + +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_InterfaceDesc_TypeDef; + + +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_EpDesc_TypeDef; +#endif +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + diff --git a/example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_hcs.h b/example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_hcs.h new file mode 100644 index 0000000..c5310b2 --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_hcs.h @@ -0,0 +1,125 @@ +/** + ****************************************************************************** + * @file usbh_hcs.h + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief Header file for usbh_hcs.c + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_HCS_H +#define __USBH_HCS_H + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_core.h" + + + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_HCS + * @brief This file is the header file for usbh_hcs.c + * @{ + */ + +/** @defgroup USBH_HCS_Exported_Defines + * @{ + */ +#define HC_MAX 8 + +#define HC_OK 0x0000 +#define HC_USED 0x8000 +#define HC_ERROR 0xFFFF +#define HC_USED_MASK 0x7FFF +/** + * @} + */ + +/** @defgroup USBH_HCS_Exported_Types + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_HCS_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_HCS_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_HCS_Exported_FunctionsPrototype + * @{ + */ + +uint8_t USBH_Alloc_Channel(USB_OTG_CORE_HANDLE *pdev, uint8_t ep_addr); + +uint8_t USBH_Free_Channel (USB_OTG_CORE_HANDLE *pdev, uint8_t idx); + +uint8_t USBH_DeAllocate_AllChannel (USB_OTG_CORE_HANDLE *pdev); + +uint8_t USBH_Open_Channel (USB_OTG_CORE_HANDLE *pdev, + uint8_t ch_num, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps); + +uint8_t USBH_Modify_Channel (USB_OTG_CORE_HANDLE *pdev, + uint8_t hc_num, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps); +/** + * @} + */ + + + +#endif /* __USBH_HCS_H */ + + +/** + * @} + */ + +/** + * @} + */ + +/** +* @} +*/ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + + diff --git a/example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_ioreq.h b/example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_ioreq.h new file mode 100644 index 0000000..4bdd436 --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_ioreq.h @@ -0,0 +1,140 @@ +/** + ****************************************************************************** + * @file usbh_ioreq.h + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief Header file for usbh_ioreq.c + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_IOREQ_H +#define __USBH_IOREQ_H + +/* Includes ------------------------------------------------------------------*/ +#include "usb_conf.h" +#include "usbh_core.h" +#include "usbh_def.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_SETUP_PKT_SIZE 8 +#define USBH_EP0_EP_NUM 0 +#define USBH_MAX_PACKET_SIZE 0x40 +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Exported_Types + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_IOREQ_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_IOREQ_Exported_FunctionsPrototype + * @{ + */ +USBH_Status USBH_CtlSendSetup ( USB_OTG_CORE_HANDLE *pdev, + uint8_t *buff, + uint8_t hc_num); + +USBH_Status USBH_CtlSendData ( USB_OTG_CORE_HANDLE *pdev, + uint8_t *buff, + uint8_t length, + uint8_t hc_num); + +USBH_Status USBH_CtlReceiveData( USB_OTG_CORE_HANDLE *pdev, + uint8_t *buff, + uint8_t length, + uint8_t hc_num); + +USBH_Status USBH_BulkReceiveData( USB_OTG_CORE_HANDLE *pdev, + uint8_t *buff, + uint16_t length, + uint8_t hc_num); + +USBH_Status USBH_BulkSendData ( USB_OTG_CORE_HANDLE *pdev, + uint8_t *buff, + uint16_t length, + uint8_t hc_num); + +USBH_Status USBH_InterruptReceiveData( USB_OTG_CORE_HANDLE *pdev, + uint8_t *buff, + uint8_t length, + uint8_t hc_num); + +USBH_Status USBH_InterruptSendData( USB_OTG_CORE_HANDLE *pdev, + uint8_t *buff, + uint8_t length, + uint8_t hc_num); + +USBH_Status USBH_CtlReq (USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t *buff, + uint16_t length); +/** + * @} + */ + +#endif /* __USBH_IOREQ_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** +* @} +*/ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + + diff --git a/example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_stdreq.h b/example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_stdreq.h new file mode 100644 index 0000000..22bf3d1 --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Core/inc/usbh_stdreq.h @@ -0,0 +1,148 @@ +/** + ****************************************************************************** + * @file usbh_stdreq.h + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief Header file for usbh_stdreq.c + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_STDREQ_H +#define __USBH_STDREQ_H + +/* Includes ------------------------------------------------------------------*/ + +#include "usb_conf.h" +#include "usb_hcd.h" +#include "usbh_core.h" +#include "usbh_def.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_STDREQ + * @brief This file is the + * @{ + */ + + +/** @defgroup USBH_STDREQ_Exported_Defines + * @{ + */ +/*Standard Feature Selector for clear feature command*/ +#define FEATURE_SELECTOR_ENDPOINT 0X00 +#define FEATURE_SELECTOR_DEVICE 0X01 + + +#define INTERFACE_DESC_TYPE 0x04 +#define ENDPOINT_DESC_TYPE 0x05 +#define INTERFACE_DESC_SIZE 0x09 + + +#define USBH_HID_CLASS 0x03 + +/** + * @} + */ + + +/** @defgroup USBH_STDREQ_Exported_Types + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_STDREQ_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_STDREQ_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_STDREQ_Exported_FunctionsPrototype + * @{ + */ +USBH_Status USBH_GetDescriptor(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t req_type, + uint16_t value_idx, + uint8_t* buff, + uint16_t length ); + +USBH_Status USBH_Get_DevDesc(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t length); + +USBH_Status USBH_Get_StringDesc(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t string_index, + uint8_t *buff, + uint16_t length); + +USBH_Status USBH_SetCfg(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint16_t configuration_value); + +USBH_Status USBH_Get_CfgDesc(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint16_t length); + +USBH_Status USBH_SetAddress(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t DeviceAddress); + +USBH_Status USBH_ClrFeature(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t ep_num, uint8_t hc_num); + +USBH_Status USBH_Issue_ClrFeature(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t ep_num); +/** + * @} + */ + +#endif /* __USBH_STDREQ_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** +* @} +*/ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + + diff --git a/example/stm32f4/STM32_USB_HOST_Library/Core/src/usbh_core.c b/example/stm32f4/STM32_USB_HOST_Library/Core/src/usbh_core.c new file mode 100644 index 0000000..a155357 --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Core/src/usbh_core.c @@ -0,0 +1,842 @@ +/** + ****************************************************************************** + * @file usbh_core.c + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief This file implements the functions for the core state machine process + * the enumeration and the control transfer process + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ +/* Includes ------------------------------------------------------------------*/ + +#include "usbh_ioreq.h" +#include "usb_bsp.h" +#include "usbh_hcs.h" +#include "usbh_stdreq.h" +#include "usbh_core.h" + + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_CORE + * @brief TThis file handles the basic enumaration when a device is connected + * to the host. + * @{ + */ + +/** @defgroup USBH_CORE_Private_TypesDefinitions + * @{ + */ +void USBH_Disconnect (void *pdev); +void USBH_Connect (void *pdev); + +USB_OTG_hPort_TypeDef USBH_DeviceConnStatus_cb = +{ + USBH_Disconnect, + USBH_Connect, + 0, + 0, + 0, + 0 +}; +/** + * @} + */ + + +/** @defgroup USBH_CORE_Private_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_CORE_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_CORE_Private_Variables + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_CORE_Private_FunctionPrototypes + * @{ + */ +static USBH_Status USBH_HandleEnum(USB_OTG_CORE_HANDLE *pdev, USBH_HOST *phost); +USBH_Status USBH_HandleControl (USB_OTG_CORE_HANDLE *pdev, USBH_HOST *phost); + +/** + * @} + */ + + +/** @defgroup USBH_CORE_Private_Functions + * @{ + */ + + +/** + * @brief USBH_Connect + * USB Connect callback function from the Interrupt. + * @param selected device + * @retval none + */ +void USBH_Connect (void *pdev) +{ + USB_OTG_CORE_HANDLE *ppdev = pdev; + ppdev->host.port_cb->ConnStatus = 1; + ppdev->host.port_cb->ConnHandled = 0; +} + +/** + * @brief USBH_Disconnect + * USB Disconnect callback function from the Interrupt. + * @param selected device + * @retval none + */ + +void USBH_Disconnect (void *pdev) +{ + + USB_OTG_CORE_HANDLE *ppdev = pdev; + + /* Make device Not connected flag true */ + ppdev->host.port_cb->DisconnStatus = 1; + ppdev->host.port_cb->DisconnHandled = 0; +} + +/** + * @brief USBH_Init + * Host hardware and stack initializations + * @param class_cb: Class callback structure address + * @param usr_cb: User callback structure address + * @retval None + */ +void USBH_Init(USB_OTG_CORE_HANDLE *pdev, + USB_OTG_CORE_ID_TypeDef coreID, + USBH_HOST *phost, + USBH_Class_cb_TypeDef *class_cb, + USBH_Usr_cb_TypeDef *usr_cb) +{ + + /* Hardware Init */ + USB_OTG_BSP_Init(pdev); + + /* configure GPIO pin used for switching VBUS power */ + USB_OTG_BSP_ConfigVBUS(0); + + + /* Host de-initializations */ + USBH_DeInit(pdev, phost); + + /*Register class and user callbacks */ + phost->class_cb = class_cb; + phost->usr_cb = usr_cb; + pdev->host.port_cb = &USBH_DeviceConnStatus_cb; + + pdev->host.port_cb->ConnStatus = 0; + pdev->host.port_cb->DisconnStatus = 0; + + + /* Start the USB OTG core */ + HCD_Init(pdev , coreID); + + /* Upon Init call usr call back */ + phost->usr_cb->Init(); + + /* Enable Interrupts */ + USB_OTG_BSP_EnableInterrupt(pdev); +} + +/** + * @brief USBH_DeInit + * Re-Initialize Host + * @param None + * @retval status: USBH_Status + */ +USBH_Status USBH_DeInit(USB_OTG_CORE_HANDLE *pdev, USBH_HOST *phost) +{ + /* Software Init */ + + phost->gState = HOST_IDLE; + phost->gStateBkp = HOST_IDLE; + phost->EnumState = ENUM_IDLE; + phost->RequestState = CMD_SEND; + + phost->Control.state = CTRL_SETUP; + phost->Control.ep0size = USB_OTG_MAX_EP0_SIZE; + + phost->device_prop.address = USBH_DEVICE_ADDRESS_DEFAULT; + phost->device_prop.speed = HPRT0_PRTSPD_FULL_SPEED; + + USBH_Free_Channel (pdev, phost->Control.hc_num_in); + USBH_Free_Channel (pdev, phost->Control.hc_num_out); + return USBH_OK; +} + +/** +* @brief USBH_Process +* USB Host core main state machine process +* @param None +* @retval None +*/ +void USBH_Process(USB_OTG_CORE_HANDLE *pdev , USBH_HOST *phost) +{ + volatile USBH_Status status = USBH_FAIL; + + switch (phost->gState) + { + case HOST_ISSUE_CORE_RESET : + + if ( HCD_ResetPort(pdev) == 0) + { + phost->gState = HOST_IDLE; + } + break; + + case HOST_IDLE : + + if (HCD_IsDeviceConnected(pdev)) + { + /* Wait for USB Connect Interrupt void USBH_ISR_Connected(void) */ + USBH_DeAllocate_AllChannel(pdev); + phost->gState = HOST_DEV_ATTACHED; + } + break; + + case HOST_DEV_ATTACHED : + + phost->usr_cb->DeviceAttached(); + pdev->host.port_cb->DisconnStatus = 0; + pdev->host.port_cb->ConnHandled = 1; + + phost->Control.hc_num_out = USBH_Alloc_Channel(pdev, 0x00); + phost->Control.hc_num_in = USBH_Alloc_Channel(pdev, 0x80); + + /* Reset USB Device */ + if ( HCD_ResetPort(pdev) == 0) + { + phost->usr_cb->ResetDevice(); + /* Wait for USB USBH_ISR_PrtEnDisableChange() + Host is Now ready to start the Enumeration + */ + + phost->device_prop.speed = HCD_GetCurrentSpeed(pdev); + + phost->gState = HOST_ENUMERATION; + phost->usr_cb->DeviceSpeedDetected(phost->device_prop.speed); + + /* Open Control pipes */ + USBH_Open_Channel (pdev, + phost->Control.hc_num_in, + phost->device_prop.address, + phost->device_prop.speed, + EP_TYPE_CTRL, + phost->Control.ep0size); + + /* Open Control pipes */ + USBH_Open_Channel (pdev, + phost->Control.hc_num_out, + phost->device_prop.address, + phost->device_prop.speed, + EP_TYPE_CTRL, + phost->Control.ep0size); + } + break; + + case HOST_ENUMERATION: + /* Check for enumeration status */ + if ( USBH_HandleEnum(pdev , phost) == USBH_OK) + { + /* The function shall return USBH_OK when full enumeration is complete */ + + /* user callback for end of device basic enumeration */ + phost->usr_cb->EnumerationDone(); + + phost->gState = HOST_USR_INPUT; + } + break; + + case HOST_USR_INPUT: + /*The function should return user response true to move to class state */ + if ( phost->usr_cb->UserInput() == USBH_USR_RESP_OK) + { + if((phost->class_cb->Init(pdev, phost))\ + == USBH_OK) + { + phost->gState = HOST_CLASS_REQUEST; + } + } + break; + + case HOST_CLASS_REQUEST: + /* process class standard contol requests state machine */ + status = phost->class_cb->Requests(pdev, phost); + + if(status == USBH_OK) + { + phost->gState = HOST_CLASS; + } + + else + { + USBH_ErrorHandle(phost, status); + } + + + break; + case HOST_CLASS: + /* process class state machine */ + status = phost->class_cb->Machine(pdev, phost); + USBH_ErrorHandle(phost, status); + break; + + case HOST_CTRL_XFER: + /* process control transfer state machine */ + USBH_HandleControl(pdev, phost); + break; + + case HOST_SUSPENDED: + break; + + case HOST_ERROR_STATE: + /* Re-Initilaize Host for new Enumeration */ + USBH_DeInit(pdev, phost); + phost->usr_cb->DeInit(); + phost->class_cb->DeInit(pdev, &phost->device_prop); + break; + + default : + break; + } + + /* check device disconnection event */ + if (!(HCD_IsDeviceConnected(pdev)) && + (pdev->host.port_cb->DisconnHandled == 0)) + { + /* Manage User disconnect operations*/ + phost->usr_cb->DeviceDisconnected(); + + pdev->host.port_cb->DisconnHandled = 1; /* Handle to avoid the Re-entry*/ + + /* Re-Initilaize Host for new Enumeration */ + USBH_DeInit(pdev, phost); + phost->usr_cb->DeInit(); + phost->class_cb->DeInit(pdev, &phost->device_prop); + } +} + + +/** + * @brief USBH_ErrorHandle + * This function handles the Error on Host side. + * @param errType : Type of Error or Busy/OK state + * @retval None + */ +void USBH_ErrorHandle(USBH_HOST *phost, USBH_Status errType) +{ + /* Error unrecovered or not supported device speed */ + if ( (errType == USBH_ERROR_SPEED_UNKNOWN) || + (errType == USBH_UNRECOVERED_ERROR) ) + { + phost->usr_cb->UnrecoveredError(); + phost->gState = HOST_ERROR_STATE; + } + /* USB host restart requested from application layer */ + else if(errType == USBH_APPLY_DEINIT) + { + phost->gState = HOST_ERROR_STATE; + /* user callback for initalization */ + phost->usr_cb->Init(); + } +} + + +/** + * @brief USBH_HandleEnum + * This function includes the complete enumeration process + * @param pdev: Selected device + * @retval USBH_Status + */ +static USBH_Status USBH_HandleEnum(USB_OTG_CORE_HANDLE *pdev, USBH_HOST *phost) +{ + USBH_Status Status = USBH_BUSY; + uint8_t Local_Buffer[64]; + + switch (phost->EnumState) + { + case ENUM_IDLE: + /* Get Device Desc for only 1st 8 bytes : To get EP0 MaxPacketSize */ + if ( USBH_Get_DevDesc(pdev , phost, 8) == USBH_OK) + { + phost->Control.ep0size = phost->device_prop.Dev_Desc.bMaxPacketSize; + + /* Issue Reset */ + HCD_ResetPort(pdev); + phost->EnumState = ENUM_GET_FULL_DEV_DESC; + + /* modify control channels configuration for MaxPacket size */ + USBH_Modify_Channel (pdev, + phost->Control.hc_num_out, + 0, + 0, + 0, + phost->Control.ep0size); + + USBH_Modify_Channel (pdev, + phost->Control.hc_num_in, + 0, + 0, + 0, + phost->Control.ep0size); + } + break; + + case ENUM_GET_FULL_DEV_DESC: + /* Get FULL Device Desc */ + if ( USBH_Get_DevDesc(pdev, phost, USB_DEVICE_DESC_SIZE)\ + == USBH_OK) + { + /* user callback for device descriptor available */ + phost->usr_cb->DeviceDescAvailable(&phost->device_prop.Dev_Desc); + phost->EnumState = ENUM_SET_ADDR; + } + break; + + case ENUM_SET_ADDR: + /* set address */ + if ( USBH_SetAddress(pdev, phost, USBH_DEVICE_ADDRESS) == USBH_OK) + { + phost->device_prop.address = USBH_DEVICE_ADDRESS; + + /* user callback for device address assigned */ + phost->usr_cb->DeviceAddressAssigned(); + phost->EnumState = ENUM_GET_CFG_DESC; + + /* modify control channels to update device address */ + USBH_Modify_Channel (pdev, + phost->Control.hc_num_in, + phost->device_prop.address, + 0, + 0, + 0); + + USBH_Modify_Channel (pdev, + phost->Control.hc_num_out, + phost->device_prop.address, + 0, + 0, + 0); + } + break; + + case ENUM_GET_CFG_DESC: + /* get standard configuration descriptor */ + if ( USBH_Get_CfgDesc(pdev, + phost, + USB_CONFIGURATION_DESC_SIZE) == USBH_OK) + { + phost->EnumState = ENUM_GET_FULL_CFG_DESC; + } + break; + + case ENUM_GET_FULL_CFG_DESC: + /* get FULL config descriptor (config, interface, endpoints) */ + if (USBH_Get_CfgDesc(pdev, + phost, + phost->device_prop.Cfg_Desc.wTotalLength) == USBH_OK) + { + /* User callback for configuration descriptors available */ + phost->usr_cb->ConfigurationDescAvailable(&phost->device_prop.Cfg_Desc, + phost->device_prop.Itf_Desc, + phost->device_prop.Ep_Desc[0]); + + phost->EnumState = ENUM_GET_MFC_STRING_DESC; + } + break; + + case ENUM_GET_MFC_STRING_DESC: + if (phost->device_prop.Dev_Desc.iManufacturer != 0) + { /* Check that Manufacturer String is available */ + + if ( USBH_Get_StringDesc(pdev, + phost, + phost->device_prop.Dev_Desc.iManufacturer, + Local_Buffer , + 0xff) == USBH_OK) + { + /* User callback for Manufacturing string */ + phost->usr_cb->ManufacturerString(Local_Buffer); + phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC; + } + } + else + { + phost->usr_cb->ManufacturerString("N/A"); + phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC; + } + break; + + case ENUM_GET_PRODUCT_STRING_DESC: + if (phost->device_prop.Dev_Desc.iProduct != 0) + { /* Check that Product string is available */ + if ( USBH_Get_StringDesc(pdev, + phost, + phost->device_prop.Dev_Desc.iProduct, + Local_Buffer, + 0xff) == USBH_OK) + { + /* User callback for Product string */ + phost->usr_cb->ProductString(Local_Buffer); + phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC; + } + } + else + { + phost->usr_cb->ProductString("N/A"); + phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC; + } + break; + + case ENUM_GET_SERIALNUM_STRING_DESC: + if (phost->device_prop.Dev_Desc.iSerialNumber != 0) + { /* Check that Serial number string is available */ + if ( USBH_Get_StringDesc(pdev, + phost, + phost->device_prop.Dev_Desc.iSerialNumber, + Local_Buffer, + 0xff) == USBH_OK) + { + /* User callback for Serial number string */ + phost->usr_cb->SerialNumString(Local_Buffer); + phost->EnumState = ENUM_SET_CONFIGURATION; + } + } + else + { + phost->usr_cb->SerialNumString("N/A"); + phost->EnumState = ENUM_SET_CONFIGURATION; + } + break; + + case ENUM_SET_CONFIGURATION: + /* set configuration (default config) */ + if (USBH_SetCfg(pdev, + phost, + phost->device_prop.Cfg_Desc.bConfigurationValue) == USBH_OK) + { + phost->EnumState = ENUM_DEV_CONFIGURED; + } + break; + + + case ENUM_DEV_CONFIGURED: + /* user callback for enumeration done */ + Status = USBH_OK; + break; + + default: + break; + } + return Status; +} + + +/** + * @brief USBH_HandleControl + * Handles the USB control transfer state machine + * @param pdev: Selected device + * @retval Status + */ +USBH_Status USBH_HandleControl (USB_OTG_CORE_HANDLE *pdev, USBH_HOST *phost) +{ + uint8_t direction; + static uint16_t timeout = 0; + USBH_Status status = USBH_OK; + URB_STATE URB_Status = URB_IDLE; + + phost->Control.status = CTRL_START; + + + switch (phost->Control.state) + { + case CTRL_SETUP: + /* send a SETUP packet */ + USBH_CtlSendSetup (pdev, + phost->Control.setup.d8 , + phost->Control.hc_num_out); + phost->Control.state = CTRL_SETUP_WAIT; + break; + + case CTRL_SETUP_WAIT: + + URB_Status = HCD_GetURB_State(pdev , phost->Control.hc_num_out); + /* case SETUP packet sent successfully */ + if(URB_Status == URB_DONE) + { + direction = (phost->Control.setup.b.bmRequestType & USB_REQ_DIR_MASK); + + /* check if there is a data stage */ + if (phost->Control.setup.b.wLength.w != 0 ) + { + timeout = DATA_STAGE_TIMEOUT; + 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 + { + timeout = NODATA_STAGE_TIMEOUT; + + /* 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; + } + } + /* Set the delay timer to enable timeout for data stage completion */ + phost->Control.timer = HCD_GetCurrentFrame(pdev); + } + else if(URB_Status == URB_ERROR) + { + phost->Control.state = CTRL_ERROR; + phost->Control.status = CTRL_XACTERR; + } + break; + + case CTRL_DATA_IN: + /* Issue an IN token */ + USBH_CtlReceiveData(pdev, + phost->Control.buff, + phost->Control.length, + phost->Control.hc_num_in); + + phost->Control.state = CTRL_DATA_IN_WAIT; + break; + + case CTRL_DATA_IN_WAIT: + + URB_Status = HCD_GetURB_State(pdev , phost->Control.hc_num_in); + + /* check is DATA packet transfered successfully */ + if (URB_Status == URB_DONE) + { + phost->Control.state = CTRL_STATUS_OUT; + } + + /* manage error cases*/ + if (URB_Status == URB_STALL) + { + /* In stall case, return to previous machine state*/ + phost->gState = phost->gStateBkp; + } + else if (URB_Status == URB_ERROR) + { + /* Device error */ + phost->Control.state = CTRL_ERROR; + } + else if ((HCD_GetCurrentFrame(pdev)- phost->Control.timer) > timeout) + { + /* timeout for IN transfer */ + phost->Control.state = CTRL_ERROR; + } + break; + + case CTRL_DATA_OUT: + /* Start DATA out transfer (only one DATA packet)*/ + + pdev->host.hc[phost->Control.hc_num_out].toggle_out ^= 1; + + USBH_CtlSendData (pdev, + phost->Control.buff, + phost->Control.length , + phost->Control.hc_num_out); + + phost->Control.state = CTRL_DATA_OUT_WAIT; + break; + + case CTRL_DATA_OUT_WAIT: + + URB_Status = HCD_GetURB_State(pdev , phost->Control.hc_num_out); + if (URB_Status == URB_DONE) + { /* If the Setup Pkt is sent successful, then change the state */ + phost->Control.state = CTRL_STATUS_IN; + } + + /* handle error cases */ + else if (URB_Status == URB_STALL) + { + /* In stall case, return to previous machine state*/ + phost->gState = phost->gStateBkp; + } + else if (URB_Status == URB_NOTREADY) + { + /* Nack received from device */ + phost->Control.state = CTRL_DATA_OUT; + } + else if (URB_Status == URB_ERROR) + { + /* device error */ + phost->Control.state = CTRL_ERROR; + } + break; + + + case CTRL_STATUS_IN: + /* Send 0 bytes out packet */ + USBH_CtlReceiveData (pdev, + 0, + 0, + phost->Control.hc_num_in); + + phost->Control.state = CTRL_STATUS_IN_WAIT; + + break; + + case CTRL_STATUS_IN_WAIT: + + URB_Status = HCD_GetURB_State(pdev , phost->Control.hc_num_in); + + if ( URB_Status == URB_DONE) + { /* Control transfers completed, Exit the State Machine */ + phost->gState = phost->gStateBkp; + } + + else if (URB_Status == URB_ERROR) + { + phost->Control.state = CTRL_ERROR; + } + + else if((HCD_GetCurrentFrame(pdev)\ + - phost->Control.timer) > timeout) + { + phost->Control.state = CTRL_ERROR; + } + else if(URB_Status == URB_STALL) + { + /* Control transfers completed, Exit the State Machine */ + phost->gState = phost->gStateBkp; + phost->Control.status = CTRL_STALL; + status = USBH_NOT_SUPPORTED; + } + break; + + case CTRL_STATUS_OUT: + pdev->host.hc[phost->Control.hc_num_out].toggle_out ^= 1; + USBH_CtlSendData (pdev, + 0, + 0, + phost->Control.hc_num_out); + + phost->Control.state = CTRL_STATUS_OUT_WAIT; + break; + + case CTRL_STATUS_OUT_WAIT: + + URB_Status = HCD_GetURB_State(pdev , phost->Control.hc_num_out); + if (URB_Status == URB_DONE) + { + phost->gState = phost->gStateBkp; + } + else if (URB_Status == URB_NOTREADY) + { + phost->Control.state = CTRL_STATUS_OUT; + } + else if (URB_Status == URB_ERROR) + { + phost->Control.state = CTRL_ERROR; + } + 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; + } + else + { + phost->Control.status = CTRL_FAIL; + phost->gState = phost->gStateBkp; + + status = USBH_FAIL; + } + break; + + default: + break; + } + return status; +} + + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + + + + diff --git a/example/stm32f4/STM32_USB_HOST_Library/Core/src/usbh_hcs.c b/example/stm32f4/STM32_USB_HOST_Library/Core/src/usbh_hcs.c new file mode 100644 index 0000000..c703d39 --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Core/src/usbh_hcs.c @@ -0,0 +1,253 @@ +/** + ****************************************************************************** + * @file usbh_hcs.c + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief This file implements functions for opening and closing host channels + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_hcs.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_HCS + * @brief This file includes opening and closing host channels + * @{ + */ + +/** @defgroup USBH_HCS_Private_Defines + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_HCS_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_HCS_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_HCS_Private_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBH_HCS_Private_FunctionPrototypes + * @{ + */ +static uint16_t USBH_GetFreeChannel (USB_OTG_CORE_HANDLE *pdev); +/** + * @} + */ + + +/** @defgroup USBH_HCS_Private_Functions + * @{ + */ + + + +/** + * @brief USBH_Open_Channel + * Open a pipe + * @param pdev : Selected device + * @param hc_num: Host channel 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 Status + */ +uint8_t USBH_Open_Channel (USB_OTG_CORE_HANDLE *pdev, + uint8_t hc_num, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps) +{ + + pdev->host.hc[hc_num].ep_num = pdev->host.channel[hc_num]& 0x7F; + pdev->host.hc[hc_num].ep_is_in = (pdev->host.channel[hc_num] & 0x80 ) == 0x80; + pdev->host.hc[hc_num].dev_addr = dev_address; + pdev->host.hc[hc_num].ep_type = ep_type; + pdev->host.hc[hc_num].max_packet = mps; + pdev->host.hc[hc_num].speed = speed; + pdev->host.hc[hc_num].toggle_in = 0; + pdev->host.hc[hc_num].toggle_out = 0; + if(speed == HPRT0_PRTSPD_HIGH_SPEED) + { + pdev->host.hc[hc_num].do_ping = 1; + } + + USB_OTG_HC_Init(pdev, hc_num) ; + + return HC_OK; + +} + +/** + * @brief USBH_Modify_Channel + * Modify a pipe + * @param pdev : Selected device + * @param hc_num: Host channel 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 Status + */ +uint8_t USBH_Modify_Channel (USB_OTG_CORE_HANDLE *pdev, + uint8_t hc_num, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps) +{ + + if(dev_address != 0) + { + pdev->host.hc[hc_num].dev_addr = dev_address; + } + + if((pdev->host.hc[hc_num].max_packet != mps) && (mps != 0)) + { + pdev->host.hc[hc_num].max_packet = mps; + } + + if((pdev->host.hc[hc_num].speed != speed ) && (speed != 0 )) + { + pdev->host.hc[hc_num].speed = speed; + } + + USB_OTG_HC_Init(pdev, hc_num); + return HC_OK; + +} + +/** + * @brief USBH_Alloc_Channel + * Allocate a new channel for the pipe + * @param ep_addr: End point for which the channel to be allocated + * @retval hc_num: Host channel number + */ +uint8_t USBH_Alloc_Channel (USB_OTG_CORE_HANDLE *pdev, uint8_t ep_addr) +{ + uint16_t hc_num; + + hc_num = USBH_GetFreeChannel(pdev); + + if (hc_num != HC_ERROR) + { + pdev->host.channel[hc_num] = HC_USED | ep_addr; + } + return hc_num; +} + +/** + * @brief USBH_Free_Pipe + * Free the USB host channel + * @param idx: Channel number to be freed + * @retval Status + */ +uint8_t USBH_Free_Channel (USB_OTG_CORE_HANDLE *pdev, uint8_t idx) +{ + if(idx < HC_MAX) + { + pdev->host.channel[idx] &= HC_USED_MASK; + } + return USBH_OK; +} + + +/** + * @brief USBH_DeAllocate_AllChannel + * Free all USB host channel +* @param pdev : core instance + * @retval Status + */ +uint8_t USBH_DeAllocate_AllChannel (USB_OTG_CORE_HANDLE *pdev) +{ + uint8_t idx; + + for (idx = 2; idx < HC_MAX ; idx ++) + { + pdev->host.channel[idx] = 0; + } + return USBH_OK; +} + +/** + * @brief USBH_GetFreeChannel + * Get a free channel number for allocation to a device endpoint + * @param None + * @retval idx: Free Channel number + */ +static uint16_t USBH_GetFreeChannel (USB_OTG_CORE_HANDLE *pdev) +{ + uint8_t idx = 0; + + for (idx = 0 ; idx < HC_MAX ; idx++) + { + if ((pdev->host.channel[idx] & HC_USED) == 0) + { + return idx; + } + } + return HC_ERROR; +} + + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + + diff --git a/example/stm32f4/STM32_USB_HOST_Library/Core/src/usbh_ioreq.c b/example/stm32f4/STM32_USB_HOST_Library/Core/src/usbh_ioreq.c new file mode 100644 index 0000000..a890848 --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Core/src/usbh_ioreq.c @@ -0,0 +1,419 @@ +/** + ****************************************************************************** + * @file usbh_ioreq.c + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief This file handles the issuing of the USB transactions + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ +/* Includes ------------------------------------------------------------------*/ + +#include "usbh_ioreq.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_IOREQ + * @brief This file handles the standard protocol processing (USB v2.0) + * @{ + */ + + +/** @defgroup USBH_IOREQ_Private_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + + +/** @defgroup USBH_IOREQ_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Private_Variables + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Private_FunctionPrototypes + * @{ + */ +static USBH_Status USBH_SubmitSetupRequest(USBH_HOST *phost, + uint8_t* buff, + uint16_t length); + +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Private_Functions + * @{ + */ + + +/** + * @brief USBH_CtlReq + * USBH_CtlReq sends a control request and provide the status after + * completion of the request + * @param pdev: Selected device + * @param req: Setup Request Structure + * @param buff: data buffer address to store the response + * @param length: length of the response + * @retval Status + */ +USBH_Status USBH_CtlReq (USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t *buff, + uint16_t length) +{ + USBH_Status status; + URB_STATE URB_Status = URB_IDLE; + + URB_Status = HCD_GetURB_State(pdev, phost->Control.hc_num_out); + + status = USBH_BUSY; + + switch (phost->RequestState) + { + case CMD_SEND: + /* Start a SETUP transfer */ + USBH_SubmitSetupRequest(phost, buff, length); + phost->RequestState = CMD_WAIT; + status = USBH_BUSY; + break; + + case CMD_WAIT: + if (URB_Status == URB_DONE) + { + /* Commands successfully sent and Response Received */ + phost->RequestState = CMD_SEND; + status = USBH_OK; + } + else if (URB_Status == URB_ERROR) + { + /* Failure Mode */ + phost->RequestState = CMD_SEND; + status = USBH_FAIL; + } + else if (URB_Status == URB_STALL) + { + /* Commands successfully sent and Response Received */ + phost->RequestState = CMD_SEND; + status = USBH_NOT_SUPPORTED; + } + break; + + default: + break; + } + return status; +} + +/** + * @brief USBH_CtlSendSetup + * Sends the Setup Packet to the Device + * @param pdev: Selected device + * @param buff: Buffer pointer from which the Data will be send to Device + * @param hc_num: Host channel Number + * @retval Status + */ +USBH_Status USBH_CtlSendSetup ( USB_OTG_CORE_HANDLE *pdev, + uint8_t *buff, + uint8_t hc_num){ + pdev->host.hc[hc_num].ep_is_in = 0; + pdev->host.hc[hc_num].data_pid = HC_PID_SETUP; + pdev->host.hc[hc_num].xfer_buff = buff; + pdev->host.hc[hc_num].xfer_len = USBH_SETUP_PKT_SIZE; + + return (USBH_Status)HCD_SubmitRequest (pdev , hc_num); +} + + +/** + * @brief USBH_CtlSendData + * Sends a data Packet to the Device + * @param pdev: Selected device + * @param buff: Buffer pointer from which the Data will be sent to Device + * @param length: Length of the data to be sent + * @param hc_num: Host channel Number + * @retval Status + */ +USBH_Status USBH_CtlSendData ( USB_OTG_CORE_HANDLE *pdev, + uint8_t *buff, + uint8_t length, + uint8_t hc_num) +{ + pdev->host.hc[hc_num].ep_is_in = 0; + pdev->host.hc[hc_num].xfer_buff = buff; + pdev->host.hc[hc_num].xfer_len = length; + + if ( length == 0 ) + { /* For Status OUT stage, Length==0, Status Out PID = 1 */ + pdev->host.hc[hc_num].toggle_out = 1; + } + + /* Set the Data Toggle bit as per the Flag */ + if ( pdev->host.hc[hc_num].toggle_out == 0) + { /* Put the PID 0 */ + pdev->host.hc[hc_num].data_pid = HC_PID_DATA0; + } + else + { /* Put the PID 1 */ + pdev->host.hc[hc_num].data_pid = HC_PID_DATA1 ; + } + + HCD_SubmitRequest (pdev , hc_num); + + return USBH_OK; +} + + +/** + * @brief USBH_CtlReceiveData + * Receives the Device Response to the Setup Packet + * @param pdev: Selected device + * @param buff: Buffer pointer in which the response needs to be copied + * @param length: Length of the data to be received + * @param hc_num: Host channel Number + * @retval Status. + */ +USBH_Status USBH_CtlReceiveData(USB_OTG_CORE_HANDLE *pdev, + uint8_t* buff, + uint8_t length, + uint8_t hc_num) +{ + + pdev->host.hc[hc_num].ep_is_in = 1; + pdev->host.hc[hc_num].data_pid = HC_PID_DATA1; + pdev->host.hc[hc_num].xfer_buff = buff; + pdev->host.hc[hc_num].xfer_len = length; + + HCD_SubmitRequest (pdev , hc_num); + + return USBH_OK; + +} + + +/** + * @brief USBH_BulkSendData + * Sends the Bulk Packet to the device + * @param pdev: Selected device + * @param buff: Buffer pointer from which the Data will be sent to Device + * @param length: Length of the data to be sent + * @param hc_num: Host channel Number + * @retval Status + */ +USBH_Status USBH_BulkSendData ( USB_OTG_CORE_HANDLE *pdev, + uint8_t *buff, + uint16_t length, + uint8_t hc_num) +{ + pdev->host.hc[hc_num].ep_is_in = 0; + pdev->host.hc[hc_num].xfer_buff = buff; + pdev->host.hc[hc_num].xfer_len = length; + + /* Set the Data Toggle bit as per the Flag */ + if ( pdev->host.hc[hc_num].toggle_out == 0) + { /* Put the PID 0 */ + pdev->host.hc[hc_num].data_pid = HC_PID_DATA0; + } + else + { /* Put the PID 1 */ + pdev->host.hc[hc_num].data_pid = HC_PID_DATA1 ; + } + + HCD_SubmitRequest (pdev , hc_num); + return USBH_OK; +} + + +/** + * @brief USBH_BulkReceiveData + * Receives IN bulk packet from device + * @param pdev: Selected device + * @param buff: Buffer pointer in which the received data packet to be copied + * @param length: Length of the data to be received + * @param hc_num: Host channel Number + * @retval Status. + */ +USBH_Status USBH_BulkReceiveData( USB_OTG_CORE_HANDLE *pdev, + uint8_t *buff, + uint16_t length, + uint8_t hc_num) +{ + pdev->host.hc[hc_num].ep_is_in = 1; + pdev->host.hc[hc_num].xfer_buff = buff; + pdev->host.hc[hc_num].xfer_len = length; + + + if( pdev->host.hc[hc_num].toggle_in == 0) + { + pdev->host.hc[hc_num].data_pid = HC_PID_DATA0; + } + else + { + pdev->host.hc[hc_num].data_pid = HC_PID_DATA1; + } + + HCD_SubmitRequest (pdev , hc_num); + return USBH_OK; +} + + +/** + * @brief USBH_InterruptReceiveData + * Receives the Device Response to the Interrupt IN token + * @param pdev: Selected device + * @param buff: Buffer pointer in which the response needs to be copied + * @param length: Length of the data to be received + * @param hc_num: Host channel Number + * @retval Status. + */ +USBH_Status USBH_InterruptReceiveData( USB_OTG_CORE_HANDLE *pdev, + uint8_t *buff, + uint8_t length, + uint8_t hc_num) +{ + + pdev->host.hc[hc_num].ep_is_in = 1; + pdev->host.hc[hc_num].xfer_buff = buff; + pdev->host.hc[hc_num].xfer_len = length; + + + + if(pdev->host.hc[hc_num].toggle_in == 0) + { + pdev->host.hc[hc_num].data_pid = HC_PID_DATA0; + } + else + { + pdev->host.hc[hc_num].data_pid = HC_PID_DATA1; + } + + /* toggle DATA PID */ + pdev->host.hc[hc_num].toggle_in ^= 1; + + HCD_SubmitRequest (pdev , hc_num); + + return USBH_OK; +} + +/** + * @brief USBH_InterruptSendData + * Sends the data on Interrupt OUT Endpoint + * @param pdev: Selected device + * @param buff: Buffer pointer from where the data needs to be copied + * @param length: Length of the data to be sent + * @param hc_num: Host channel Number + * @retval Status. + */ +USBH_Status USBH_InterruptSendData( USB_OTG_CORE_HANDLE *pdev, + uint8_t *buff, + uint8_t length, + uint8_t hc_num) +{ + + pdev->host.hc[hc_num].ep_is_in = 0; + pdev->host.hc[hc_num].xfer_buff = buff; + pdev->host.hc[hc_num].xfer_len = length; + + if(pdev->host.hc[hc_num].toggle_in == 0) + { + pdev->host.hc[hc_num].data_pid = HC_PID_DATA0; + } + else + { + pdev->host.hc[hc_num].data_pid = HC_PID_DATA1; + } + + pdev->host.hc[hc_num].toggle_in ^= 1; + + HCD_SubmitRequest (pdev , hc_num); + + return USBH_OK; +} + + +/** + * @brief USBH_SubmitSetupRequest + * Start a setup transfer by changing the state-machine and + * initializing the required variables needed for the Control Transfer + * @param pdev: Selected device + * @param setup: Setup Request Structure + * @param buff: Buffer used for setup request + * @param length: Length of the data + * @retval Status. +*/ +static USBH_Status USBH_SubmitSetupRequest(USBH_HOST *phost, + uint8_t* buff, + uint16_t length) +{ + + /* Save Global State */ + phost->gStateBkp = phost->gState; + + /* Prepare the Transactions */ + phost->gState = HOST_CTRL_XFER; + phost->Control.buff = buff; + phost->Control.length = length; + phost->Control.state = CTRL_SETUP; + + return USBH_OK; +} + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + + + diff --git a/example/stm32f4/STM32_USB_HOST_Library/Core/src/usbh_stdreq.c b/example/stm32f4/STM32_USB_HOST_Library/Core/src/usbh_stdreq.c new file mode 100644 index 0000000..fb90c4b --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Core/src/usbh_stdreq.c @@ -0,0 +1,551 @@ +/** + ****************************************************************************** + * @file usbh_stdreq.c + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief This file implements the standard requests for device enumeration + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ +/* Includes ------------------------------------------------------------------*/ + +#include "usbh_ioreq.h" +#include "usbh_stdreq.h" + +/** @addtogroup USBH_LIB +* @{ +*/ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_STDREQ +* @brief This file implements the standard requests for device enumeration +* @{ +*/ + + +/** @defgroup USBH_STDREQ_Private_Defines +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_STDREQ_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + + +/** @defgroup USBH_STDREQ_Private_Macros +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_STDREQ_Private_Variables +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_STDREQ_Private_FunctionPrototypes +* @{ +*/ +static void USBH_ParseDevDesc (USBH_DevDesc_TypeDef* , uint8_t *buf, uint16_t length); + +static void USBH_ParseCfgDesc (USBH_CfgDesc_TypeDef* cfg_desc, + USBH_InterfaceDesc_TypeDef* itf_desc, + USBH_EpDesc_TypeDef* ep_desc, + uint8_t *buf, + uint16_t length); +static USBH_DescHeader_t *USBH_GetNextDesc (uint8_t *pbuf, + uint16_t *ptr); + +static void USBH_ParseInterfaceDesc (USBH_InterfaceDesc_TypeDef *if_descriptor, uint8_t *buf); +static void USBH_ParseEPDesc (USBH_EpDesc_TypeDef *ep_descriptor, uint8_t *buf); + +static void USBH_ParseStringDesc (uint8_t* psrc, uint8_t* pdest, uint16_t length); +/** +* @} +*/ + + +/** @defgroup USBH_STDREQ_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 pdev: Selected device +* @param dev_desc: Device Descriptor buffer address +* @param pdev->host.Rx_Buffer: Receive Buffer address +* @param length: Length of the descriptor +* @retval Status +*/ +USBH_Status USBH_Get_DevDesc(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t length) +{ + + USBH_Status status; + + if((status = USBH_GetDescriptor(pdev, + phost, + USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD, + USB_DESC_DEVICE, + pdev->host.Rx_Buffer, + length)) == USBH_OK) + { + /* Commands successfully sent and Response Received */ + USBH_ParseDevDesc(&phost->device_prop.Dev_Desc, pdev->host.Rx_Buffer, length); + } + return status; +} + +/** +* @brief USBH_Get_CfgDesc +* Issues Configuration Descriptor to the device. Once the response +* received, it parses the configuartion descriptor and updates the +* status. +* @param pdev: Selected device +* @param cfg_desc: Configuration Descriptor address +* @param itf_desc: Interface Descriptor address +* @param ep_desc: Endpoint Descriptor address +* @param length: Length of the descriptor +* @retval Status +*/ +USBH_Status USBH_Get_CfgDesc(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint16_t length) + +{ + USBH_Status status; + + if((status = USBH_GetDescriptor(pdev, + phost, + USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD, + USB_DESC_CONFIGURATION, + pdev->host.Rx_Buffer, + length)) == USBH_OK) + { + /* Commands successfully sent and Response Received */ + USBH_ParseCfgDesc (&phost->device_prop.Cfg_Desc, + phost->device_prop.Itf_Desc, + phost->device_prop.Ep_Desc[0], + pdev->host.Rx_Buffer, + 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 pdev: Selected device +* @param string_index: String index for the descriptor +* @param buff: Buffer address for the descriptor +* @param length: Length of the descriptor +* @retval Status +*/ +USBH_Status USBH_Get_StringDesc(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t string_index, + uint8_t *buff, + uint16_t length) +{ + USBH_Status status; + + if((status = USBH_GetDescriptor(pdev, + phost, + USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD, + USB_DESC_STRING | string_index, + pdev->host.Rx_Buffer, + length)) == USBH_OK) + { + /* Commands successfully sent and Response Received */ + USBH_ParseStringDesc(pdev->host.Rx_Buffer,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 pdev: Selected device +* @param req_type: Descriptor type +* @param value_idx: wValue for the GetDescriptr request +* @param buff: Buffer to store the descriptor +* @param length: Length of the descriptor +* @retval Status +*/ +USBH_Status USBH_GetDescriptor(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t req_type, + uint16_t value_idx, + uint8_t* buff, + uint16_t length ) +{ + phost->Control.setup.b.bmRequestType = USB_D2H | req_type; + phost->Control.setup.b.bRequest = USB_REQ_GET_DESCRIPTOR; + phost->Control.setup.b.wValue.w = value_idx; + + if ((value_idx & 0xff00) == USB_DESC_STRING) + { + phost->Control.setup.b.wIndex.w = 0x0409; + } + else + { + phost->Control.setup.b.wIndex.w = 0; + } + phost->Control.setup.b.wLength.w = length; + return USBH_CtlReq(pdev, phost, buff , length ); +} + +/** +* @brief USBH_SetAddress +* This command sets the address to the connected device +* @param pdev: Selected device +* @param DeviceAddress: Device address to assign +* @retval Status +*/ +USBH_Status USBH_SetAddress(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t DeviceAddress) +{ + phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE | \ + USB_REQ_TYPE_STANDARD; + + phost->Control.setup.b.bRequest = USB_REQ_SET_ADDRESS; + + phost->Control.setup.b.wValue.w = (uint16_t)DeviceAddress; + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = 0; + + return USBH_CtlReq(pdev, phost, 0 , 0 ); +} + +/** +* @brief USBH_SetCfg +* The command sets the configuration value to the connected device +* @param pdev: Selected device +* @param cfg_idx: Configuration value +* @retval Status +*/ +USBH_Status USBH_SetCfg(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint16_t cfg_idx) +{ + + phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE |\ + USB_REQ_TYPE_STANDARD; + phost->Control.setup.b.bRequest = USB_REQ_SET_CONFIGURATION; + phost->Control.setup.b.wValue.w = cfg_idx; + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = 0; + + return USBH_CtlReq(pdev, phost, 0 , 0 ); +} + +/** +* @brief USBH_ClrFeature +* This request is used to clear or disable a specific feature. + +* @param pdev: Selected device +* @param ep_num: endpoint number +* @param hc_num: Host channel number +* @retval Status +*/ +USBH_Status USBH_ClrFeature(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t ep_num, + uint8_t hc_num) +{ + + phost->Control.setup.b.bmRequestType = USB_H2D | + USB_REQ_RECIPIENT_ENDPOINT | + USB_REQ_TYPE_STANDARD; + + phost->Control.setup.b.bRequest = USB_REQ_CLEAR_FEATURE; + phost->Control.setup.b.wValue.w = FEATURE_SELECTOR_ENDPOINT; + phost->Control.setup.b.wIndex.w = ep_num; + phost->Control.setup.b.wLength.w = 0; + + if ((ep_num & USB_REQ_DIR_MASK ) == USB_D2H) + { /* EP Type is IN */ + pdev->host.hc[hc_num].toggle_in = 0; + } + else + {/* EP Type is OUT */ + pdev->host.hc[hc_num].toggle_out = 0; + } + + return USBH_CtlReq(pdev, phost, 0 , 0 ); +} + +/** +* @brief USBH_ParseDevDesc +* This function Parses the device descriptor +* @param dev_desc: device_descriptor destinaton address +* @param buf: Buffer where the source descriptor is available +* @param length: Length of the descriptor +* @retval None +*/ +static void USBH_ParseDevDesc (USBH_DevDesc_TypeDef* dev_desc, + uint8_t *buf, + uint16_t length) +{ + dev_desc->bLength = *(uint8_t *) (buf + 0); + dev_desc->bDescriptorType = *(uint8_t *) (buf + 1); + dev_desc->bcdUSB = LE16 (buf + 2); + dev_desc->bDeviceClass = *(uint8_t *) (buf + 4); + dev_desc->bDeviceSubClass = *(uint8_t *) (buf + 5); + dev_desc->bDeviceProtocol = *(uint8_t *) (buf + 6); + dev_desc->bMaxPacketSize = *(uint8_t *) (buf + 7); + + if (length > 8) + { /* For 1st time after device connection, Host may issue only 8 bytes for + Device Descriptor Length */ + dev_desc->idVendor = LE16 (buf + 8); + dev_desc->idProduct = LE16 (buf + 10); + dev_desc->bcdDevice = LE16 (buf + 12); + dev_desc->iManufacturer = *(uint8_t *) (buf + 14); + dev_desc->iProduct = *(uint8_t *) (buf + 15); + dev_desc->iSerialNumber = *(uint8_t *) (buf + 16); + dev_desc->bNumConfigurations = *(uint8_t *) (buf + 17); + } +} + +/** +* @brief USBH_ParseCfgDesc +* This function Parses the configuration descriptor +* @param cfg_desc: Configuration Descriptor address +* @param itf_desc: Interface Descriptor address +* @param ep_desc: Endpoint Descriptor address +* @param buf: Buffer where the source descriptor is available +* @param length: Length of the descriptor +* @retval None +*/ +static void USBH_ParseCfgDesc (USBH_CfgDesc_TypeDef* cfg_desc, + USBH_InterfaceDesc_TypeDef* itf_desc, + USBH_EpDesc_TypeDef* ep_desc, + uint8_t *buf, + uint16_t length) +{ + USBH_InterfaceDesc_TypeDef *pif ; + USBH_EpDesc_TypeDef *pep; + USBH_DescHeader_t *pdesc = (USBH_DescHeader_t *)buf; + uint16_t ptr; + int8_t if_ix; + int8_t ep_ix; + + pdesc = (USBH_DescHeader_t *)buf; + + /* Parse configuration descriptor */ + cfg_desc->bLength = *(uint8_t *) (buf + 0); + cfg_desc->bDescriptorType = *(uint8_t *) (buf + 1); + cfg_desc->wTotalLength = LE16 (buf + 2); + cfg_desc->bNumInterfaces = *(uint8_t *) (buf + 4); + cfg_desc->bConfigurationValue = *(uint8_t *) (buf + 5); + cfg_desc->iConfiguration = *(uint8_t *) (buf + 6); + cfg_desc->bmAttributes = *(uint8_t *) (buf + 7); + cfg_desc->bMaxPower = *(uint8_t *) (buf + 8); + + + if (length > USB_CONFIGURATION_DESC_SIZE) + { + ptr = USB_LEN_CFG_DESC; + + if ( cfg_desc->bNumInterfaces <= USBH_MAX_NUM_INTERFACES) + { + if_ix = 0; + pif = (USBH_InterfaceDesc_TypeDef *)0; + + /* Parse Interface descriptor relative to the current configuration */ + if(cfg_desc->bNumInterfaces <= USBH_MAX_NUM_INTERFACES) + { + while (if_ix < cfg_desc->bNumInterfaces) + { + pdesc = USBH_GetNextDesc((uint8_t *)pdesc, &ptr); + if (pdesc->bDescriptorType == USB_DESC_TYPE_INTERFACE) + { + pif = &itf_desc[if_ix]; + USBH_ParseInterfaceDesc (pif, (uint8_t *)pdesc); + ep_ix = 0; + + /* Parse Ep descriptors relative to the current interface */ + if(pif->bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) + { + while (ep_ix < pif->bNumEndpoints) + { + pdesc = USBH_GetNextDesc((void* )pdesc, &ptr); + if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT) + { + pep = &ep_desc[ep_ix]; + USBH_ParseEPDesc (pep, (uint8_t *)pdesc); + ep_ix++; + } + else + { + ptr += pdesc->bLength; + } + } + } + if_ix++; + } + else + { + ptr += pdesc->bLength; + } + } + } + } + } +} + + +/** +* @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_InterfaceDesc_TypeDef *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_EpDesc_TypeDef *ep_descriptor, + uint8_t *buf) +{ + + ep_descriptor->bLength = *(uint8_t *) (buf + 0); + ep_descriptor->bDescriptorType = *(uint8_t *) (buf + 1); + ep_descriptor->bEndpointAddress = *(uint8_t *) (buf + 2); + ep_descriptor->bmAttributes = *(uint8_t *) (buf + 3); + ep_descriptor->wMaxPacketSize = LE16 (buf + 4); + ep_descriptor->bInterval = *(uint8_t *) (buf + 6); +} + +/** +* @brief USBH_ParseStringDesc +* This function Parses the string descriptor +* @param psrc: Source pointer containing the descriptor data +* @param pdest: Destination address pointer +* @param length: Length of the descriptor +* @retval None +*/ +static void USBH_ParseStringDesc (uint8_t* psrc, + uint8_t* pdest, + uint16_t length) +{ + uint16_t strlength; + uint16_t idx; + + /* The UNICODE string descriptor is not NULL-terminated. The string length is + computed by substracting two from the value of the first byte of the descriptor. + */ + + /* Check which is lower size, the Size of string or the length of bytes read + from the device */ + + if ( psrc[1] == USB_DESC_TYPE_STRING) + { /* Make sure the Descriptor is String Type */ + + /* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */ + strlength = ( ( (psrc[0]-2) <= length) ? (psrc[0]-2) :length); + psrc += 2; /* Adjust the offset ignoring the String Len and Descriptor type */ + + for (idx = 0; idx < strlength; idx+=2 ) + {/* Copy Only the string and ignore the UNICODE ID, hence add the src */ + *pdest = psrc[idx]; + pdest++; + } + *pdest = 0; /* mark end of string */ + } +} + +/** +* @brief USBH_GetNextDesc +* This function return the next descriptor header +* @param buf: Buffer where the cfg descriptor is available +* @param ptr: data popinter inside the cfg descriptor +* @retval next header +*/ +static USBH_DescHeader_t *USBH_GetNextDesc (uint8_t *pbuf, uint16_t *ptr) +{ + USBH_DescHeader_t *pnext; + + *ptr += ((USBH_DescHeader_t *)pbuf)->bLength; + pnext = (USBH_DescHeader_t *)((uint8_t *)pbuf + \ + ((USBH_DescHeader_t *)pbuf)->bLength); + + return(pnext); +} + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + + + + -- 2.47.2