2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  SPDX - FileCopyrightText :  2024  Espressif  Systems  ( Shanghai )  CO  LTD 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  SPDX - License - Identifier :  Apache - 2.0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <string.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <stdint.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 12:06:16 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  "sdkconfig.h" 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  "esp_err.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "esp_log.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "esp_heap_caps.h" 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-07 13:51:09 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  "esp_private/critical_section.h" 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  "usb_private.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "ext_hub.h" 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 12:06:16 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  "ext_port.h" 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  "usb/usb_helpers.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# define EXT_HUB_MAX_STATUS_BYTES_SIZE               (sizeof(uint32_t)) 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# define EXT_HUB_STATUS_CHANGE_FLAG                  (1 << 0) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define EXT_HUB_STATUS_PORT1_CHANGE_FLAG            (1 << 1) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define EXT_HUB_CTRL_TRANSFER_MAX_DATA_LEN          CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Device  state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Global  state  of  the  Device 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								typedef  enum  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_STATE_ATTACHED ,                          /**< Device attached, but not state is unknown (no: Hub Descriptor, Device status and Hub status) */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_STATE_CONFIGURED ,                        /**< Device attached and configured (has Hub Descriptor, Device status and Hub status were requested )*/ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_STATE_SUSPENDED ,                         /**< Device suspended */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_STATE_FAILED                             /**< Device has internal error */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}  ext_hub_state_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Device  stages 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  During  the  lifecycle ,  Hub  requires  different  actions .  To  implement  interaction  with  external  Hub  the  FSM ,  based  on  these  stages  is  using . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Entry : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  Every  new  attached  external  Hub  should  start  from  EXT_HUB_STAGE_GET_HUB_DESCRIPTOR .  Without  Fetching  Hub  Descriptor ,  device  is  not  configured  and  doesn ' t  have  any  ports . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  After  handling  the  response  during  EXT_HUB_STAGE_CHECK_HUB_DESCRIPTOR ,  the  External  Hub  Driver  configures  the  Device  according  to  the  data  from  Hub  Descriptor . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  After  completion  of  any  stage ,  the  Device  does  back  to  the  IDLE  stage  and  waits  for  another  request .  Source  of  the  request  could  be :  EP1  INT  callback  ( the  Hub  or  Ports  changes )  or  external  call . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  Stages ,  that  don ' t  required  response  handling  could  not  end  up  with  fail . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								typedef  enum  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Device in IDLE state
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_STAGE_IDLE  =  0 ,                          /**< Device in idle state and do not fulfill any actions  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Stages, required response handling
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_STAGE_GET_DEVICE_STATUS ,                 /**< Device requests Device Status. For more details, refer to 9.4.5 Get Status of usb_20 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_STAGE_CHECK_DEVICE_STATUS ,               /**< Device received the Device Status and required its' handling */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_STAGE_GET_HUB_DESCRIPTOR ,                /**< Device requests Hub Descriptor. For more details, refer to 11.24.2.5 Get Hub Descriptor of usb_20 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_STAGE_CHECK_HUB_DESCRIPTOR ,              /**< Device received the Hub Descriptor and requires its' handling  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_STAGE_GET_HUB_STATUS ,                    /**< Device requests Hub Status. For more details, refer to 11.24.2.6 Get Hub Status of usb_20 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_STAGE_CHECK_HUB_STATUS ,                  /**< Device received the Hub Status and requires its' handling  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Stages, don't required response handling
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_STAGE_PORT_FEATURE ,                      /**< Device completed the Port Feature class-specific request (Set Feature or Clear Feature). For more details, refer to 11.24.2 Class-specific Requests of usb_20 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_STAGE_PORT_STATUS_REQUEST ,               /**< Device completed the Port Get Status class-specific request. For more details, refer to 11.24.2 Class-specific Requests of usb_20 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_STAGE_FAILURE                            /**< Device has internal error and requires handling */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}  ext_hub_stage_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								const  char  * const  ext_hub_stage_strings [ ]  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " IDLE " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " GET_DEVICE_STATUS " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " CHECK_DEVICE_STATUS " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " GET_HUB_DESCRIPTOR " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " CHECK_HUB_DESCRIPTOR " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " GET_HUB_STATUS " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " CHECK_HUB_STATUS " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " PORT_FEATURE " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " PORT_STATUS_REQUEST " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " FAILURE " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  Device  action  flags 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								typedef  enum  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    DEV_ACTION_EP0_COMPLETE              =  ( 1  < <  1 ) ,   /**< Device complete one of stages, requires handling */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    DEV_ACTION_EP1_FLUSH                 =  ( 1  < <  2 ) ,   /**< Device's Interrupt EP needs to be flushed */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    DEV_ACTION_EP1_DEQUEUE               =  ( 1  < <  3 ) ,   /**< Device's Interrupt EP needs to be dequeued */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    DEV_ACTION_EP1_CLEAR                 =  ( 1  < <  4 ) ,   /**< Device's Interrupt EP needs to be cleared */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    DEV_ACTION_REQ                       =  ( 1  < <  5 ) ,   /**< Device has new actions and required handling */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    DEV_ACTION_ERROR                     =  ( 1  < <  6 ) ,   /**< Device encounters an error */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    DEV_ACTION_GONE                      =  ( 1  < <  7 ) ,   /**< Device was gone */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    DEV_ACTION_RELEASE                   =  ( 1  < <  8 ) ,   /**< Device was released */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    DEV_ACTION_FREE                      =  ( 1  < <  9 ) ,   /**< Device should be freed */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}  dev_action_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								typedef  struct  ext_hub_s  ext_hub_dev_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ brief  External  Hub  device  configuration  parameters  for  device  allocation 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								typedef  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_device_handle_t  dev_hdl ;         /**< Device's handle */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  dev_addr ;                    /**< Device's bus address */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  usb_intf_desc_t  * iface_desc ;   /**< Device's Interface Descriptor pointer */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  usb_ep_desc_t  * ep_in_desc ;     /**< Device's IN Endpoint Descriptor pointer */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}  device_config_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								struct  ext_hub_s  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        TAILQ_ENTRY ( ext_hub_s )  tailq_entry ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        union  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                uint32_t  in_pending_list :  1 ;         /**< Device is in pending list */ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                uint32_t  waiting_release :  1 ;         /**< Device waiting to be released */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                uint32_t  waiting_children :  1 ;        /**< Device is waiting children to be freed */ 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								                uint32_t  waiting_free :  1 ;            /**< Device waiting to be freed */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                uint32_t  is_gone :  1 ;                 /**< Device is gone */ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                uint32_t  reserved27 :  27 ;             /**< Reserved */ 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								            } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            uint32_t  val ;                            /**< Device's flags value */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  flags ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        uint32_t  action_flags ;                       /**< Device's action flags */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  dynamic ;                                       /**< Dynamic members require a critical section */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ext_hub_stage_t  stage ;                       /**< Device's stage */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        uint8_t  maxchild ;                            /**< Amount of allocated ports. Could be 0 for some Hubs. Is increased when new port is added and decreased when port has been freed. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ext_hub_state_t  state ;                       /**< Device's state */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  single_thread ;                                 /**< Single thread members don't require a critical section, as long as they are never accessed from multiple threads */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // For optimisation & debug only
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        uint8_t  iface_num ;                           /**< Device's bInterfaceNum */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Driver purpose
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        uint8_t  dev_addr ;                            /**< Device's bus address */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        usb_device_handle_t  dev_hdl ;                 /**< Device's handle */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        urb_t  * ctrl_urb ;                             /**< Device's Control pipe transfer URB */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        urb_t  * in_urb ;                               /**< Device's Interrupt pipe URB */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        usbh_ep_handle_t  ep_in_hdl ;                  /**< Device's Interrupt EP handle */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        usb_hub_descriptor_t  * hub_desc ;              /**< Device's Hub descriptor pointer. Could be NULL when not requested */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ext_port_hdl_t  * ports ;                       /**< Flexible array of Ports. Could be NULL, when maxchild is 0 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  constant ;                                      /**< Constant members. Do not change after installation thus do not require a critical section or mutex */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								typedef  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        TAILQ_HEAD ( ext_hubs ,  ext_hub_s )     ext_hubs_tailq ;               /**< Idle tailq */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        TAILQ_HEAD ( ext_hubs_cb ,  ext_hub_s )  ext_hubs_pending_tailq ;       /**< Pending tailq */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  dynamic ;                           /**< Dynamic members require a critical section */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ext_hub_cb_t  proc_req_cb ;                    /**< Process callback  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        void  * proc_req_cb_arg ;                       /**< Process callback argument */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        const  ext_hub_port_driver_t *  port_driver ;    /**< External Port Driver */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  constant ;                          /**< Constant members. Do not change after installation thus do not require a critical section or mutex */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}  ext_hub_driver_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  ext_hub_driver_t  * p_ext_hub_driver  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								const  char  * EXT_HUB_TAG  =  " EXT_HUB " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// ------------------------------- Helpers -------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-10-07 13:51:09 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								DEFINE_CRIT_SECTION_LOCK_STATIC ( ext_hub_driver_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define EXT_HUB_ENTER_CRITICAL()           esp_os_enter_critical(&ext_hub_driver_lock) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define EXT_HUB_EXIT_CRITICAL()            esp_os_exit_critical(&ext_hub_driver_lock) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define EXT_HUB_ENTER_CRITICAL_SAFE()      esp_os_enter_critical_safe(&ext_hub_driver_lock) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define EXT_HUB_EXIT_CRITICAL_SAFE()       esp_os_exit_critical_safe(&ext_hub_driver_lock) 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define EXT_HUB_CHECK(cond, ret_val) ({              \ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ! ( cond ) )  {                                   \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  ( ret_val ) ;                            \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }                                                \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define EXT_HUB_CHECK_FROM_CRIT(cond, ret_val) ({    \ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ! ( cond ) )  {                                   \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                EXT_HUB_EXIT_CRITICAL ( ) ;              \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  ret_val ;                              \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }                                                \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// ----------------------- Forward declaration ---------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  bool  _device_set_actions ( ext_hub_dev_t  * ext_hub_dev ,  uint32_t  action_flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  device_error ( ext_hub_dev_t  * ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  device_status_change_handle ( ext_hub_dev_t  * ext_hub_dev ,  const  uint8_t *  data ,  const  int  length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// ---------------------- Callbacks (implementation) ---------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  bool  interrupt_pipe_cb ( usbh_ep_handle_t  ep_hdl ,  usbh_ep_event_t  ep_event ,  void  * user_arg ,  bool  in_isr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint32_t  action_flags ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * ext_hub_dev  =  ( ext_hub_dev_t  * ) user_arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( ep_event )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  USBH_EP_EVENT_URB_DONE :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // A interrupt transfer completed on EP1's pipe . We need to dequeue it
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        action_flags  =  DEV_ACTION_EP1_DEQUEUE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  USBH_EP_EVENT_ERROR_XFER : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  USBH_EP_EVENT_ERROR_URB_NOT_AVAIL : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  USBH_EP_EVENT_ERROR_OVERFLOW : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // EP1's pipe has encountered an error. We need to retire all URBs, dequeue them, then make the pipe active again
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            action_flags  =  DEV_ACTION_EP1_FLUSH  | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                           DEV_ACTION_EP1_DEQUEUE  | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                           DEV_ACTION_EP1_CLEAR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( in_isr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ESP_EARLY_LOGE ( EXT_HUB_TAG ,  " Device %d EP1 Error " ,  ext_hub_dev - > constant . dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ESP_LOGE ( EXT_HUB_TAG ,  " Device %d EP1 Error " ,  ext_hub_dev - > constant . dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  USBH_EP_EVENT_ERROR_STALL : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // EP1's pipe encountered a "protocol stall". We just need to dequeue URBs then make the pipe active again
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            action_flags  =  DEV_ACTION_EP1_DEQUEUE  |  DEV_ACTION_EP1_CLEAR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( in_isr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ESP_EARLY_LOGE ( EXT_HUB_TAG ,  " Device %d EP1 STALL " ,  ext_hub_dev - > constant . dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ESP_LOGE ( EXT_HUB_TAG ,  " Device %d EP1 STALL " ,  ext_hub_dev - > constant . dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        action_flags  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL_SAFE ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  call_proc_req_cb  =  _device_set_actions ( ext_hub_dev ,  action_flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL_SAFE ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  yield  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( call_proc_req_cb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        yield  =  p_ext_hub_driver - > constant . proc_req_cb ( in_isr ,  p_ext_hub_driver - > constant . proc_req_cb_arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  yield ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  @ 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  control_transfer_complete_cb ( usb_transfer_t  * ctrl_xfer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  call_proc_req_cb  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * ext_hub_dev  =  ( ext_hub_dev_t  * )  ctrl_xfer - > context ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    call_proc_req_cb  =  _device_set_actions ( ext_hub_dev ,  DEV_ACTION_EP0_COMPLETE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( call_proc_req_cb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_ext_hub_driver - > constant . proc_req_cb ( false ,  p_ext_hub_driver - > constant . proc_req_cb_arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  interrupt_transfer_complete_cb ( usb_transfer_t  * intr_xfer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    assert ( intr_xfer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * ext_hub_dev  =  ( ext_hub_dev_t  * ) intr_xfer - > context ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    assert ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( intr_xfer - > status )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  USB_TRANSFER_STATUS_COMPLETED : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOG_BUFFER_HEXDUMP ( EXT_HUB_TAG ,  intr_xfer - > data_buffer ,  intr_xfer - > actual_num_bytes ,  ESP_LOG_VERBOSE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        device_status_change_handle ( ext_hub_dev ,  intr_xfer - > data_buffer ,  intr_xfer - > actual_num_bytes ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  USB_TRANSFER_STATUS_NO_DEVICE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Device was removed, nothing to do
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  USB_TRANSFER_STATUS_CANCELED : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Cancellation due to USB Host uninstall routine
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Any other error
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " [%d] Interrupt transfer failed, status %d " ,  ext_hub_dev - > constant . dev_addr ,  intr_xfer - > status ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        device_error ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// --------------------------- Internal Logic  ---------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  bool  _device_set_actions ( ext_hub_dev_t  * ext_hub_dev ,  uint32_t  action_flags ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    THIS  FUNCTION  MUST  BE  CALLED  FROM  A  CRITICAL  SECTION 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( action_flags  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  call_proc_req_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Check if device is already on the callback list
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! ext_hub_dev - > dynamic . flags . in_pending_list )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Move device form idle device list to callback device list
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        TAILQ_REMOVE ( & p_ext_hub_driver - > dynamic . ext_hubs_tailq ,  ext_hub_dev ,  dynamic . tailq_entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        TAILQ_INSERT_TAIL ( & p_ext_hub_driver - > dynamic . ext_hubs_pending_tailq ,  ext_hub_dev ,  dynamic . tailq_entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ext_hub_dev - > dynamic . action_flags  | =  action_flags ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ext_hub_dev - > dynamic . flags . in_pending_list  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        call_proc_req_cb  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // The device is already on the callback list, thus a processing request is already pending.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ext_hub_dev - > dynamic . action_flags  | =  action_flags ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        call_proc_req_cb  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  call_proc_req_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  device_enable_int_ep ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( EXT_HUB_TAG ,  " [%d] Enable EP IN " ,  ext_hub_dev - > constant . dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret  =  usbh_ep_enqueue_urb ( ext_hub_dev - > constant . ep_in_hdl ,  ext_hub_dev - > constant . in_urb ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " Failed to submit in urb: %s " ,  esp_err_to_name ( ret ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  device_has_changed ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // TODO: IDF-10053 Hub status change handling
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // After getting the IRQ about Hub status change we need to request status
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // device_get_status(ext_hub_dev);
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGW ( EXT_HUB_TAG ,  " Hub status change has not been implemented yet " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    device_enable_int_ep ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								//
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								// Figure 11-22. Hub and Port Status Change Bitmap
 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// Bit     | N | ... | 3 | 2 | 1 | 0 |
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// Value   |1/0| ... |1/0|1/0|1/0|1/0|
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//           |         |   |   |   |
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//           |         |   |   |   +------ Hub change detected
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//           |         |   |   +---------- Port 1 change detected
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//           |         |   +-------------- Port 2 change detected
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//           |         +------------------ Port 3 change detected
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//           |                             ...
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//           +---------------------------- Port N change detected
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								static  void  device_status_change_handle ( ext_hub_dev_t  * ext_hub_dev ,  const  uint8_t *  data ,  const  int  length ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    uint32_t  device_status  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Driver does not support Hubs with EP IN wMaxPacketSize > 4
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    assert ( length  < =  EXT_HUB_MAX_STATUS_BYTES_SIZE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  ( uint32_t  i  =  0 ;  i  <  length ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        device_status  | =  ( uint32_t ) ( data [ i ]  < <  i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( device_status )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // If device has a status change, we will re-trigger back the transfer
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // after all handling will be done
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( device_status  &  EXT_HUB_STATUS_CHANGE_FLAG )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Check device status
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            device_has_changed ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // HINTs:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // - every byte of Data IN has 8 bits of possible port statuses bits: (length * 8)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // - very first bit of status is used for Hub status: (length * 8) - 1
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  ( uint8_t  i  =  0 ;  i  <  ( length  *  8 )  -  1 ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Check ports statuses
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( device_status  &  ( EXT_HUB_STATUS_PORT1_CHANGE_FLAG  < <  i ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                assert ( i  <  ext_hub_dev - > single_thread . maxchild ) ;         // Port should be in range
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                assert ( p_ext_hub_driver - > constant . port_driver ) ;          // Port driver call should be valid
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // Request Port status to handle changes
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                p_ext_hub_driver - > constant . port_driver - > get_status ( ext_hub_dev - > constant . ports [ i ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Device status is 0. Could happen when HS Hub with HS device is connected to HS Hub, connected to FS root port
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Re-trigger transfer right now
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        device_enable_int_ep ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  void  device_error ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  call_proc_req_cb  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    call_proc_req_cb  =  _device_set_actions ( ext_hub_dev ,  DEV_ACTION_ERROR ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( call_proc_req_cb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_ext_hub_driver - > constant . proc_req_cb ( false ,  p_ext_hub_driver - > constant . proc_req_cb_arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  esp_err_t  device_port_new ( ext_hub_dev_t  * ext_hub_dev ,  uint8_t  port_idx ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 12:06:16 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ext_port_config_t  port_config  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . ext_hub_hdl  =  ( ext_hub_handle_t )  ext_hub_dev , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . parent_dev_hdl  =   ext_hub_dev - > constant . dev_hdl , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . parent_port_num  =  port_idx  +  1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . port_power_delay_ms  =  ext_hub_dev - > constant . hub_desc - > bPwrOn2PwrGood  *  2 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    assert ( p_ext_hub_driver - > constant . port_driver ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 12:06:16 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    esp_err_t  ret  =  p_ext_hub_driver - > constant . port_driver - > new  ( & port_config ,  ( void * * )  & ext_hub_dev - > constant . ports [ port_idx ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " [%d:%d] Port allocation error: %s " ,  ext_hub_dev - > constant . dev_addr ,  port_idx  +  1 ,  esp_err_to_name ( ret ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev - > single_thread . maxchild + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								fail : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  device_port_free ( ext_hub_dev_t  * ext_hub_dev ,  uint8_t  port_idx ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( ext_hub_dev - > constant . ports [ port_idx ]  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    bool  call_proc_req_cb  =  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    bool  all_ports_freed  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    assert ( ext_hub_dev - > single_thread . maxchild  ! =  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    assert ( p_ext_hub_driver - > constant . port_driver ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 12:06:16 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    esp_err_t  ret  =  p_ext_hub_driver - > constant . port_driver - > del ( ext_hub_dev - > constant . ports [ port_idx ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " [%d:%d] Unable to free port: %s " ,  ext_hub_dev - > constant . dev_addr ,  port_idx  +  1 ,  esp_err_to_name ( ret ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev - > constant . ports [ port_idx ]  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev - > single_thread . maxchild - - ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ext_hub_dev - > dynamic . flags . is_gone )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        all_ports_freed  =  ( ext_hub_dev - > single_thread . maxchild  = =  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( all_ports_freed )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ext_hub_dev - > dynamic . flags . waiting_children  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ext_hub_dev - > dynamic . flags . waiting_free  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            call_proc_req_cb  =  _device_set_actions ( ext_hub_dev ,  DEV_ACTION_FREE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ext_hub_dev - > dynamic . flags . waiting_children  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // Close the device if all children were freed
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( all_ports_freed )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGD ( EXT_HUB_TAG ,  " [%d] Release USBH device object " ,  ext_hub_dev - > constant . dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_ERROR_CHECK ( usbh_dev_close ( ext_hub_dev - > constant . dev_hdl ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    if  ( call_proc_req_cb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_ext_hub_driver - > constant . proc_req_cb ( false ,  p_ext_hub_driver - > constant . proc_req_cb_arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								exit : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  device_release ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    esp_err_t  ret ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( EXT_HUB_TAG ,  " [%d] Device release " ,  ext_hub_dev - > constant . dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Release IN EP
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_ERROR_CHECK ( usbh_ep_command ( ext_hub_dev - > constant . ep_in_hdl ,  USBH_EP_CMD_HALT ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ext_hub_dev - > dynamic . flags . is_gone  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev - > dynamic . flags . waiting_release  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ext_hub_dev - > single_thread . state  > =  EXT_HUB_STATE_CONFIGURED )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Hub device was configured and has a descriptor
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        assert ( ext_hub_dev - > constant . hub_desc  ! =  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        assert ( p_ext_hub_driver - > constant . port_driver ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Mark all ports as gone
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  ( uint8_t  i  =  0 ;  i  <  ext_hub_dev - > constant . hub_desc - > bNbrPorts ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ext_hub_dev - > constant . ports [ i ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ret  =  p_ext_hub_driver - > constant . port_driver - > gone ( ext_hub_dev - > constant . ports [ i ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( ret  = =  ESP_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    // Port doesn't have a device and can be recycled right now
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    ret  =  device_port_free ( ext_hub_dev ,  i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        // Hub runs into an error state
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        // TODO: IDF-10057 Hub handling error
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                }  else  if  ( ret  = =  ESP_ERR_NOT_FINISHED )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    // Port has a device and will be recycled after USBH device will be released by all clients and freed
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    ESP_LOGE ( EXT_HUB_TAG ,  " [%d:%d] Port is gone " ,  ext_hub_dev - > constant . dev_addr ,  i  +  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    ESP_LOGE ( EXT_HUB_TAG ,  " [%d:%d] Unable to mark port as gone: %s " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                             ext_hub_dev - > constant . dev_addr ,  i  +  1 ,  esp_err_to_name ( ret ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  device_alloc_desc ( ext_hub_dev_t  * ext_hub_hdl ,  const  usb_hub_descriptor_t  * hub_desc ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Allocate memory to store the configuration descriptor
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_hub_descriptor_t  * desc  =  heap_caps_malloc ( hub_desc - > bDescLength ,  MALLOC_CAP_DEFAULT ) ;   // Buffer to copy over full configuration descriptor (wTotalLength)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( desc  = =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  ESP_ERR_NO_MEM ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Copy the hub descriptor
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    memcpy ( desc ,  hub_desc ,  hub_desc - > bDescLength ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Assign the hub descriptor to the device object
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    assert ( ext_hub_hdl - > constant . hub_desc  = =  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_hdl - > constant . hub_desc  =  desc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  device_alloc ( device_config_t  * config ,  ext_hub_dev_t  * * ext_hub_dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    urb_t  * ctrl_urb  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    urb_t  * in_urb  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# if !ENABLE_MULTIPLE_HUBS 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_device_info_t  dev_info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_ERROR_CHECK ( usbh_dev_get_info ( config - > dev_hdl ,  & dev_info ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( dev_info . parent . dev_hdl )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-20 13:33:28 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ESP_LOGW ( EXT_HUB_TAG ,  " Multiple Hubs support disabled, Hub device was not initialized " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_NOT_SUPPORTED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif  // ENABLE_MULTIPLE_HUBS
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * hub_dev  =  heap_caps_calloc ( 1 ,  sizeof ( ext_hub_dev_t ) ,  MALLOC_CAP_DEFAULT ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( hub_dev  = =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " Unable to allocate device " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_NO_MEM ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Allocate Control transfer URB
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ctrl_urb  =  urb_alloc ( sizeof ( usb_setup_packet_t )  +  EXT_HUB_CTRL_TRANSFER_MAX_DATA_LEN ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ctrl_urb  = =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " Unable to allocate Control URB " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_NO_MEM ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  ctrl_urb_fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( config - > ep_in_desc - > wMaxPacketSize  >  EXT_HUB_MAX_STATUS_BYTES_SIZE )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " wMaxPacketSize=%d is not supported " ,  config - > ep_in_desc - > wMaxPacketSize ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_NOT_SUPPORTED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  in_urb_fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    in_urb  =  urb_alloc ( config - > ep_in_desc - > wMaxPacketSize ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Allocate Interrupt transfer URB
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( in_urb  = =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " Unable to allocate Interrupt URB " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =   ESP_ERR_NO_MEM ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  in_urb_fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usbh_ep_handle_t  ep_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usbh_ep_config_t  ep_config  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . bInterfaceNumber  =  config - > iface_desc - > bInterfaceNumber , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . bAlternateSetting  =  config - > iface_desc - > bAlternateSetting , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . bEndpointAddress  =  config - > ep_in_desc - > bEndpointAddress , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . ep_cb  =  interrupt_pipe_cb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . ep_cb_arg  =  ( void  * ) hub_dev , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . context  =  ( void  * ) hub_dev , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  usbh_ep_alloc ( config - > dev_hdl ,  & ep_config ,  & ep_hdl ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " Endpoint allocation failure: %s " ,  esp_err_to_name ( ret ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        goto  ep_fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Configure Control transfer URB
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ctrl_urb - > usb_host_client  =  ( void  * )  p_ext_hub_driver ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ctrl_urb - > transfer . callback  =  control_transfer_complete_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ctrl_urb - > transfer . context  =  ( void  * )  hub_dev ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Client is a memory address of the p_ext_hub_driver driver object
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    in_urb - > usb_host_client  =  ( void  * )  p_ext_hub_driver ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    in_urb - > transfer . callback  =  interrupt_transfer_complete_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    in_urb - > transfer . context  =  ( void  * )  hub_dev ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    in_urb - > transfer . num_bytes  =  config - > ep_in_desc - > wMaxPacketSize ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    hub_dev - > dynamic . flags . val  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    hub_dev - > dynamic . action_flags  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Mutex protected
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    hub_dev - > single_thread . state  =  EXT_HUB_STATE_ATTACHED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Constant members
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    hub_dev - > constant . ep_in_hdl  =  ep_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    hub_dev - > constant . ctrl_urb  =  ctrl_urb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    hub_dev - > constant . in_urb  =  in_urb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    hub_dev - > constant . dev_hdl  =  config - > dev_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    hub_dev - > constant . dev_addr  =  config - > dev_addr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    hub_dev - > constant . iface_num  =  config - > iface_desc - > bInterfaceNumber ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // Single thread members
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    hub_dev - > single_thread . stage  =  EXT_HUB_STAGE_IDLE ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    // We will update number of ports during Hub Descriptor handling stage
 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    hub_dev - > single_thread . maxchild  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TAILQ_INSERT_TAIL ( & p_ext_hub_driver - > dynamic . ext_hubs_tailq ,  hub_dev ,  dynamic . tailq_entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( EXT_HUB_TAG ,  " [%d] New device (iface %d) " ,  config - > dev_addr ,  hub_dev - > constant . iface_num ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    * ext_hub_dev  =  hub_dev ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								ep_fail : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    urb_free ( in_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								in_urb_fail : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    urb_free ( ctrl_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								ctrl_urb_fail : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    heap_caps_free ( hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								fail : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  device_configure ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    esp_err_t  ret ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( ext_hub_dev - > constant . hub_desc  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_hub_descriptor_t  * hub_desc  =  ext_hub_dev - > constant . hub_desc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( EXT_HUB_TAG ,  " [%d] Device configure (iface %d) " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             ext_hub_dev - > constant . dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             ext_hub_dev - > constant . iface_num ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( hub_desc - > wHubCharacteristics . compound )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGD ( EXT_HUB_TAG ,  " \t Compound device " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGD ( EXT_HUB_TAG ,  " \t Standalone HUB " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( EXT_HUB_TAG ,  " \t %d external port%s " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             ext_hub_dev - > constant . hub_desc - > bNbrPorts , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             ( ext_hub_dev - > constant . hub_desc - > bNbrPorts  = =  1 )  ?  " "  :  " s " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( hub_desc - > wHubCharacteristics . power_switching )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  USB_W_HUB_CHARS_PORT_PWR_CTRL_NO : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGD ( EXT_HUB_TAG ,  " \t No power switching (usb 1.0) " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  USB_W_HUB_CHARS_PORT_PWR_CTRL_INDV : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGD ( EXT_HUB_TAG ,  " \t Individual port power switching " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // USB_W_HUB_CHARS_PORT_PWR_CTRL_ALL
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGD ( EXT_HUB_TAG ,  " \t All ports power at once " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( hub_desc - > wHubCharacteristics . ovr_current_protect )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  USB_W_HUB_CHARS_PORT_OVER_CURR_NO : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGD ( EXT_HUB_TAG ,  " \t No over-current protection " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  USB_W_HUB_CHARS_PORT_OVER_CURR_INDV : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGD ( EXT_HUB_TAG ,  " \t Individual port over-current protection " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // USB_W_HUB_CHARS_PORT_OVER_CURR_ALL
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGD ( EXT_HUB_TAG ,  " \t Global over-current protection " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( hub_desc - > wHubCharacteristics . indicator_support )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGD ( EXT_HUB_TAG ,  " \t Port indicators are supported " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( EXT_HUB_TAG ,  " \t Power on to power good time: %dms " ,  hub_desc - > bPwrOn2PwrGood  *  2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( EXT_HUB_TAG ,  " \t Maximum current: %d mA " ,  hub_desc - > bHubContrCurrent ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Create External Port flexible array
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev - > constant . ports  =  heap_caps_calloc ( ext_hub_dev - > constant . hub_desc - > bNbrPorts ,  sizeof ( ext_port_hdl_t ) ,  MALLOC_CAP_DEFAULT ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ext_hub_dev - > constant . ports  = =  NULL )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " Ports list allocation error " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_NO_MEM ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  fail ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Create port and add it to pending list
 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    for  ( uint8_t  i  =  0 ;  i  <  ext_hub_dev - > constant . hub_desc - > bNbrPorts ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ext_hub_dev - > constant . ports [ i ]  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  device_port_new ( ext_hub_dev ,  i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            goto  fail ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ext_hub_dev - > single_thread . state  =  EXT_HUB_STATE_CONFIGURED ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								fail : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Free allocated resources
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  ( uint8_t  i  =  0 ;  i  <  ext_hub_dev - > constant . hub_desc - > bNbrPorts ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ext_hub_dev - > constant . ports [ i ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            device_port_free ( ext_hub_dev ,  i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ext_hub_dev - > constant . ports )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        assert ( ext_hub_dev - > single_thread . maxchild  = =  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        heap_caps_free ( ext_hub_dev - > constant . ports ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  device_free ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    assert ( ext_hub_dev - > single_thread . maxchild  = =  0 ) ;  // All ports should be freed by now
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( EXT_HUB_TAG ,  " [%d] Freeing device " ,  ext_hub_dev - > constant . dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    assert ( ext_hub_dev - > dynamic . flags . waiting_free  = =  1 ) ;  // Hub should await being freed
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev - > dynamic . flags . waiting_free  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TAILQ_REMOVE ( & p_ext_hub_driver - > dynamic . ext_hubs_tailq ,  ext_hub_dev ,  dynamic . tailq_entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ext_hub_dev - > constant . hub_desc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        heap_caps_free ( ext_hub_dev - > constant . hub_desc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ext_hub_dev - > constant . ports )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        heap_caps_free ( ext_hub_dev - > constant . ports ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_ERROR_CHECK ( usbh_ep_free ( ext_hub_dev - > constant . ep_in_hdl ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    urb_free ( ext_hub_dev - > constant . ctrl_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    urb_free ( ext_hub_dev - > constant . in_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    heap_caps_free ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  get_dev_by_hdl ( usb_device_handle_t  dev_hdl ,  ext_hub_dev_t  * * ext_hub_hdl ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret  =  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Go through the Hubs lists to find the hub with the specified device address
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * found_hub  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * hub  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TAILQ_FOREACH ( hub ,  & p_ext_hub_driver - > dynamic . ext_hubs_pending_tailq ,  dynamic . tailq_entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( hub - > constant . dev_hdl  = =  dev_hdl )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            found_hub  =  hub ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TAILQ_FOREACH ( hub ,  & p_ext_hub_driver - > dynamic . ext_hubs_tailq ,  dynamic . tailq_entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( hub - > constant . dev_hdl  = =  dev_hdl )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            found_hub  =  hub ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								exit : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( found_hub  = =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_NOT_FOUND ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    * ext_hub_hdl  =  found_hub ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  get_dev_by_addr ( uint8_t  dev_addr ,  ext_hub_dev_t  * * ext_hub_hdl ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret  =  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Go through the Hubs lists to find the Hub with the specified device address
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * found_hub  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * hub  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TAILQ_FOREACH ( hub ,  & p_ext_hub_driver - > dynamic . ext_hubs_pending_tailq ,  dynamic . tailq_entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( hub - > constant . dev_addr  = =  dev_addr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            found_hub  =  hub ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TAILQ_FOREACH ( hub ,  & p_ext_hub_driver - > dynamic . ext_hubs_tailq ,  dynamic . tailq_entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( hub - > constant . dev_addr  = =  dev_addr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            found_hub  =  hub ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								exit : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( found_hub  = =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_NOT_FOUND ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    * ext_hub_hdl  =  found_hub ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -------------------------- Device handling  ---------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  bool  handle_hub_descriptor ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  pass ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * ctrl_xfer  =  & ext_hub_dev - > constant . ctrl_urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  usb_hub_descriptor_t  * hub_desc  =  ( const  usb_hub_descriptor_t  * ) ( ctrl_xfer - > data_buffer  +  sizeof ( usb_setup_packet_t ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ctrl_xfer - > status  ! =  USB_TRANSFER_STATUS_COMPLETED )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " Bad transfer status %d: stage=%d " ,  ctrl_xfer - > status ,  ext_hub_dev - > single_thread . stage ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOG_BUFFER_HEXDUMP ( EXT_HUB_TAG ,  ctrl_xfer - > data_buffer ,  ctrl_xfer - > actual_num_bytes ,  ESP_LOG_VERBOSE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  device_alloc_desc ( ext_hub_dev ,  hub_desc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pass  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  device_configure ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pass  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pass  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								exit : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  pass ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  bool  handle_device_status ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * ctrl_xfer  =  & ext_hub_dev - > constant . ctrl_urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  usb_device_status_t  * dev_status  =  ( const  usb_device_status_t  * ) ( ctrl_xfer - > data_buffer  +  sizeof ( usb_setup_packet_t ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( EXT_HUB_TAG ,  " [%d] Device status:  " ,  ext_hub_dev - > constant . dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( EXT_HUB_TAG ,  " \t Power: %s " ,  dev_status - > self_powered  ?  " self-powered "  :  " bus-powered " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( EXT_HUB_TAG ,  " \t RemoteWakeup: %s " ,  dev_status - > remote_wakeup  ?  " yes "  :  " no " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( dev_status - > remote_wakeup )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Device in remote_wakeup, we need send command Clear Device Feature: USB_W_VALUE_FEATURE_DEVICE_REMOTE_WAKEUP
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // HEX codes of command: 00 01 01 00 00 00 00 00
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // TODO: IDF-10055 Hub Support remote_wakeup feature
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGW ( EXT_HUB_TAG ,  " Remote Wakeup feature has not been implemented yet " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  bool  handle_hub_status ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * ctrl_xfer  =  & ext_hub_dev - > constant . ctrl_urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  usb_hub_status_t  * hub_status  =  ( const  usb_hub_status_t  * ) ( ctrl_xfer - > data_buffer  +  sizeof ( usb_setup_packet_t ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( EXT_HUB_TAG ,  " [%d] Hub status:  " ,  ext_hub_dev - > constant . dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( EXT_HUB_TAG ,  " \t External power supply: %s " ,  hub_status - > wHubStatus . HUB_LOCAL_POWER  ?  " yes "  :  " no " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( EXT_HUB_TAG ,  " \t Overcurrent: %s " ,  hub_status - > wHubStatus . HUB_OVER_CURRENT  ?  " yes "  :  " no " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( hub_status - > wHubStatus . HUB_OVER_CURRENT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " Device has overcurrent! " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Hub has an overcurrent, we need to disable all port and/or disable parent port
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // TODO: IDF-10056 Hubs overcurrent handling
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGW ( EXT_HUB_TAG ,  " Feature has not been implemented yet " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  void  handle_port_feature ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * ctrl_xfer  =  & ext_hub_dev - > constant . ctrl_urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  port_num  =  USB_SETUP_PACKET_GET_PORT ( ( usb_setup_packet_t  * ) ctrl_xfer - > data_buffer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  port_idx  =  port_num  -  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    assert ( port_idx  <  ext_hub_dev - > constant . hub_desc - > bNbrPorts ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    assert ( p_ext_hub_driver - > constant . port_driver ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_ext_hub_driver - > constant . port_driver - > req_process ( ext_hub_dev - > constant . ports [ port_idx ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  handle_port_status ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * ctrl_xfer  =  & ext_hub_dev - > constant . ctrl_urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  port_num  =  USB_SETUP_PACKET_GET_PORT ( ( usb_setup_packet_t  * ) ctrl_xfer - > data_buffer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  port_idx  =  port_num  -  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  usb_port_status_t  * new_status  =  ( const  usb_port_status_t  * ) ( ctrl_xfer - > data_buffer  +  sizeof ( usb_setup_packet_t ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    assert ( port_idx  <  ext_hub_dev - > constant . hub_desc - > bNbrPorts ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    assert ( p_ext_hub_driver - > constant . port_driver ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_ext_hub_driver - > constant . port_driver - > set_status ( ext_hub_dev - > constant . ports [ port_idx ] ,  new_status ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								static  bool  device_control_request ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * transfer  =  & ext_hub_dev - > constant . ctrl_urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    switch  ( ext_hub_dev - > single_thread . stage )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_GET_DEVICE_STATUS : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        USB_SETUP_PACKET_INIT_GET_STATUS ( ( usb_setup_packet_t  * ) transfer - > data_buffer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        transfer - > num_bytes  =  sizeof ( usb_setup_packet_t )  +  sizeof ( usb_device_status_t ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_GET_HUB_DESCRIPTOR : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        USB_SETUP_PACKET_INIT_GET_HUB_DESCRIPTOR ( ( usb_setup_packet_t  * ) transfer - > data_buffer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        transfer - > num_bytes  =  sizeof ( usb_setup_packet_t )  +  sizeof ( usb_hub_descriptor_t ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_GET_HUB_STATUS : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        USB_SETUP_PACKET_INIT_GET_HUB_STATUS ( ( usb_setup_packet_t  * ) transfer - > data_buffer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        transfer - > num_bytes  =  sizeof ( usb_setup_packet_t )  +  sizeof ( usb_hub_status_t ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Should never occur
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        abort ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  usbh_dev_submit_ctrl_urb ( ext_hub_dev - > constant . dev_hdl ,  ext_hub_dev - > constant . ctrl_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " Failed to submit ctrl urb: %s " ,  esp_err_to_name ( ret ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  bool  device_control_response_handling ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  stage_pass  =  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * ctrl_xfer  =  & ext_hub_dev - > constant . ctrl_urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Check transfer status
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ctrl_xfer - > status  ! =  USB_TRANSFER_STATUS_COMPLETED )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " Control request bad transfer status %d " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 ctrl_xfer - > status ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  stage_pass ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // Transfer completed, verbose data in ESP_LOG_VERBOSE is set
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOG_BUFFER_HEXDUMP ( EXT_HUB_TAG ,  ctrl_xfer - > data_buffer ,  ctrl_xfer - > actual_num_bytes ,  ESP_LOG_VERBOSE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( ext_hub_dev - > single_thread . stage )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_CHECK_DEVICE_STATUS : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        stage_pass  =  handle_device_status ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_CHECK_HUB_DESCRIPTOR : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        stage_pass  =  handle_hub_descriptor ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_CHECK_HUB_STATUS : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        stage_pass  =  handle_hub_status ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_PORT_FEATURE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        handle_port_feature ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        stage_pass  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_PORT_STATUS_REQUEST : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        handle_port_status ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        stage_pass  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Should never occur
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        abort ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  stage_pass ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  bool  stage_need_process ( ext_hub_stage_t  stage ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  need_process_cb  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( stage )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Stages, required control transfer
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_GET_DEVICE_STATUS : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_GET_HUB_DESCRIPTOR : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_GET_HUB_STATUS : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Error stage
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_FAILURE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        need_process_cb  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  need_process_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// return
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// true - next stage requires the processing
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// false - terminal stage
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  bool  device_set_next_stage ( ext_hub_dev_t  * ext_hub_dev ,  bool  last_stage_pass ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ext_hub_stage_t  last_stage  =  ext_hub_dev - > single_thread . stage ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_stage_t  next_stage ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( last_stage_pass )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGD ( EXT_HUB_TAG ,  " Stage %s OK " ,  ext_hub_stage_strings [ last_stage ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( last_stage  = =  EXT_HUB_STAGE_GET_DEVICE_STATUS  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                last_stage  = =  EXT_HUB_STAGE_GET_HUB_DESCRIPTOR  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                last_stage  = =  EXT_HUB_STAGE_GET_HUB_STATUS )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Simply increment to get the next stage
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            next_stage  =  last_stage  +  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Terminal stages, move to IDLE
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            next_stage  =  EXT_HUB_STAGE_IDLE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " Stage %s FAILED " ,  ext_hub_stage_strings [ last_stage ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // These stages cannot fail
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        assert ( last_stage  ! =  EXT_HUB_STAGE_PORT_FEATURE  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								               last_stage  ! =  EXT_HUB_STAGE_PORT_STATUS_REQUEST ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        next_stage  =  EXT_HUB_STAGE_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ext_hub_dev - > single_thread . stage  =  next_stage ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  stage_need_process ( next_stage ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  void  handle_error ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ext_hub_dev - > single_thread . state  =  EXT_HUB_STATE_FAILED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // TODO: IDF-10057 Hub handling error
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGW ( EXT_HUB_TAG ,  " %s has not been implemented yet " ,  __FUNCTION__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  handle_device ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  call_proc_req_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  stage_pass  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // FSM for external Hub
 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    switch  ( ext_hub_dev - > single_thread . stage )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_IDLE : 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 12:06:16 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        stage_pass  =  true ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_GET_DEVICE_STATUS : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_GET_HUB_DESCRIPTOR : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_GET_HUB_STATUS : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        stage_pass  =  device_control_request ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_CHECK_DEVICE_STATUS : 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_CHECK_HUB_DESCRIPTOR : 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_CHECK_HUB_STATUS : 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_PORT_FEATURE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_PORT_STATUS_REQUEST : 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        stage_pass  =  device_control_response_handling ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  EXT_HUB_STAGE_FAILURE : 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        handle_error ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        stage_pass  =  true ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Should never occur
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        abort ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    call_proc_req_cb  =  device_set_next_stage ( ext_hub_dev ,  stage_pass ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( call_proc_req_cb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_ext_hub_driver - > constant . proc_req_cb ( false ,  p_ext_hub_driver - > constant . proc_req_cb_arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  handle_ep1_flush ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_ERROR_CHECK ( usbh_ep_command ( ext_hub_dev - > constant . ep_in_hdl ,  USBH_EP_CMD_HALT ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_ERROR_CHECK ( usbh_ep_command ( ext_hub_dev - > constant . ep_in_hdl ,  USBH_EP_CMD_FLUSH ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  handle_ep1_dequeue ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Dequeue all URBs and run their transfer callback
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( EXT_HUB_TAG ,  " [%d] Interrupt dequeue " ,  ext_hub_dev - > constant . dev_addr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    urb_t  * urb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usbh_ep_dequeue_urb ( ext_hub_dev - > constant . ep_in_hdl ,  & urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    while  ( urb  ! =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Clear the transfer's in-flight flag to indicate the transfer is no longer in-flight
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        urb - > usb_host_inflight  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        urb - > transfer . callback ( & urb - > transfer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        usbh_ep_dequeue_urb ( ext_hub_dev - > constant . ep_in_hdl ,  & urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  handle_ep1_clear ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // We allow the pipe command to fail just in case the pipe becomes invalid mid command
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usbh_ep_command ( ext_hub_dev - > constant . ep_in_hdl ,  USBH_EP_CMD_CLEAR ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  handle_gone ( ext_hub_dev_t  * ext_hub_dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  call_proc_req_cb  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Set the flags
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev - > dynamic . flags . waiting_free  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    call_proc_req_cb  =  _device_set_actions ( ext_hub_dev ,  DEV_ACTION_FREE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( call_proc_req_cb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_ext_hub_driver - > constant . proc_req_cb ( false ,  p_ext_hub_driver - > constant . proc_req_cb_arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// ------------------------------ Driver ---------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  ext_hub_install ( const  ext_hub_config_t  * config ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_driver_t  * ext_hub_drv  =  heap_caps_calloc ( 1 ,  sizeof ( ext_hub_driver_t ) ,  MALLOC_CAP_DEFAULT ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 12:06:16 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ext_hub_drv  = =  NULL )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_NO_MEM ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  err ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    // Save callbacks
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_drv - > constant . proc_req_cb  =  config - > proc_req_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_drv - > constant . proc_req_cb_arg  =  config - > proc_req_cb_arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Copy Port driver pointer
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_drv - > constant . port_driver  =  config - > port_driver ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ext_hub_drv - > constant . port_driver  = =  NULL )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " Port Driver has not been implemented yet " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_NOT_FINISHED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  err ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TAILQ_INIT ( & ext_hub_drv - > dynamic . ext_hubs_tailq ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TAILQ_INIT ( & ext_hub_drv - > dynamic . ext_hubs_pending_tailq ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( p_ext_hub_driver  ! =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_INVALID_STATE ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        goto  err ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_ext_hub_driver  =  ext_hub_drv ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( EXT_HUB_TAG ,  " Driver installed " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								err : 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    heap_caps_free ( ext_hub_drv ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  ext_hub_uninstall ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK_FROM_CRIT ( p_ext_hub_driver  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK_FROM_CRIT ( TAILQ_EMPTY ( & p_ext_hub_driver - > dynamic . ext_hubs_tailq ) ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK_FROM_CRIT ( TAILQ_EMPTY ( & p_ext_hub_driver - > dynamic . ext_hubs_pending_tailq ) ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_driver_t  * ext_hub_drv  =  p_ext_hub_driver ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p_ext_hub_driver  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // Free resources
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    heap_caps_free ( ext_hub_drv ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( EXT_HUB_TAG ,  " Driver uninstalled " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  * ext_hub_get_client ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  driver_installed  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    driver_installed  =  ( p_ext_hub_driver  ! =  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ( driver_installed )  ?  ( void * )  p_ext_hub_driver  :  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -------------------------- External Hub API ---------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  ext_hub_get_handle ( usb_device_handle_t  dev_hdl ,  ext_hub_handle_t  * ext_hub_hdl ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK_FROM_CRIT ( p_ext_hub_driver  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  get_dev_by_hdl ( dev_hdl ,  ext_hub_hdl ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  esp_err_t  find_first_intf_desc ( const  usb_config_desc_t  * config_desc ,  device_config_t  * hub_config ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  iface_found  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  usb_ep_desc_t  * ep_in_desc  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  offset  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  usb_intf_desc_t  * next_intf_desc  =  ( const  usb_intf_desc_t  * ) usb_parse_next_descriptor_of_type ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                                ( const  usb_standard_desc_t  * ) config_desc , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                                config_desc - > wTotalLength , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                                USB_B_DESCRIPTOR_TYPE_INTERFACE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                                & offset ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    while  ( next_intf_desc  ! =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( iface_found )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // TODO: IDF-10058 Hubs support interface selection (HS)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ESP_LOGW ( EXT_HUB_TAG ,  " Device has several Interfaces, selection has not been implemented yet. Using first. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Parse all interfaces
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( USB_CLASS_HUB  = =  next_intf_desc - > bInterfaceClass )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // We have found the first interface descriptor with matching bInterfaceNumber
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( next_intf_desc - > bInterfaceProtocol  ! =  USB_B_DEV_PROTOCOL_HUB_FS )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                // TODO: IDF-10059 Hubs support multiple TT (HS)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( next_intf_desc - > bInterfaceProtocol  ! =  USB_B_DEV_PROTOCOL_HUB_HS_NO_TT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    ESP_LOGW ( EXT_HUB_TAG ,  " Transaction Translator has not been implemented yet " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                switch  ( next_intf_desc - > bInterfaceProtocol )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                case  USB_B_DEV_PROTOCOL_HUB_HS_NO_TT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    ESP_LOGD ( EXT_HUB_TAG ,  " \t No TT " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                case  USB_B_DEV_PROTOCOL_HUB_HS_SINGLE_TT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    ESP_LOGD ( EXT_HUB_TAG ,  " \t Single TT " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                case  USB_B_DEV_PROTOCOL_HUB_HS_MULTI_TT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    ESP_LOGD ( EXT_HUB_TAG ,  " \t Multi TT " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    ESP_LOGE ( EXT_HUB_TAG ,  " \t Interface Protocol (%#x) not supported " ,  next_intf_desc - > bInterfaceProtocol ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    goto  next_iface ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Hub Interface always should have only one Interrupt endpoint
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( next_intf_desc - > bNumEndpoints  ! =  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ESP_LOGE ( EXT_HUB_TAG ,  " Unexpected number of endpoints (%d) " ,  next_intf_desc - > bNumEndpoints ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                goto  next_iface ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Get related IN EP
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ep_in_desc  =  usb_parse_endpoint_descriptor_by_index ( next_intf_desc ,  0 ,  config_desc - > wTotalLength ,  & offset ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ep_in_desc  = =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ESP_LOGE ( EXT_HUB_TAG ,  " EP descriptor not found (iface=%d) " ,  next_intf_desc - > bInterfaceNumber ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                goto  next_iface ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ! USB_EP_DESC_GET_EP_DIR ( ep_in_desc )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    ( USB_EP_DESC_GET_XFERTYPE ( ep_in_desc )  ! =  USB_TRANSFER_TYPE_INTR ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ESP_LOGE ( EXT_HUB_TAG ,  " Interrupt EP not found (iface=%d) " ,  next_intf_desc - > bInterfaceNumber ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                goto  next_iface ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Interface found, fill the config
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            hub_config - > iface_desc  =  next_intf_desc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            hub_config - > ep_in_desc  =  ep_in_desc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            iface_found  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								next_iface : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        next_intf_desc  =  ( const  usb_intf_desc_t  * ) usb_parse_next_descriptor_of_type ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                             ( const  usb_standard_desc_t  * ) next_intf_desc , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                             config_desc - > wTotalLength , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                             USB_B_DESCRIPTOR_TYPE_INTERFACE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                             & offset ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ( iface_found )  ?  ESP_OK  :  ESP_ERR_NOT_FOUND ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  ext_hub_new_dev ( uint8_t  dev_addr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK_FROM_CRIT ( p_ext_hub_driver  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * hub_dev  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_device_handle_t  dev_hdl  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  usb_config_desc_t  * config_desc  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  call_proc_req_cb  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Open device
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  usbh_devs_open ( dev_addr ,  & dev_hdl ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-12 13:32:18 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " USBH device opening error: %s " ,  esp_err_to_name ( ret ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Get Configuration Descriptor
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  usbh_dev_get_config_desc ( dev_hdl ,  & config_desc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-12 13:32:18 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " Getting config desc error %s " ,  esp_err_to_name ( ret ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Find related Hub Interface descriptor
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    device_config_t  hub_config  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . dev_hdl  =  dev_hdl , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . dev_addr  =  dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . iface_desc  =  NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . ep_in_desc  =  NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  find_first_intf_desc ( config_desc ,  & hub_config ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Create External Hub device
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  device_alloc ( & hub_config ,  & hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-12 13:32:18 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " External HUB device alloc error %s " ,  esp_err_to_name ( ret ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    hub_dev - > single_thread . stage  =  EXT_HUB_STAGE_GET_HUB_DESCRIPTOR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    call_proc_req_cb  =  _device_set_actions ( hub_dev ,  DEV_ACTION_REQ ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( call_proc_req_cb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_ext_hub_driver - > constant . proc_req_cb ( false ,  p_ext_hub_driver - > constant . proc_req_cb_arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								exit : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_ERROR_CHECK ( usbh_dev_close ( dev_hdl ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  ext_hub_dev_gone ( uint8_t  dev_addr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK_FROM_CRIT ( p_ext_hub_driver  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * ext_hub_dev  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    bool  in_pending  =  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( dev_addr  ! =  0 ,  ESP_ERR_INVALID_ARG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Find device with dev_addr in the devices TAILQ
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // TODO: IDF-10058
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Release all devices by dev_addr
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  get_dev_by_addr ( dev_addr ,  & ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGD ( EXT_HUB_TAG ,  " No device with address %d was found " ,  dev_addr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        goto  exit ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ESP_LOGD ( EXT_HUB_TAG ,  " [%d] Device gone " ,  ext_hub_dev - > constant . dev_addr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ext_hub_dev - > dynamic . flags . waiting_release  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ext_hub_dev - > dynamic . flags . waiting_children )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // External Hub was already released or waiting children to be freed
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  ESP_ERR_INVALID_STATE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ext_hub_dev - > dynamic . flags . in_pending_list )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        in_pending  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // TODO: IDF-10490
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // test case:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // - detach the external Hub device right before the Hub Descriptor request.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        _device_set_actions ( ext_hub_dev ,  DEV_ACTION_RELEASE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // Device not in pending, can be released immediately
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! in_pending )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        device_release ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								exit : 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  ext_hub_all_free ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  call_proc_req_cb  =  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    bool  wait_for_free  =  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    for  ( int  i  =  0 ;  i  <  2 ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ext_hub_dev_t  * hub_curr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ext_hub_dev_t  * hub_next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Go through pending list first
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( i  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            hub_curr  =  TAILQ_FIRST ( & p_ext_hub_driver - > dynamic . ext_hubs_pending_tailq ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            hub_curr  =  TAILQ_FIRST ( & p_ext_hub_driver - > dynamic . ext_hubs_tailq ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        while  ( hub_curr  ! =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            hub_next  =  TAILQ_NEXT ( hub_curr ,  dynamic . tailq_entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            hub_curr - > dynamic . flags . waiting_release  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            call_proc_req_cb  =  _device_set_actions ( hub_curr ,  DEV_ACTION_RELEASE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // At least one hub should be released
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            wait_for_free  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            hub_curr  =  hub_next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( call_proc_req_cb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_ext_hub_driver - > constant . proc_req_cb ( false ,  p_ext_hub_driver - > constant . proc_req_cb_arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  ( wait_for_free )  ?  ESP_ERR_NOT_FINISHED  :  ESP_OK ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  ext_hub_status_handle_complete ( ext_hub_handle_t  ext_hub_hdl ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( ext_hub_hdl  ! =  NULL ,  ESP_ERR_INVALID_ARG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * ext_hub_dev  =  ( ext_hub_dev_t  * ) ext_hub_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( ext_hub_dev - > single_thread . state  = =  EXT_HUB_STATE_CONFIGURED ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  device_enable_int_ep ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  ext_hub_process ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK_FROM_CRIT ( p_ext_hub_driver  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Keep processing until all device's with pending events have been handled
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    while  ( ! TAILQ_EMPTY ( & p_ext_hub_driver - > dynamic . ext_hubs_pending_tailq ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Move the device back into the idle device list,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ext_hub_dev_t  * ext_hub_dev  =  TAILQ_FIRST ( & p_ext_hub_driver - > dynamic . ext_hubs_pending_tailq ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        TAILQ_REMOVE ( & p_ext_hub_driver - > dynamic . ext_hubs_pending_tailq ,  ext_hub_dev ,  dynamic . tailq_entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        TAILQ_INSERT_TAIL ( & p_ext_hub_driver - > dynamic . ext_hubs_tailq ,  ext_hub_dev ,  dynamic . tailq_entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Clear the device's flags
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        uint32_t  action_flags  =  ext_hub_dev - > dynamic . action_flags ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ext_hub_dev - > dynamic . action_flags  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ext_hub_dev - > dynamic . flags . in_pending_list  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* ---------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Exit  critical  section  to  handle  device  action  flags  in  their  listed  order 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_LOGD ( EXT_HUB_TAG ,  " [%d] Processing actions 0x% " PRIx32 " " ,  ext_hub_dev - > constant . dev_addr ,  action_flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( action_flags  &  DEV_ACTION_REQ  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                action_flags  &  DEV_ACTION_EP0_COMPLETE )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            handle_device ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( action_flags  &  DEV_ACTION_EP1_FLUSH )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            handle_ep1_flush ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( action_flags  &  DEV_ACTION_EP1_DEQUEUE )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            handle_ep1_dequeue ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( action_flags  &  DEV_ACTION_EP1_CLEAR )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            handle_ep1_clear ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( action_flags  &  DEV_ACTION_ERROR )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            handle_error ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( action_flags  &  DEV_ACTION_GONE )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            handle_gone ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( action_flags  &  DEV_ACTION_RELEASE )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            device_release ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( action_flags  &  DEV_ACTION_FREE )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            device_free ( ext_hub_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* ---------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Re - enter  critical  sections .  All  device  action  flags  should  have  been  handled . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// --------------------- External Hub - Device related -------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  ext_hub_get_hub_status ( ext_hub_handle_t  ext_hub_hdl ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK_FROM_CRIT ( p_ext_hub_driver  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( ext_hub_hdl  ! =  NULL ,  ESP_ERR_INVALID_ARG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * ext_hub_dev  =  ( ext_hub_dev_t  * ) ext_hub_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ext_hub_dev - > single_thread . stage  =  EXT_HUB_STAGE_GET_HUB_STATUS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  call_proc_req_cb  =  _device_set_actions ( ext_hub_dev ,  DEV_ACTION_REQ ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( call_proc_req_cb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_ext_hub_driver - > constant . proc_req_cb ( false ,  p_ext_hub_driver - > constant . proc_req_cb_arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  ext_hub_get_status ( ext_hub_handle_t  ext_hub_hdl ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK_FROM_CRIT ( p_ext_hub_driver  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( ext_hub_hdl  ! =  NULL ,  ESP_ERR_INVALID_ARG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * ext_hub_dev  =  ( ext_hub_dev_t  * ) ext_hub_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ext_hub_dev - > single_thread . stage  =  EXT_HUB_STAGE_GET_DEVICE_STATUS ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  call_proc_req_cb  =  _device_set_actions ( ext_hub_dev ,  DEV_ACTION_REQ ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( call_proc_req_cb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p_ext_hub_driver - > constant . proc_req_cb ( false ,  p_ext_hub_driver - > constant . proc_req_cb_arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// --------------------- External Hub - Port related ---------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  ext_hub_port_recycle ( ext_hub_handle_t  ext_hub_hdl ,  uint8_t  port_num ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK_FROM_CRIT ( p_ext_hub_driver  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( ext_hub_hdl  ! =  NULL ,  ESP_ERR_INVALID_ARG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * ext_hub_dev  =  ( ext_hub_dev_t  * ) ext_hub_hdl ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  port_idx  =  port_num  -  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    bool  free_port  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  release_port  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( port_idx  <  ext_hub_dev - > constant . hub_desc - > bNbrPorts ,  ESP_ERR_INVALID_SIZE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( p_ext_hub_driver - > constant . port_driver  ! =  NULL ,  ESP_ERR_NOT_SUPPORTED ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( ext_hub_dev - > single_thread . state  = =  EXT_HUB_STATE_CONFIGURED ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ext_hub_dev - > dynamic . flags . waiting_release )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        release_port  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  if  ( ext_hub_dev - > dynamic . flags . waiting_children )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        assert ( ext_hub_dev - > dynamic . flags . waiting_release  = =  0 ) ;  // Device should be already released
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        assert ( ext_hub_dev - > dynamic . flags . is_gone  = =  1 ) ;          // Device should be gone by now
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        free_port  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! release_port  & &  ! free_port )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Parent still present, recycle the port
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  p_ext_hub_driver - > constant . port_driver - > recycle ( ext_hub_dev - > constant . ports [ port_idx ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ESP_LOGE ( EXT_HUB_TAG ,  " [%d:%d] Unable to recycle the port: %s " ,  ext_hub_dev - > constant . dev_addr ,  port_num ,  esp_err_to_name ( ret ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( release_port )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Notify the port that parent is not available anymore and port should be recycled then freed
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ret  =  p_ext_hub_driver - > constant . port_driver - > gone ( ext_hub_dev - > constant . ports [ port_idx ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ret  = =  ESP_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ESP_LOGD ( EXT_HUB_TAG ,  " [%d:%d] Port doesn't have a device and can be freed right now " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         ext_hub_dev - > constant . dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         port_num ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                assert ( free_port  = =  false ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                free_port  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }  else  if  ( ret  = =  ESP_ERR_NOT_FINISHED )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // Port has a device and will be recycled after USBH device will be released by all clients and freed
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ESP_LOGE ( EXT_HUB_TAG ,  " [%d:%d] Port is gone " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         ext_hub_dev - > constant . dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         port_num ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // Logically, recycling logic are finished for the Hub Driver, return ESP_OK to free the node
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                assert ( free_port  = =  false ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ESP_LOGE ( EXT_HUB_TAG ,  " [%d:%d] Unable to mark port as gone: %s " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         ext_hub_dev - > constant . dev_addr ,  port_num ,  esp_err_to_name ( ret ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( free_port )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ret  =  device_port_free ( ext_hub_dev ,  port_idx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                goto  exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								exit : 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  ext_hub_port_reset ( ext_hub_handle_t  ext_hub_hdl ,  uint8_t  port_num ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK_FROM_CRIT ( p_ext_hub_driver  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( ext_hub_hdl  ! =  NULL ,  ESP_ERR_INVALID_ARG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * ext_hub_dev  =  ( ext_hub_dev_t  * ) ext_hub_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  port_idx  =  port_num  -  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( port_idx  <  ext_hub_dev - > constant . hub_desc - > bNbrPorts ,  ESP_ERR_INVALID_SIZE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( p_ext_hub_driver - > constant . port_driver  ! =  NULL ,  ESP_ERR_NOT_SUPPORTED ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  p_ext_hub_driver - > constant . port_driver - > reset ( ext_hub_dev - > constant . ports [ port_idx ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  ext_hub_port_active ( ext_hub_handle_t  ext_hub_hdl ,  uint8_t  port_num ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK_FROM_CRIT ( p_ext_hub_driver  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( ext_hub_hdl  ! =  NULL ,  ESP_ERR_INVALID_ARG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * ext_hub_dev  =  ( ext_hub_dev_t  * ) ext_hub_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  port_idx  =  port_num  -  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( port_idx  <  ext_hub_dev - > constant . hub_desc - > bNbrPorts ,  ESP_ERR_INVALID_SIZE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( p_ext_hub_driver - > constant . port_driver  ! =  NULL ,  ESP_ERR_NOT_SUPPORTED ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  p_ext_hub_driver - > constant . port_driver - > active ( ext_hub_dev - > constant . ports [ port_idx ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  ext_hub_port_disable ( ext_hub_handle_t  ext_hub_hdl ,  uint8_t  port_num ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK_FROM_CRIT ( p_ext_hub_driver  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( ext_hub_hdl  ! =  NULL ,  ESP_ERR_INVALID_ARG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * ext_hub_dev  =  ( ext_hub_dev_t  * ) ext_hub_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  port_idx  =  port_num  -  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( port_idx  <  ext_hub_dev - > constant . hub_desc - > bNbrPorts ,  ESP_ERR_INVALID_SIZE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( p_ext_hub_driver - > constant . port_driver  ! =  NULL ,  ESP_ERR_NOT_SUPPORTED ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  p_ext_hub_driver - > constant . port_driver - > disable ( ext_hub_dev - > constant . ports [ port_idx ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  ext_hub_port_get_speed ( ext_hub_handle_t  ext_hub_hdl ,  uint8_t  port_num ,  usb_speed_t  * speed ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK_FROM_CRIT ( p_ext_hub_driver  ! =  NULL ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( ext_hub_hdl  ! =  NULL ,  ESP_ERR_INVALID_ARG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * ext_hub_dev  =  ( ext_hub_dev_t  * ) ext_hub_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  port_idx  =  port_num  -  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( port_idx  <  ext_hub_dev - > constant . hub_desc - > bNbrPorts ,  ESP_ERR_INVALID_SIZE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( p_ext_hub_driver - > constant . port_driver  ! =  NULL ,  ESP_ERR_NOT_SUPPORTED ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  p_ext_hub_driver - > constant . port_driver - > get_speed ( ext_hub_dev - > constant . ports [ port_idx ] ,  speed ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// --------------------------- USB Chapter 11 ----------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// -----------------------------------------------------------------------------
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  ext_hub_set_port_feature ( ext_hub_handle_t  ext_hub_hdl ,  uint8_t  port_num ,  uint8_t  feature ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 12:06:16 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK_FROM_CRIT ( p_ext_hub_driver  ! =  NULL ,  ESP_ERR_NOT_ALLOWED ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( ext_hub_hdl  ! =  NULL ,  ESP_ERR_INVALID_ARG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * ext_hub_dev  =  ( ext_hub_dev_t  * ) ext_hub_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * transfer  =  & ext_hub_dev - > constant . ctrl_urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( port_num  ! =  0  & &  port_num  < =  ext_hub_dev - > constant . hub_desc - > bNbrPorts ,  ESP_ERR_INVALID_SIZE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( ext_hub_dev - > single_thread . state  = =  EXT_HUB_STATE_CONFIGURED ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    USB_SETUP_PACKET_INIT_SET_PORT_FEATURE ( ( usb_setup_packet_t  * ) transfer - > data_buffer ,  port_num ,  feature ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    transfer - > num_bytes  =  sizeof ( usb_setup_packet_t ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ext_hub_dev - > single_thread . stage  =  EXT_HUB_STAGE_PORT_FEATURE ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  usbh_dev_submit_ctrl_urb ( ext_hub_dev - > constant . dev_hdl ,  ext_hub_dev - > constant . ctrl_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " [%d:%d] Set port feature %#x, failed to submit ctrl urb: %s " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 ext_hub_dev - > constant . dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 port_num , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 feature , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 esp_err_to_name ( ret ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  ext_hub_clear_port_feature ( ext_hub_handle_t  ext_hub_hdl ,  uint8_t  port_num ,  uint8_t  feature ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 12:06:16 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK_FROM_CRIT ( p_ext_hub_driver  ! =  NULL ,  ESP_ERR_NOT_ALLOWED ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( ext_hub_hdl  ! =  NULL ,  ESP_ERR_INVALID_ARG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * ext_hub_dev  =  ( ext_hub_dev_t  * ) ext_hub_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * transfer  =  & ext_hub_dev - > constant . ctrl_urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( port_num  ! =  0  & &  port_num  < =  ext_hub_dev - > constant . hub_desc - > bNbrPorts ,  ESP_ERR_INVALID_SIZE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( ext_hub_dev - > single_thread . state  = =  EXT_HUB_STATE_CONFIGURED ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    USB_SETUP_PACKET_INIT_CLEAR_PORT_FEATURE ( ( usb_setup_packet_t  * ) transfer - > data_buffer ,  port_num ,  feature ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    transfer - > num_bytes  =  sizeof ( usb_setup_packet_t ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ext_hub_dev - > single_thread . stage  =  EXT_HUB_STAGE_PORT_FEATURE ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  usbh_dev_submit_ctrl_urb ( ext_hub_dev - > constant . dev_hdl ,  ext_hub_dev - > constant . ctrl_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " [%d:%d] Clear port feature %#x, failed to submit ctrl urb: %s " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 ext_hub_dev - > constant . dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 port_num , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 feature , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 esp_err_to_name ( ret ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  ext_hub_get_port_status ( ext_hub_handle_t  ext_hub_hdl ,  uint8_t  port_num ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_ENTER_CRITICAL ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 12:06:16 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK_FROM_CRIT ( p_ext_hub_driver  ! =  NULL ,  ESP_ERR_NOT_ALLOWED ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_EXIT_CRITICAL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_err_t  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( ext_hub_hdl  ! =  NULL ,  ESP_ERR_INVALID_ARG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ext_hub_dev_t  * ext_hub_dev  =  ( ext_hub_dev_t  * ) ext_hub_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_transfer_t  * transfer  =  & ext_hub_dev - > constant . ctrl_urb - > transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( port_num  ! =  0  & &  port_num  < =  ext_hub_dev - > constant . hub_desc - > bNbrPorts ,  ESP_ERR_INVALID_SIZE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    EXT_HUB_CHECK ( ext_hub_dev - > single_thread . state  = =  EXT_HUB_STATE_CONFIGURED ,  ESP_ERR_INVALID_STATE ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    USB_SETUP_PACKET_INIT_GET_PORT_STATUS ( ( usb_setup_packet_t  * ) transfer - > data_buffer ,  port_num ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    transfer - > num_bytes  =  sizeof ( usb_setup_packet_t )  +  sizeof ( usb_port_status_t ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ext_hub_dev - > single_thread . stage  =  EXT_HUB_STAGE_PORT_STATUS_REQUEST ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  usbh_dev_submit_ctrl_urb ( ext_hub_dev - > constant . dev_hdl ,  ext_hub_dev - > constant . ctrl_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  ! =  ESP_OK )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-21 12:57:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ESP_LOGE ( EXT_HUB_TAG ,  " [%d:%d] Get port status, failed to submit ctrl urb: %s " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 ext_hub_dev - > constant . dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 port_num , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 esp_err_to_name ( ret ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-02 14:25:11 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}