2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  SPDX - FileCopyrightText :  2023 - 2024  Espressif  Systems  ( Shanghai )  CO  LTD 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  SPDX - License - Identifier :  Apache - 2.0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <string.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <stdint.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "esp_err.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "esp_log.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "esp_heap_caps.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "freertos/FreeRTOS.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "freertos/task.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "usb_private.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "usbh.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "enum.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "usb/usb_helpers.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define SET_ADDR_RECOVERY_INTERVAL_MS               CONFIG_USB_HOST_SET_ADDR_RECOVERY_MS 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define ENUM_CTRL_TRANSFER_MAX_DATA_LEN             CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define ENUM_INIT_VALUE_DEV_ADDR                    1        // Init value for device address
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define ENUM_DEFAULT_CONFIGURATION_VALUE            1        // Default configuration value for SetConfiguration() request
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define ENUM_SHORT_DESC_REQ_LEN                     8        // Number of bytes to request when getting a short descriptor (just enough to get bMaxPacketSize0 or wTotalLength)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define ENUM_WORST_CASE_MPS_LS                      8        // The worst case MPS of EP0 for a LS device
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define ENUM_WORST_CASE_MPS_FS_HS                   64       // The worst case MPS of EP0 for a FS/HS device
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define ENUM_LANGID                                 0x409    // Current enumeration only supports English (United States) string descriptors
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define ENUM_MAX_ADDRESS                            (127)    // Maximal device address value
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Stages  of  device  enumeration  listed  in  their  order  of  execution 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  Entry : 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								 *  -  These  stages  MUST  BE  LISTED  IN  THE  ORDER  OF  THEIR  EXECUTION  as  the  enumeration  will  simply  increment  the  current  stage 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  If  an  error  occurs  at  any  stage ,  ENUM_STAGE_CANCEL  acts  as  a  common  exit  stage  on  failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  Must  start  with  0  as  enum  is  also  used  as  an  index 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  The  short  descriptor  stages  are  used  to  fetch  the  start  particular  descriptors  that  don ' t  have  a  fixed  length  in  order  to  determine  the  full  descriptors  length 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  -  Any  state  of  Get  String  Descriptor  could  be  STALLed  by  the  device .  In  that  case  we  just  don ' t  fetch  them  and  treat  enumeration  as  successful 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								typedef  enum  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_IDLE  =  0 ,                     /**< There is no device awaiting enumeration */ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // Basic Device enumeration
 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_GET_SHORT_DEV_DESC ,           /**< Getting short dev desc (wLength is ENUM_SHORT_DESC_REQ_LEN) */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_CHECK_SHORT_DEV_DESC ,         /**< Save bMaxPacketSize0 from the short dev desc. Update the MPS of the enum pipe */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_SECOND_RESET ,                 /**< Reset the device again (Workaround for old USB devices that get confused by the previous short dev desc request). */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_SET_ADDR ,                     /**< Send SET_ADDRESS request */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_CHECK_ADDR ,                   /**< Update the enum pipe's target address */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_SET_ADDR_RECOVERY ,            /**< Wait SET ADDRESS recovery interval at least for 2ms due to usb_20, chapter 9.2.6.3 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_GET_FULL_DEV_DESC ,            /**< Get the full dev desc */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_CHECK_FULL_DEV_DESC ,          /**< Check the full dev desc, fill it into the device object in USBH. Save the string descriptor indexes*/ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_SELECT_CONFIG ,                /**< Select configuration: select default ENUM_DEFAULT_CONFIGURATION_VALUE value or use callback if ENABLE_ENUM_FILTER_CALLBACK enabled */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_GET_SHORT_CONFIG_DESC ,        /**< Getting a short config desc (wLength is ENUM_SHORT_DESC_REQ_LEN) */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_CHECK_SHORT_CONFIG_DESC ,      /**< Save wTotalLength of the short config desc */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_GET_FULL_CONFIG_DESC ,         /**< Get the full config desc (wLength is the saved wTotalLength) */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_CHECK_FULL_CONFIG_DESC ,       /**< Check the full config desc, fill it into the device object in USBH */ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // Get String Descriptors
 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_GET_SHORT_LANGID_TABLE ,       /**< Get the header of the LANGID table string descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_CHECK_SHORT_LANGID_TABLE ,     /**< Save the bLength of the LANGID table string descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_GET_FULL_LANGID_TABLE ,        /**< Get the full LANGID table string descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_CHECK_FULL_LANGID_TABLE ,      /**< Check whether ENUM_LANGID is in the LANGID table */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_GET_SHORT_MANU_STR_DESC ,      /**< Get the header of the iManufacturer string descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_CHECK_SHORT_MANU_STR_DESC ,    /**< Save the bLength of the iManufacturer string descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_GET_FULL_MANU_STR_DESC ,       /**< Get the full iManufacturer string descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_CHECK_FULL_MANU_STR_DESC ,     /**< Check and fill the full iManufacturer string descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_GET_SHORT_PROD_STR_DESC ,      /**< Get the header of the string descriptor at index iProduct */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_CHECK_SHORT_PROD_STR_DESC ,    /**< Save the bLength of the iProduct string descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_GET_FULL_PROD_STR_DESC ,       /**< Get the full iProduct string descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_CHECK_FULL_PROD_STR_DESC ,     /**< Check and fill the full iProduct string descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_GET_SHORT_SER_STR_DESC ,       /**< Get the header of the string descriptor at index iSerialNumber */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_CHECK_SHORT_SER_STR_DESC ,     /**< Save the bLength of the iSerialNumber string descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_GET_FULL_SER_STR_DESC ,        /**< Get the full iSerialNumber string descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_CHECK_FULL_SER_STR_DESC ,      /**< Check and fill the full iSerialNumber string descriptor */ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // Set Configuration
 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_SET_CONFIG ,                   /**< Send SET_CONFIGURATION request */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_CHECK_CONFIG ,                 /**< Check that SET_CONFIGURATION request was successful */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Terminal stages
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_COMPLETE ,                     /**< Successful enumeration complete. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_STAGE_CANCEL ,                       /**< Cancel enumeration. Free device resources */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}  enum_stage_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								const  char  * const  enum_stage_strings [ ]  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " NONE " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " GET_SHORT_DEV_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " CHECK_SHORT_DEV_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " SECOND_RESET " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " SET_ADDR " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " CHECK_ADDR " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " SET_ADDR_RECOVERY " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " GET_FULL_DEV_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " CHECK_FULL_DEV_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " SELECT_CONFIG " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " GET_SHORT_CONFIG_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " CHECK_SHORT_CONFIG_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " GET_FULL_CONFIG_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " CHECK_FULL_CONFIG_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " GET_SHORT_LANGID_TABLE " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " CHECK_SHORT_LANGID_TABLE " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " GET_FULL_LANGID_TABLE " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " CHECK_FULL_LANGID_TABLE " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " GET_SHORT_MANU_STR_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " CHECK_SHORT_MANU_STR_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " GET_FULL_MANU_STR_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " CHECK_FULL_MANU_STR_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " GET_SHORT_PROD_STR_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " CHECK_SHORT_PROD_STR_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " GET_FULL_PROD_STR_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " CHECK_FULL_PROD_STR_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " GET_SHORT_SER_STR_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " CHECK_SHORT_SER_STR_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " GET_FULL_SER_STR_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " CHECK_FULL_SER_STR_DESC " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " SET_CONFIG " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " CHECK_CONFIG " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " COMPLETE " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " CANCEL " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								typedef  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Constant
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  new_dev_addr ;            /**< Device address that should be assigned during enumeration */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  bMaxPacketSize0 ;         /**< Max packet size of the device's EP0. Read from bMaxPacketSize0 field of device descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint16_t  wTotalLength ;           /**< Total length of device's configuration descriptor. Read from wTotalLength field of config descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  iManufacturer ;           /**< Index of the Manufacturer string descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  iProduct ;                /**< Index of the Product string descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  iSerialNumber ;           /**< Index of the Serial Number string descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  str_desc_bLength ;        /**< Saved bLength from getting a short string descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  bConfigurationValue ;     /**< Device's current configuration number */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}  enum_device_params_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								typedef  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        union  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                uint32_t  processing :  1 ;              /**< Enumeration process is active */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                uint32_t  reserved31 :  31 ;             /**< Reserved */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            uint32_t  val ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  flags ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        enum_stage_t  stage ;                          /**< Current enumeration stage */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        uint8_t  next_dev_addr ;                       /**< Device address for device under enumeration */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  dynamic ;                                       /**< Dynamic members. Require a critical section */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Device related objects, initialized at start of a particular enumeration
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        unsigned  int  dev_uid ;                        /**< Unique device ID being enumerated */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        usb_device_handle_t  dev_hdl ;                 /**< Handle of device being enumerated */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Parent info for optimization and more clean debug output
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        usb_device_handle_t  parent_dev_hdl ;          /**< Device's parent handle */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        uint8_t  parent_dev_addr ;                     /**< Device's parent address */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        uint8_t  parent_port_num ;                     /**< Device's parent port number */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Parameters, updated during enumeration
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        enum_device_params_t  dev_params ;             /**< Parameters of device under enumeration */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        int  expect_num_bytes ;                        /**< Expected number of bytes for IN transfers stages. Set to 0 for OUT transfer */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  single_thread ;                                 /**< Single thread members don't require a critical section so long as they are never accessed from multiple threads */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Internal objects
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        urb_t  * urb ;                                  /**< URB used for enumeration control transfers. Max data length of ENUM_CTRL_TRANSFER_MAX_DATA_LEN */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Callbacks
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        usb_proc_req_cb_t  proc_req_cb ;               /**< USB Host process request callback. Refer to proc_req_callback() in usb_host.c */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        void  * proc_req_cb_arg ;                       /**< USB Host process request callback argument */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        enum_event_cb_t  enum_event_cb ;               /**< Enumeration driver event callback */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        void  * enum_event_cb_arg ;                     /**< Enumeration driver event callback argument */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# if ENABLE_ENUM_FILTER_CALLBACK 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        usb_host_enum_filter_cb_t  enum_filter_cb ;    /**< Set device configuration callback */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        void  * enum_filter_cb_arg ;                    /**< Set device configuration callback argument */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif  // ENABLE_ENUM_FILTER_CALLBACK
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  constant ;                                      /**< Constant members. Do not change after installation thus do not require a critical section or mutex */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}  enum_driver_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  enum_driver_t  * p_enum_driver  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  portMUX_TYPE  enum_driver_lock  =  portMUX_INITIALIZER_UNLOCKED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								const  char  * ENUM_TAG  =  " ENUM " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// ---------------------------- Helpers ----------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define ENUM_ENTER_CRITICAL()                     portENTER_CRITICAL(&enum_driver_lock) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define ENUM_EXIT_CRITICAL()                      portEXIT_CRITICAL(&enum_driver_lock) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define ENUM_CHECK(cond, ret_val) ({                                        \ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ! ( cond ) )  {                                                   \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  ( ret_val ) ;                                            \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }                                                                \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define ENUM_CHECK_FROM_CRIT(cond, ret_val) ({    \ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ! ( cond ) )  {                                   \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ENUM_EXIT_CRITICAL ( ) ;              \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  ret_val ;                              \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }                                                \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// ------------------------ Private functions ----------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  inline  uint8_t  get_next_dev_addr ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  ret  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > dynamic . next_dev_addr + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( p_enum_driver - > dynamic . next_dev_addr  >  ENUM_MAX_ADDRESS )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_enum_driver - > dynamic . next_dev_addr  =  ENUM_INIT_VALUE_DEV_ADDR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  p_enum_driver - > dynamic . next_dev_addr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  uint8_t  get_next_free_dev_addr ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_device_handle_t  dev_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  new_dev_addr  =  p_enum_driver - > dynamic . next_dev_addr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    while  ( 1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( usbh_devs_open ( new_dev_addr ,  & dev_hdl )  = =  ESP_ERR_NOT_FOUND )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // We have a device with the same address on a bus, close device and request new addr
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        usbh_dev_close ( dev_hdl ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        new_dev_addr  =  get_next_dev_addr ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Sanity check
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    assert ( new_dev_addr  ! =  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  new_dev_addr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Get  Configuration  descriptor  index 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  For  Configuration  descriptor  bConfigurationValue  and  index  are  not  the  same  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  should  be  different  for  SetConfiguration ( )  and  GetDescriptor ( )  requests . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  GetDescriptor ( ) :  index  from  0  to  one  less  than  the  bNumConfigurations  ( refer  to  section  9.4 .3  Get  Descriptor ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  SetConfiguration ( ) :  bConfigurationValue  field  used  as  a  parameter  to  the  SetConfiguration ( )  request .  ( refer  to  section  9.6 .3  Configuration ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ return  uint8_t 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  inline  uint8_t  get_configuration_descriptor_index ( uint8_t  bConfigurationValue ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ( bConfigurationValue  = =  0 )  ?  bConfigurationValue  :  ( bConfigurationValue  -  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Select  active  configuration 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  During  enumeration  process ,  device  objects  could  have  several  configuration  that  can  be  activated 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  To  be  able  to  select  configuration  this  call  should  be  used 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  This  will  call  the  enumeration  filter  callback  ( if  enabled )  and  set  the  bConfigurationValue  for  the  upcoming  SetConfiguration ( )  command 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ return  esp_err_t 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  select_active_configuration ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // This configuration value must be zero or match a configuration value from a configuration descriptor.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // If the configuration value is zero, the device is placed in its Address state.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // But some devices STALLed get configuration descriptor with bConfigurationValue = 1, even they have one configuration with bValue = 1.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  bConfigurationValue  =  ENUM_DEFAULT_CONFIGURATION_VALUE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# if ENABLE_ENUM_FILTER_CALLBACK 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_device_handle_t  dev_hdl  =  p_enum_driver - > single_thread . dev_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  usb_device_desc_t  * dev_desc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_ERROR_CHECK ( usbh_dev_get_desc ( dev_hdl ,  & dev_desc ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  enum_proceed  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Sanity check
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    assert ( dev_desc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( p_enum_driver - > constant . enum_filter_cb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        enum_proceed  =  p_enum_driver - > constant . enum_filter_cb ( dev_desc ,  & bConfigurationValue ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // User's request NOT to enumerate the USB device
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! enum_proceed )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGW ( ENUM_TAG ,  " [%d:%d] Abort request of enumeration process (%#x:%#x) " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 p_enum_driver - > single_thread . parent_dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 p_enum_driver - > single_thread . parent_port_num , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 dev_desc - > idProduct , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 dev_desc - > idVendor ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        enum_cancel ( p_enum_driver - > single_thread . dev_uid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Set configuration descriptor
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ( bConfigurationValue  = =  0 )  | |  ( bConfigurationValue  >  dev_desc - > bNumConfigurations ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( ENUM_TAG ,  " Invalid bConfigurationValue (%d) provided by user, using default " ,  bConfigurationValue ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        bConfigurationValue  =  ENUM_DEFAULT_CONFIGURATION_VALUE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif  // ENABLE_ENUM_FILTER_CALLBACK
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( ENUM_TAG ,  " Selected bConfigurationValue=%d " ,  bConfigurationValue ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . dev_params . bConfigurationValue  =  bConfigurationValue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  second_reset ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Notify USB Host
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_event_data_t  event_data  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . event  =  ENUM_EVENT_RESET_REQUIRED , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . reset_req  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            . parent_dev_hdl  =  p_enum_driver - > single_thread . parent_dev_hdl , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            . parent_port_num  =  p_enum_driver - > single_thread . parent_port_num , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > constant . enum_event_cb ( & event_data ,  p_enum_driver - > constant . enum_event_cb_arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Get  index  and  langid 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Returns  index  and  langid ,  based  on  enumerator  stage . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ param [ in ]  stage      Stage 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ param [ out ]  index     String  index 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ param [ out ]  langid    String  langid 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  inline  void  get_index_langid_for_stage ( enum_stage_t  stage ,  uint8_t  * index ,  uint16_t  * langid ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( stage )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_LANGID_TABLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_LANGID_TABLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        * index  =  0 ;      // The LANGID table uses an index of 0
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        * langid  =  0 ;     // Getting the LANGID table itself should use a LANGID of 0
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        * index  =  p_enum_driver - > single_thread . dev_params . iManufacturer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        * langid  =  ENUM_LANGID ;   // Use the default LANGID
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        * index  =  p_enum_driver - > single_thread . dev_params . iProduct ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        * langid  =  ENUM_LANGID ;   // Use the default LANGID
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_SER_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_SER_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        * index  =  p_enum_driver - > single_thread . dev_params . iSerialNumber ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        * langid  =  ENUM_LANGID ;   // Use the default LANGID
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Should not occur
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        abort ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Control  request :  General 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Prepares  the  Control  request  byte - data  transfer  for  current  stage  of  the  enumerator 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  control_request_general ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * transfer  =  & p_enum_driver - > constant . urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  ctrl_ep_mps  =  p_enum_driver - > single_thread . dev_params . bMaxPacketSize0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint16_t  wTotalLength  =  p_enum_driver - > single_thread . dev_params . wTotalLength ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  bConfigurationValue  =  p_enum_driver - > single_thread . dev_params . bConfigurationValue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  desc_index  =  get_configuration_descriptor_index ( bConfigurationValue ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( p_enum_driver - > dynamic . stage )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_DEV_DESC :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Initialize a short device descriptor request
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        USB_SETUP_PACKET_INIT_GET_DEVICE_DESC ( ( usb_setup_packet_t  * ) transfer - > data_buffer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ( ( usb_setup_packet_t  * ) transfer - > data_buffer ) - > wLength  =  ENUM_SHORT_DESC_REQ_LEN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        transfer - > num_bytes  =  sizeof ( usb_setup_packet_t )  +  usb_round_up_to_mps ( ENUM_SHORT_DESC_REQ_LEN ,  ctrl_ep_mps ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // IN data stage should return exactly ENUM_SHORT_DESC_REQ_LEN bytes
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_enum_driver - > single_thread . expect_num_bytes  =  sizeof ( usb_setup_packet_t )  +  ENUM_SHORT_DESC_REQ_LEN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_SET_ADDR :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_enum_driver - > single_thread . dev_params . new_dev_addr  =  get_next_free_dev_addr ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        USB_SETUP_PACKET_INIT_SET_ADDR ( ( usb_setup_packet_t  * ) transfer - > data_buffer ,  p_enum_driver - > single_thread . dev_params . new_dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        transfer - > num_bytes  =  sizeof ( usb_setup_packet_t ) ;    // No data stage
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_enum_driver - > single_thread . expect_num_bytes  =  0 ;    // OUT transfer. No need to check number of bytes returned
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_DEV_DESC :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        USB_SETUP_PACKET_INIT_GET_DEVICE_DESC ( ( usb_setup_packet_t  * ) transfer - > data_buffer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        transfer - > num_bytes  =  sizeof ( usb_setup_packet_t )  +  usb_round_up_to_mps ( sizeof ( usb_device_desc_t ) ,  ctrl_ep_mps ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // IN data stage should return exactly sizeof(usb_device_desc_t) bytes
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_enum_driver - > single_thread . expect_num_bytes  =  sizeof ( usb_setup_packet_t )  +  sizeof ( usb_device_desc_t ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_CONFIG_DESC :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Get a short config descriptor at descriptor index
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        USB_SETUP_PACKET_INIT_GET_CONFIG_DESC ( ( usb_setup_packet_t  * ) transfer - > data_buffer ,  desc_index ,  ENUM_SHORT_DESC_REQ_LEN ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        transfer - > num_bytes  =  sizeof ( usb_setup_packet_t )  +  usb_round_up_to_mps ( ENUM_SHORT_DESC_REQ_LEN ,  ctrl_ep_mps ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // IN data stage should return exactly ENUM_SHORT_DESC_REQ_LEN bytes
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_enum_driver - > single_thread . expect_num_bytes  =  sizeof ( usb_setup_packet_t )  +  ENUM_SHORT_DESC_REQ_LEN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_CONFIG_DESC :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Get the full configuration descriptor at descriptor index, requesting its exact length.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        USB_SETUP_PACKET_INIT_GET_CONFIG_DESC ( ( usb_setup_packet_t  * ) transfer - > data_buffer ,  desc_index ,  wTotalLength ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        transfer - > num_bytes  =  sizeof ( usb_setup_packet_t )  +  usb_round_up_to_mps ( wTotalLength ,  ctrl_ep_mps ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // IN data stage should return exactly wTotalLength bytes
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_enum_driver - > single_thread . expect_num_bytes  =  sizeof ( usb_setup_packet_t )  +  wTotalLength ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_SET_CONFIG :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        USB_SETUP_PACKET_INIT_SET_CONFIG ( ( usb_setup_packet_t  * ) transfer - > data_buffer ,  bConfigurationValue ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        transfer - > num_bytes  =  sizeof ( usb_setup_packet_t ) ;    // No data stage
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_enum_driver - > single_thread . expect_num_bytes  =  0 ;     // OUT transfer. No need to check number of bytes returned
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Should never occur
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_enum_driver - > single_thread . expect_num_bytes  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        abort ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Control  request :  String 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Prepares  the  Control  request  string - data  transfer  for  current  stage  of  the  enumerator 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  control_request_string ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * transfer  =  & p_enum_driver - > constant . urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_stage_t  stage  =  p_enum_driver - > dynamic . stage ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-12 21:29:41 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    uint8_t  ctrl_ep_mps  =  p_enum_driver - > single_thread . dev_params . bMaxPacketSize0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  bLength  =  p_enum_driver - > single_thread . dev_params . str_desc_bLength ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  index  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint16_t  langid  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    get_index_langid_for_stage ( stage ,  & index ,  & langid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( stage )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_LANGID_TABLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_SER_STR_DESC :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Get only the header of the string descriptor
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        USB_SETUP_PACKET_INIT_GET_STR_DESC ( ( usb_setup_packet_t  * ) transfer - > data_buffer ,  index ,  langid ,  sizeof ( usb_str_desc_t ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-12 21:29:41 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        transfer - > num_bytes  =  sizeof ( usb_setup_packet_t )  +  usb_round_up_to_mps ( sizeof ( usb_str_desc_t ) ,  ctrl_ep_mps ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        // IN data stage should return exactly sizeof(usb_str_desc_t) bytes
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_enum_driver - > single_thread . expect_num_bytes  =  sizeof ( usb_setup_packet_t )  +  sizeof ( usb_str_desc_t ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_LANGID_TABLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_SER_STR_DESC :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Get the full string descriptor at a particular index, requesting the descriptors exact length
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        USB_SETUP_PACKET_INIT_GET_STR_DESC ( ( usb_setup_packet_t  * ) transfer - > data_buffer ,  index ,  langid ,  bLength ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-12 21:29:41 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        transfer - > num_bytes  =  sizeof ( usb_setup_packet_t )  +  usb_round_up_to_mps ( bLength ,  ctrl_ep_mps ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        // IN data stage should return exactly str_desc_bLength bytes
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_enum_driver - > single_thread . expect_num_bytes  =  sizeof ( usb_setup_packet_t )  +  bLength ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Should never occur
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_enum_driver - > single_thread . expect_num_bytes  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        abort ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Parse  short  Device  descriptor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Parses  short  device  descriptor  response 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Configures  the  EP0  MPS  for  device  object  under  enumeration 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  parse_short_dev_desc ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret  =  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_device_handle_t  dev_hdl  =  p_enum_driver - > single_thread . dev_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * ctrl_xfer  =  & p_enum_driver - > constant . urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  usb_device_desc_t  * dev_desc  =  ( usb_device_desc_t  * ) ( ctrl_xfer - > data_buffer  +  sizeof ( usb_setup_packet_t ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Check if the returned descriptor has correct type
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( dev_desc - > bDescriptorType  ! =  USB_B_DESCRIPTOR_TYPE_DEVICE )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( ENUM_TAG ,  " Short dev desc has wrong bDescriptorType " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_INVALID_RESPONSE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Update and save actual MPS of the default pipe
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  usbh_dev_set_ep0_mps ( dev_hdl ,  dev_desc - > bMaxPacketSize0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( ENUM_TAG ,  " Failed to update MPS " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Save the actual MPS of EP0 in enum driver context
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . dev_params . bMaxPacketSize0  =  dev_desc - > bMaxPacketSize0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								exit : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  check_addr ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_device_handle_t  dev_hdl  =  p_enum_driver - > single_thread . dev_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  assign_addr  =  p_enum_driver - > single_thread . dev_params . new_dev_addr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( ENUM_TAG ,  " Assign address (dev_addr=%d) " ,  assign_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret  =  usbh_dev_set_addr ( dev_hdl ,  assign_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( ENUM_TAG ,  " Error during assign device address " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Parse  full  Device  descriptor  response 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Parses  full  device  descriptor  response 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Set  device  descriptor  for  device  object  under  enumeration 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  parse_full_dev_desc ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret  =  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_device_handle_t  dev_hdl  =  p_enum_driver - > single_thread . dev_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * ctrl_xfer  =  & p_enum_driver - > constant . urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  usb_device_desc_t  * dev_desc  =  ( usb_device_desc_t  * ) ( ctrl_xfer - > data_buffer  +  sizeof ( usb_setup_packet_t ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Check if the returned descriptor has correct type
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( dev_desc - > bDescriptorType  ! =  USB_B_DESCRIPTOR_TYPE_DEVICE )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( ENUM_TAG ,  " Full dev desc has wrong bDescriptorType " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_INVALID_RESPONSE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Save string parameters
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . dev_params . iManufacturer  =  dev_desc - > iManufacturer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . dev_params . iProduct  =  dev_desc - > iProduct ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . dev_params . iSerialNumber  =  dev_desc - > iSerialNumber ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Device has more than one configuration
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( dev_desc - > bNumConfigurations  >  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGW ( ENUM_TAG ,  " Device has more than 1 configuration " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Allocate Device descriptor and set it's value to device object
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  usbh_dev_set_desc ( dev_hdl ,  dev_desc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								exit : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Parse  short  Configuration  descriptor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Parses  short  Configuration  descriptor  response 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Set  the  length  to  request  full  Configuration  descriptor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  parse_short_config_desc ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * ctrl_xfer  =  & p_enum_driver - > constant . urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  usb_config_desc_t  * config_desc  =  ( usb_config_desc_t  * ) ( ctrl_xfer - > data_buffer  +  sizeof ( usb_setup_packet_t ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Check if the returned descriptor is corrupted
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( config_desc - > bDescriptorType  ! =  USB_B_DESCRIPTOR_TYPE_CONFIGURATION )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( ENUM_TAG ,  " Short config desc has wrong bDescriptorType " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_INVALID_RESPONSE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# if (ENUM_CTRL_TRANSFER_MAX_DATA_LEN < UINT16_MAX)   // Suppress -Wtype-limits warning due to uint16_t wTotalLength
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Check if the descriptor is too long to be supported
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( config_desc - > wTotalLength  >  ENUM_CTRL_TRANSFER_MAX_DATA_LEN )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( ENUM_TAG ,  " Configuration descriptor larger than control transfer max length " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_INVALID_SIZE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Set the configuration descriptor's full length
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . dev_params . wTotalLength  =  config_desc - > wTotalLength ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								exit : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Parse  full  Configuration  descriptor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Parses  full  Configuration  descriptor  response 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Set  the  Configuration  descriptor  to  device  object  under  enumeration 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  parse_full_config_desc ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_device_handle_t  dev_hdl  =  p_enum_driver - > single_thread . dev_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * ctrl_xfer  =  & p_enum_driver - > constant . urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  usb_config_desc_t  * config_desc  =  ( usb_config_desc_t  * ) ( ctrl_xfer - > data_buffer  +  sizeof ( usb_setup_packet_t ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Check if the returned descriptor is corrupted
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( config_desc - > bDescriptorType  ! =  USB_B_DESCRIPTOR_TYPE_CONFIGURATION )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( ENUM_TAG ,  " Full config desc has wrong bDescriptorType " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_INVALID_RESPONSE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Allocate Configuration descriptor and set it's value to device object
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  usbh_dev_set_config_desc ( dev_hdl ,  config_desc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								exit : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Parse  short  String  descriptor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Parses  short  String  descriptor  response 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Set  the  length  to  request  full  String  descriptor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  parse_short_str_desc ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * transfer  =  & p_enum_driver - > constant . urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  usb_str_desc_t  * str_desc  =  ( usb_str_desc_t  * ) ( transfer - > data_buffer  +  sizeof ( usb_setup_packet_t ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Check if the returned descriptor is supported or corrupted
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( str_desc - > bDescriptorType  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( ENUM_TAG ,  " String desc not supported " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_NOT_SUPPORTED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  if  ( str_desc - > bDescriptorType  ! =  USB_B_DESCRIPTOR_TYPE_STRING )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( ENUM_TAG ,  " Short string desc corrupt " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_INVALID_RESPONSE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# if (ENUM_CTRL_TRANSFER_MAX_DATA_LEN < UINT8_MAX)    //Suppress -Wtype-limits warning due to uint8_t bLength
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Check if the descriptor is too long to be supported
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( str_desc - > bLength  >  ( uint32_t ) ENUM_CTRL_TRANSFER_MAX_DATA_LEN )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( ENUM_TAG ,  " String descriptor larger than control transfer max length " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_INVALID_SIZE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Set the descriptor's full length
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . dev_params . str_desc_bLength  =  str_desc - > bLength ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								exit : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Parse  Language  ID  table 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Parses  Language  ID  table  response 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Searches  Language  ID  table  for  LangID  =  0x0409 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  parse_langid_table ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * transfer  =  & p_enum_driver - > constant . urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  usb_str_desc_t  * str_desc  =  ( usb_str_desc_t  * ) ( transfer - > data_buffer  +  sizeof ( usb_setup_packet_t ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Scan the LANGID table for our target LANGID
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  ESP_ERR_NOT_FOUND ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  langid_table_num_entries  =  ( str_desc - > bLength  -  sizeof ( usb_str_desc_t ) )  /  2 ;   // Each LANGID is 2 bytes
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  ( int  i  =  0 ;  i  <  langid_table_num_entries ;  i + + )  {   // Each LANGID is 2 bytes
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( str_desc - > wData [ i ]  = =  ENUM_LANGID )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ret  =  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( ENUM_TAG ,  " LANGID %#x not found " ,  ENUM_LANGID ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Get  String  index  number 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Returns  string  number  index  ( 0 ,  1  or  2 )  based  on  stage 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  inline  int  get_str_index ( enum_stage_t  stage ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( stage )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_FULL_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_FULL_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_FULL_SER_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Should never occurred
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    abort ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Parse  full  String  descriptor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Set  String  descriptor  to  the  device  object  under  enumeration 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  parse_full_str_desc ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * transfer  =  & p_enum_driver - > constant . urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_device_handle_t  dev_hdl  =  p_enum_driver - > single_thread . dev_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  usb_str_desc_t  * str_desc  =  ( usb_str_desc_t  * ) ( transfer - > data_buffer  +  sizeof ( usb_setup_packet_t ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_stage_t  stage  =  p_enum_driver - > dynamic . stage ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  usbh_dev_set_str_desc ( dev_hdl ,  str_desc ,  get_str_index ( stage ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  check_config ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Nothing to parse after a SET_CONFIG request
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// ---------------------- Stage handle functions -------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Control  request  stage 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Based  on  the  stage ,  does  prepare  General  or  String  Control  request 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  control_request ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( p_enum_driver - > dynamic . stage )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_DEV_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_SET_ADDR : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_DEV_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_CONFIG_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_CONFIG_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_SET_CONFIG : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        control_request_general ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_LANGID_TABLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_LANGID_TABLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_SER_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_SER_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        control_request_string ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    default :     // Should never occur
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_INVALID_STATE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        abort ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  usbh_dev_submit_ctrl_urb ( p_enum_driver - > single_thread . dev_hdl ,  p_enum_driver - > constant . urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( ENUM_TAG ,  " [%d:%d] Control transfer submit error (%#x), stage '%s' " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 p_enum_driver - > single_thread . parent_dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 p_enum_driver - > single_thread . parent_port_num , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 ret , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 enum_stage_strings [ p_enum_driver - > dynamic . stage ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Control  request  response  handling  stage 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Based  on  the  stage ,  does  parse  the  response  data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  control_response_handling ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret  =  ESP_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Check transfer status
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  expected_num_bytes  =  p_enum_driver - > single_thread . expect_num_bytes ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * ctrl_xfer  =  & p_enum_driver - > constant . urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ctrl_xfer - > status  ! =  USB_TRANSFER_STATUS_COMPLETED )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( ENUM_TAG ,  " Bad transfer status %d: %s " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 ctrl_xfer - > status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 enum_stage_strings [ p_enum_driver - > dynamic . stage ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Check Control IN transfer returned the expected correct number of bytes
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( expected_num_bytes  ! =  0  & &  expected_num_bytes  ! =  ctrl_xfer - > actual_num_bytes )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGW ( ENUM_TAG ,  " [%d:%d] Unexpected (%d) device response length (expected %d) " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 p_enum_driver - > single_thread . parent_dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 p_enum_driver - > single_thread . parent_port_num , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 ctrl_xfer - > actual_num_bytes , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 expected_num_bytes ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ctrl_xfer - > actual_num_bytes  <  expected_num_bytes )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // The device returned less bytes than requested. We cannot continue.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ESP_LOGE ( ENUM_TAG ,  " Device returned less bytes than requested " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ret  =  ESP_ERR_INVALID_SIZE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // The device returned more bytes than requested.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // This violates the USB specs chapter 9.3.5, but we can continue
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( p_enum_driver - > dynamic . stage )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_SHORT_DEV_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  parse_short_dev_desc ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_ADDR : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  check_addr ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_FULL_DEV_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  parse_full_dev_desc ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_SHORT_CONFIG_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  parse_short_config_desc ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_FULL_CONFIG_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  parse_full_config_desc ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_CONFIG : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  check_config ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_SHORT_LANGID_TABLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_SHORT_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_SHORT_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_SHORT_SER_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  parse_short_str_desc ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_FULL_LANGID_TABLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  parse_langid_table ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_FULL_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_FULL_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_FULL_SER_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  parse_full_str_desc ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Should never occurred
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_INVALID_STATE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        abort ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								exit : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Cancel  stage 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Force  shutdown  device  object  under  enumeration 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  stage_cancel ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // There should be device under enumeration
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_device_handle_t  dev_hdl  =  p_enum_driver - > single_thread . dev_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_device_handle_t  parent_dev_hdl  =  p_enum_driver - > single_thread . parent_dev_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  parent_port_num  =  p_enum_driver - > single_thread . parent_port_num ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Close the device
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_ERROR_CHECK ( usbh_dev_enum_unlock ( dev_hdl ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_ERROR_CHECK ( usbh_dev_close ( dev_hdl ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Release device from enumerator
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . dev_uid  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . dev_hdl  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . parent_dev_hdl  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . parent_dev_addr  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . parent_port_num  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > constant . urb - > transfer . context  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > dynamic . flags . processing  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_event_data_t  event_data  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . event  =  ENUM_EVENT_CANCELED , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . canceled  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            . parent_dev_hdl  =  parent_dev_hdl , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            . parent_port_num  =  parent_port_num , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > constant . enum_event_cb ( & event_data ,  p_enum_driver - > constant . enum_event_cb_arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Complete  stage 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Closes  device  object  under  enumeration 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  stage_complete ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_device_handle_t  dev_hdl  =  p_enum_driver - > single_thread . dev_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_device_handle_t  parent_dev_hdl  =  p_enum_driver - > single_thread . parent_dev_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  parent_dev_addr  =  p_enum_driver - > single_thread . parent_dev_addr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  parent_port_num  =  p_enum_driver - > single_thread . parent_port_num ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  dev_addr  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_ERROR_CHECK ( usbh_dev_get_addr ( dev_hdl ,  & dev_addr ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Close device
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_ERROR_CHECK ( usbh_dev_enum_unlock ( dev_hdl ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_ERROR_CHECK ( usbh_dev_close ( dev_hdl ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Release device from enumerator
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . dev_uid  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . dev_hdl  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . parent_dev_hdl  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . parent_dev_addr  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . parent_port_num  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Release device from enumerator
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > constant . urb - > transfer . context  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Flush device params
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    memset ( & p_enum_driver - > single_thread . dev_params ,  0 ,  sizeof ( enum_device_params_t ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . expect_num_bytes  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Increase device address to use new value during the next enumeration process
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    get_next_dev_addr ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > dynamic . flags . processing  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( ENUM_TAG ,  " [%d:%d] Processing complete, new device address %d " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             parent_dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             parent_port_num , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_event_data_t  event_data  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . event  =  ENUM_EVENT_COMPLETED , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . complete  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            . dev_hdl  =  dev_hdl , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            . dev_addr  =  dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            . parent_dev_hdl  =  parent_dev_hdl , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            . parent_port_num  =  parent_port_num , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > constant . enum_event_cb ( & event_data ,  p_enum_driver - > constant . enum_event_cb_arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -------------------------- State Machine ------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Set  next  stage 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Does  set  next  stage ,  based  on  the  successful  completion  of  last  stage 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Some  stages  ( i . e . ,  string  descriptors )  are  skipped  if  the  device  doesn ' t  support  them 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Some  stages  ( i . e .  string  descriptors )  are  allowed  to  fail 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ param [ in ]  last_stage_pass   Flag  of  successful  completion  last  stage 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  set_next_stage ( bool  last_stage_pass ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_stage_t  last_stage  =  p_enum_driver - > dynamic . stage ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_stage_t  next_stage ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    while  ( 1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        bool  stage_skip  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Find the next stage
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( last_stage_pass )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Last stage was successful
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ESP_LOGD ( ENUM_TAG ,  " [%d:%d] %s OK " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                     p_enum_driver - > single_thread . parent_dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                     p_enum_driver - > single_thread . parent_port_num , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                     enum_stage_strings [ last_stage ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Get next stage
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( last_stage  = =  ENUM_STAGE_COMPLETE )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // Complete stage are terminal, move state machine to IDLE
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                next_stage  =  ENUM_STAGE_IDLE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }  else  if  ( last_stage  = =  ENUM_STAGE_CANCEL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // CANCEL can be called anytime, keep the state and handle in the next process callback
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                next_stage  =  last_stage ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // Simply increment to get the next stage
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                next_stage  =  last_stage  +  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ESP_LOGE ( ENUM_TAG ,  " [%d:%d] %s FAILED " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                     p_enum_driver - > single_thread . parent_dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                     p_enum_driver - > single_thread . parent_port_num , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                     enum_stage_strings [ last_stage ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // These stages cannot fail
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            assert ( last_stage  ! =  ENUM_STAGE_SET_ADDR_RECOVERY  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                   last_stage  ! =  ENUM_STAGE_SELECT_CONFIG  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                   last_stage  ! =  ENUM_STAGE_COMPLETE  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                   last_stage  ! =  ENUM_STAGE_CANCEL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Last stage failed
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            switch  ( last_stage )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Stages that are allowed to fail skip to the next appropriate stage
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  ENUM_STAGE_CHECK_SHORT_LANGID_TABLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  ENUM_STAGE_CHECK_FULL_LANGID_TABLE : 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // Couldn't get LANGID, skip the rest of the string descriptors
 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								            case  ENUM_STAGE_CHECK_SHORT_SER_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  ENUM_STAGE_CHECK_FULL_SER_STR_DESC : 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                // iSerialNumber string failed. Jump to Set Configuration and complete enumeration process.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                next_stage  =  ENUM_STAGE_SET_CONFIG ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  ENUM_STAGE_CHECK_SHORT_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  ENUM_STAGE_CHECK_FULL_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // iManufacturer string failed. Get iProduct string next
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                next_stage  =  ENUM_STAGE_GET_SHORT_PROD_STR_DESC ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  ENUM_STAGE_CHECK_SHORT_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  ENUM_STAGE_CHECK_FULL_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // iProduct string failed. Get iSerialNumber string next
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                next_stage  =  ENUM_STAGE_GET_SHORT_SER_STR_DESC ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  ENUM_STAGE_COMPLETE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  ENUM_STAGE_CANCEL : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // These stages should never fail
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                abort ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // Stage is not allowed to failed. Cancel enumeration.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                next_stage  =  ENUM_STAGE_CANCEL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Check if the next stage should be skipped
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        switch  ( next_stage )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  ENUM_STAGE_GET_SHORT_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  ENUM_STAGE_CHECK_SHORT_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  ENUM_STAGE_GET_FULL_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  ENUM_STAGE_CHECK_FULL_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Device doesn't support iManufacturer string
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( p_enum_driver - > single_thread . dev_params . iManufacturer  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ESP_LOGD ( ENUM_TAG ,  " String iManufacturer not set, skip " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                stage_skip  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  ENUM_STAGE_GET_SHORT_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  ENUM_STAGE_CHECK_SHORT_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  ENUM_STAGE_GET_FULL_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  ENUM_STAGE_CHECK_FULL_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Device doesn't support iProduct string
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( p_enum_driver - > single_thread . dev_params . iProduct  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ESP_LOGD ( ENUM_TAG ,  " String iProduct not set, skip " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                stage_skip  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  ENUM_STAGE_GET_SHORT_SER_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  ENUM_STAGE_CHECK_SHORT_SER_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  ENUM_STAGE_GET_FULL_SER_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  ENUM_STAGE_CHECK_FULL_SER_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Device doesn't support iSerialNumber string
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( p_enum_driver - > single_thread . dev_params . iSerialNumber  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ESP_LOGD ( ENUM_TAG ,  " String iSerialNumber not set, skip " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                stage_skip  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( stage_skip )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Loop back around to get the next stage again
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            last_stage  =  next_stage ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > dynamic . stage  =  next_stage ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Control  transfer  completion  callback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Is  called  by  lower  logic  when  transfer  is  completed  with  or  without  error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ param [ in ]  ctrl_xfer  Pointer  to  a  transfer  buffer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  enum_control_transfer_complete ( usb_transfer_t  * ctrl_xfer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Sanity checks
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    assert ( ctrl_xfer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    assert ( ctrl_xfer - > context ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    assert ( p_enum_driver - > single_thread . dev_hdl  = =  ctrl_xfer - > context ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    switch  ( ctrl_xfer - > status )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  USB_TRANSFER_STATUS_COMPLETED : 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOG_BUFFER_HEXDUMP ( ENUM_TAG ,  ctrl_xfer - > data_buffer ,  ctrl_xfer - > actual_num_bytes ,  ESP_LOG_VERBOSE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  process ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  USB_TRANSFER_STATUS_STALL : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Device can STALL some requests if it doesn't have the requested descriptors
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  process ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    default : 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( ENUM_TAG ,  " [%d:%d] Control transfer failed, status=%d " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 p_enum_driver - > single_thread . parent_dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 p_enum_driver - > single_thread . parent_port_num , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 ctrl_xfer - > status ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Cancel enumeration process
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_cancel ( p_enum_driver - > single_thread . dev_uid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								process : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Request processing
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > constant . proc_req_cb ( USB_PROC_REQ_SOURCE_ENUM ,  false ,  p_enum_driver - > constant . proc_req_cb_arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -------------------------- Public API ---------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  enum_install ( enum_config_t  * config ,  void  * * client_ret ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_CHECK_FROM_CRIT ( p_enum_driver  = =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_CHECK ( config  ! =  NULL ,  ESP_ERR_INVALID_ARG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_driver_t  * enum_drv  =  heap_caps_calloc ( 1 ,  sizeof ( enum_driver_t ) ,  MALLOC_CAP_DEFAULT ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_CHECK ( enum_drv ,  ESP_ERR_NO_MEM ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Initialize ENUM objects
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    urb_t  * urb  =  urb_alloc ( sizeof ( usb_setup_packet_t )  +  ENUM_CTRL_TRANSFER_MAX_DATA_LEN ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( urb  = =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_NOT_FINISHED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  alloc_err ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Setup urb
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    urb - > usb_host_client  =  ( void  * )  enum_drv ;    // Client is an address of the enum driver object
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    urb - > transfer . callback  =  enum_control_transfer_complete ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_drv - > constant . urb  =  urb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Save callbacks
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_drv - > constant . proc_req_cb  =  config - > proc_req_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_drv - > constant . proc_req_cb_arg  =  config - > proc_req_cb_arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_drv - > constant . enum_event_cb  =  config - > enum_event_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_drv - > constant . enum_event_cb_arg  =  config - > enum_event_cb_arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# if ENABLE_ENUM_FILTER_CALLBACK 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_drv - > constant . enum_filter_cb  =  config - > enum_filter_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_drv - > constant . enum_filter_cb_arg  =  config - > enum_filter_cb_arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif  // ENABLE_ENUM_FILTER_CALLBACK
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_drv - > dynamic . flags . val  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_drv - > dynamic . stage  =  ENUM_STAGE_IDLE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_drv - > dynamic . next_dev_addr  =  ENUM_INIT_VALUE_DEV_ADDR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( p_enum_driver  ! =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ENUM_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_NOT_FINISHED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  err ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver  =  enum_drv ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Write-back client_ret pointer
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    * client_ret  =  ( void  * ) enum_drv ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								err : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    urb_free ( urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								alloc_err : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    heap_caps_free ( enum_drv ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  enum_uninstall ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_CHECK_FROM_CRIT ( p_enum_driver  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_driver_t  * enum_drv  =  p_enum_driver ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Free resources
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    urb_free ( enum_drv - > constant . urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    heap_caps_free ( enum_drv ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  enum_start ( unsigned  int  uid ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_CHECK_FROM_CRIT ( p_enum_driver  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_CHECK_FROM_CRIT ( p_enum_driver - > dynamic . flags . processing  = =  0 ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret  =  ESP_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Open device and lock it for enumeration process
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_device_handle_t  dev_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  usbh_devs_open ( 0 ,  & dev_hdl ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_ERROR_CHECK ( usbh_dev_enum_lock ( dev_hdl ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Get device info
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_device_info_t  dev_info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  parent_dev_addr  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_ERROR_CHECK ( usbh_dev_get_info ( dev_hdl ,  & dev_info ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( dev_info . parent . dev_hdl )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_ERROR_CHECK ( usbh_dev_get_addr ( dev_info . parent . dev_hdl ,  & parent_dev_addr ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Stage ENUM_STAGE_GET_SHORT_DEV_DESC
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( ENUM_TAG ,  " [%d:%d] Start processing, device address %d " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             parent_dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             dev_info . parent . port_num , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > dynamic . flags . processing  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > dynamic . stage  =  ENUM_STAGE_GET_SHORT_DEV_DESC ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . dev_uid  =  uid ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . dev_hdl  =  dev_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . parent_dev_hdl  =  dev_info . parent . dev_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . parent_dev_addr  =  parent_dev_addr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . parent_port_num  =  dev_info . parent . port_num ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Save device handle to the URB transfer context
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > constant . urb - > transfer . context  =  ( void  * )  dev_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Device params
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    memset ( & p_enum_driver - > single_thread . dev_params ,  0 ,  sizeof ( enum_device_params_t ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > single_thread . dev_params . bMaxPacketSize0  =  ( dev_info . speed  = =  USB_SPEED_LOW ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                                              ?  ENUM_WORST_CASE_MPS_LS 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                                              :  ENUM_WORST_CASE_MPS_FS_HS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Notify USB Host about starting enumeration process
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_event_data_t  event_data  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . event  =  ENUM_EVENT_STARTED , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . started  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            . uid  =  uid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            . parent_dev_hdl  =  dev_info . parent . dev_hdl , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            . parent_port_num  =  dev_info . parent . port_num , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > constant . enum_event_cb ( & event_data ,  p_enum_driver - > constant . enum_event_cb_arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Request processing
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > constant . proc_req_cb ( USB_PROC_REQ_SOURCE_ENUM ,  false ,  p_enum_driver - > constant . proc_req_cb_arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  enum_proceed ( unsigned  int  uid ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_CHECK_FROM_CRIT ( p_enum_driver  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_CHECK_FROM_CRIT ( p_enum_driver - > dynamic . flags . processing  ! =  0 ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Request processing
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > constant . proc_req_cb ( USB_PROC_REQ_SOURCE_ENUM ,  false ,  p_enum_driver - > constant . proc_req_cb_arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  enum_cancel ( unsigned  int  uid ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_stage_t  stage  =  ENUM_STAGE_CANCEL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_CHECK_FROM_CRIT ( p_enum_driver  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_CHECK_FROM_CRIT ( p_enum_driver - > dynamic . flags . processing  ! =  0 ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    stage  =  p_enum_driver - > dynamic . stage ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_enum_driver - > dynamic . stage  =  ENUM_STAGE_CANCEL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGV ( ENUM_TAG ,  " [%d:%d] Cancel at %s " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             p_enum_driver - > single_thread . parent_dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             p_enum_driver - > single_thread . parent_port_num , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             enum_stage_strings [ stage ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Nothing to do more here, will deal with that the very next enum_process()
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  enum_process ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_CHECK_FROM_CRIT ( p_enum_driver  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_CHECK_FROM_CRIT ( p_enum_driver - > dynamic . flags . processing  ! =  0 ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ENUM_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    esp_err_t  res  =  ESP_FAIL ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    bool  need_process_cb  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    enum_stage_t  stage  =  p_enum_driver - > dynamic . stage ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( stage )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Transfer submission stages
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_DEV_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_SET_ADDR : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_DEV_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_CONFIG_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_CONFIG_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_SET_CONFIG : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_LANGID_TABLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_LANGID_TABLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_SHORT_SER_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_GET_FULL_SER_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        need_process_cb  =  false ;  // Do not need to request process callback, as we need to wait transfer completion
 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        res  =  control_request ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Recovery interval
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_SET_ADDR_RECOVERY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Need a short delay before device is ready. Todo: IDF-7007
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        vTaskDelay ( pdMS_TO_TICKS ( SET_ADDR_RECOVERY_INTERVAL_MS ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        res  =  ESP_OK ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Transfer check stages
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_SHORT_DEV_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_ADDR : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_FULL_DEV_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_SHORT_CONFIG_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_FULL_CONFIG_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_CONFIG : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_SHORT_LANGID_TABLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_FULL_LANGID_TABLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_SHORT_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_FULL_MANU_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_SHORT_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_FULL_PROD_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_SHORT_SER_STR_DESC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CHECK_FULL_SER_STR_DESC : 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        res  =  control_response_handling ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_SELECT_CONFIG : 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        res  =  select_active_configuration ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_SECOND_RESET : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        need_process_cb  =  false ;  // We need to wait Hub driver to finish port reset
 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        res  =  second_reset ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_CANCEL : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        need_process_cb  =  false ;  // Terminal state
 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        res  =  stage_cancel ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  ENUM_STAGE_COMPLETE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        need_process_cb  =  false ;  // Terminal state
 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        res  =  stage_complete ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Should never occur
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        abort ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // Set nest stage of enumeration process, based on the stage result
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    set_next_stage ( res  = =  ESP_OK ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Request process callback is necessary
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( need_process_cb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_enum_driver - > constant . proc_req_cb ( USB_PROC_REQ_SOURCE_ENUM ,  false ,  p_enum_driver - > constant . proc_req_cb_arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 15:15:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 21:11:43 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								}