基础版本

This commit is contained in:
bathfire
2026-04-27 16:55:02 +08:00
commit 64b3e488da
269 changed files with 383851 additions and 0 deletions
@@ -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.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* 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****/
@@ -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.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* 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****/
@@ -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.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/** @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****/
@@ -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.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* 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****/
@@ -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.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* 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****/
@@ -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.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* 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****/
@@ -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.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* 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****/
@@ -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.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* 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****/
@@ -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.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* 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****/
@@ -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.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* 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****/