2021-10-25 21:42:09 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/*
 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-18 02:07:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  SPDX - FileCopyrightText :  2020 - 2022  Espressif  Systems  ( Shanghai )  CO  LTD 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-25 21:42:09 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  SPDX - License - Identifier :  Apache - 2.0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <stddef.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <stdint.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <string.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-02 17:57:50 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  "sdkconfig.h" 
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  "hal/usbh_hal.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "hal/usbh_ll.h" 
 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-19 10:53:21 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  "hal/assert.h" 
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// ------------------------------------------------ Macros and Types ---------------------------------------------------
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// ---------------------- Constants ------------------------
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-05 20:51:25 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# define BENDPOINTADDRESS_NUM_MSK     0x0F    //Endpoint number mask of the bEndpointAddress field of an endpoint descriptor
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define BENDPOINTADDRESS_DIR_MSK     0x80    //Endpoint direction mask of the bEndpointAddress field of an endpoint descriptor
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# define CORE_REG_GSNPSID    0x4F54400A 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define CORE_REG_GHWCFG1    0x00000000 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define CORE_REG_GHWCFG2    0x224DD930 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define CORE_REG_GHWCFG3    0x00C804B5 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define CORE_REG_GHWCFG4    0xD3F0A030 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// -------------------- Configurable -----------------------
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  The  following  core  interrupts  will  be  enabled  ( listed  LSB  to  MSB ) .  Some  of  these 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  interrupts  are  enabled  later  than  others . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  USB_LL_INTR_CORE_PRTINT 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  USB_LL_INTR_CORE_HCHINT 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  USB_LL_INTR_CORE_DISCONNINT 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  The  following  PORT  interrupts  cannot  be  masked ,  listed  LSB  to  MSB 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  USBH_LL_INTR_HPRT_PRTCONNDET 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  USBH_LL_INTR_HPRT_PRTENCHNG 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  USBH_LL_INTR_HPRT_PRTOVRCURRCHNG 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define CORE_INTRS_EN_MSK   (USB_LL_INTR_CORE_DISCONNINT) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//Interrupts that pertain to core events
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define CORE_EVENTS_INTRS_MSK (USB_LL_INTR_CORE_DISCONNINT | \ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                               USB_LL_INTR_CORE_HCHINT ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//Interrupt that pertain to host port events
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define PORT_EVENTS_INTRS_MSK (USBH_LL_INTR_HPRT_PRTCONNDET | \ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                               USBH_LL_INTR_HPRT_PRTENCHNG  |  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                               USBH_LL_INTR_HPRT_PRTOVRCURRCHNG ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/**
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  The  following  channel  interrupt  bits  are  currently  checked  ( in  order  LSB  to  MSB ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  USBH_LL_INTR_CHAN_XFERCOMPL 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  USBH_LL_INTR_CHAN_CHHLTD 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  USBH_LL_INTR_CHAN_STALL 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  USBH_LL_INTR_CHAN_BBLEER 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  USBH_LL_INTR_CHAN_BNAINTR 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  USBH_LL_INTR_CHAN_XCS_XACT_ERR 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-09 10:29:01 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  Note  the  following  points  about  channel  interrupts : 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								 *  -  Not  all  bits  are  unmaskable  under  scatter / gather 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  Those  bits  proxy  their  interrupt  through  the  USBH_LL_INTR_CHAN_CHHLTD  bit 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  -  USBH_LL_INTR_CHAN_XCS_XACT_ERR  is  always  unmasked 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-09 10:29:01 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  -  When  USBH_LL_INTR_CHAN_BNAINTR  occurs ,  USBH_LL_INTR_CHAN_CHHLTD  will  NOT . 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-02 17:57:50 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  -  USBH_LL_INTR_CHAN_AHBERR  doesn ' t  actually  ever  happen  on  our  system  ( i . e . ,  ESP32 - S2 ,  ESP32 - S3 ) : 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-09 10:29:01 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *       -  If  the  QTD  list ' s  starting  address  is  an  invalid  address  ( e . g . ,  NULL ) ,  the  core  will  attempt  to  fetch  that 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *         address  for  a  transfer  descriptor  and  probably  gets  all  zeroes .  It  will  interpret  the  zero  as  a  bad  QTD  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *         return  a  USBH_LL_INTR_CHAN_BNAINTR  instead . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *       -  If  the  QTD ' s  buffer  pointer  is  an  invalid  address ,  the  core  will  attempt  to  read / write  data  to / from  that 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *         invalid  buffer  address  with  NO  INDICATION  OF  ERROR .  The  transfer  will  be  acknowledged  and  treated  as 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *         successful .  Bad  buffer  pointers  MUST  BE  CHECKED  FROM  HIGHER  LAYERS  INSTEAD . 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define CHAN_INTRS_EN_MSK   (USBH_LL_INTR_CHAN_XFERCOMPL | \ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                             USBH_LL_INTR_CHAN_CHHLTD  |  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                             USBH_LL_INTR_CHAN_BNAINTR ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-09 10:29:01 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# define CHAN_INTRS_ERROR_MSK  (USBH_LL_INTR_CHAN_STALL | \ 
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								                               USBH_LL_INTR_CHAN_BBLEER  |  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                               USBH_LL_INTR_CHAN_BNAINTR  |  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                               USBH_LL_INTR_CHAN_XCS_XACT_ERR ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// -------------------------------------------------- Core (Global) ----------------------------------------------------
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  set_defaults ( usbh_hal_context_t  * hal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //GAHBCFG register
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_en_dma_mode ( hal - > dev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-02 17:57:50 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# ifdef CONFIG_IDF_TARGET_ESP32S2 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_set_hbstlen ( hal - > dev ,  1 ) ;     //Use INCR AHB burst. See the ESP32-S2 and later chip ERRATA.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# elif CONFIG_IDF_TARGET_ESP32S3 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_set_hbstlen ( hal - > dev ,  0 ) ;     //Do not use USB burst INCR mode for the ESP32-S3, to avoid interference with other peripherals.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    //GUSBCFG register
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_dis_hnp_cap ( hal - > dev ) ;        //Disable HNP
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_dis_srp_cap ( hal - > dev ) ;        //Disable SRP
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Enable interruts
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_dis_intrs ( hal - > dev ,  0xFFFFFFFF ) ;      //Mask all interrupts first
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_en_intrs ( hal - > dev ,  CORE_INTRS_EN_MSK ) ;    //Unmask global interrupts
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_intr_read_and_clear ( hal - > dev ) ;    //Clear interrupts
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_en_global_intr ( hal - > dev ) ;         //Enable interrupt signal
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Enable host mode
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_set_host_mode ( hal - > dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  usbh_hal_init ( usbh_hal_context_t  * hal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Check if a peripheral is alive by reading the core ID registers
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usbh_dev_t  * dev  =  & USBH ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint32_t  core_id  =  usb_ll_get_controller_core_id ( dev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-19 10:53:21 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    HAL_ASSERT ( core_id  = =  CORE_REG_GSNPSID ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ( void )  core_id ;      //Suppress unused variable warning if asserts are disabled
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    //Initialize HAL context
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    memset ( hal ,  0 ,  sizeof ( usbh_hal_context_t ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    hal - > dev  =  dev ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    set_defaults ( hal ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  usbh_hal_deinit ( usbh_hal_context_t  * hal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Disable and clear global interrupt
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_dis_intrs ( hal - > dev ,  0xFFFFFFFF ) ;  //Disable all interrupts
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_intr_read_and_clear ( hal - > dev ) ;    //Clear interrupts
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_dis_global_intr ( hal - > dev ) ;        //Disable interrupt signal
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    hal - > dev  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  usbh_hal_core_soft_reset ( usbh_hal_context_t  * hal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_core_soft_reset ( hal - > dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    while  ( usb_ll_check_core_soft_reset ( hal - > dev ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ;    //Wait until core reset is done
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    while  ( ! usb_ll_check_ahb_idle ( hal - > dev ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ;    //Wait until AHB Master bus is idle before doing any other operations
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Set the default bits
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    set_defaults ( hal ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-09 10:29:01 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    //Clear all the flags and channels
 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    hal - > periodic_frame_list  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    hal - > flags . val  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-09 10:29:01 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    hal - > channels . num_allocd  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    hal - > channels . chan_pend_intrs_msk  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    memset ( hal - > channels . hdls ,  0 ,  sizeof ( usbh_hal_chan_t  * )  *  USBH_HAL_NUM_CHAN ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								void  usbh_hal_set_fifo_size ( usbh_hal_context_t  * hal ,  const  usbh_hal_fifo_config_t  * fifo_config ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-19 10:53:21 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    HAL_ASSERT ( ( fifo_config - > rx_fifo_lines  +  fifo_config - > nptx_fifo_lines  +  fifo_config - > ptx_fifo_lines )  < =  USBH_HAL_FIFO_TOTAL_USABLE_LINES ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    //Check that none of the channels are active
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  ( int  i  =  0 ;  i  <  USBH_HAL_NUM_CHAN ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( hal - > channels . hdls [ i ]  ! =  NULL )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-19 10:53:21 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            HAL_ASSERT ( ! hal - > channels . hdls [ i ] - > flags . active ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Set the new FIFO lengths
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_set_rx_fifo_size ( hal - > dev ,  fifo_config - > rx_fifo_lines ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_set_nptx_fifo_size ( hal - > dev ,  fifo_config - > rx_fifo_lines ,  fifo_config - > nptx_fifo_lines ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usbh_ll_set_ptx_fifo_size ( hal - > dev ,  fifo_config - > rx_fifo_lines  +  fifo_config - > nptx_fifo_lines ,  fifo_config - > ptx_fifo_lines ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Flush the FIFOs
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_flush_nptx_fifo ( hal - > dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_flush_ptx_fifo ( hal - > dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_flush_rx_fifo ( hal - > dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    hal - > flags . fifo_sizes_set  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// ---------------------------------------------------- Host Port ------------------------------------------------------
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  inline  void  debounce_lock_enable ( usbh_hal_context_t  * hal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Disable the hprt (connection) and disconnection interrupts to prevent repeated triggerings
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usb_ll_dis_intrs ( hal - > dev ,  USB_LL_INTR_CORE_PRTINT  |  USB_LL_INTR_CORE_DISCONNINT ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    hal - > flags . dbnc_lock_enabled  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  usbh_hal_port_enable ( usbh_hal_context_t  * hal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-05 20:51:25 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    usb_priv_speed_t  speed  =  usbh_ll_hprt_get_speed ( hal - > dev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    //Host Configuration
 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-09 10:29:01 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    usbh_ll_hcfg_set_defaults ( hal - > dev ,  speed ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    //Configure HFIR
 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-09 10:29:01 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    usbh_ll_hfir_set_defaults ( hal - > dev ,  speed ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// ----------------------------------------------------- Channel -------------------------------------------------------
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// ----------------- Channel Allocation --------------------
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								bool  usbh_hal_chan_alloc ( usbh_hal_context_t  * hal ,  usbh_hal_chan_t  * chan_obj ,  void  * chan_ctx ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-19 10:53:21 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    HAL_ASSERT ( hal - > flags . fifo_sizes_set ) ;   //FIFO sizes should be set befor attempting to allocate a channel
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    //Attempt to allocate channel
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( hal - > channels . num_allocd  = =  USBH_HAL_NUM_CHAN )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  false ;     //Out of free channels
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  chan_idx  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  ( int  i  =  0 ;  i  <  USBH_HAL_NUM_CHAN ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( hal - > channels . hdls [ i ]  = =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            hal - > channels . hdls [ i ]  =  chan_obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            chan_idx  =  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            hal - > channels . num_allocd + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-19 10:53:21 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    HAL_ASSERT ( chan_idx  ! =  - 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    //Initialize channel object
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    memset ( chan_obj ,  0 ,  sizeof ( usbh_hal_chan_t ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    chan_obj - > flags . chan_idx  =  chan_idx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    chan_obj - > regs  =  usbh_ll_get_chan_regs ( hal - > dev ,  chan_idx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    chan_obj - > chan_ctx  =  chan_ctx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Note: EP characteristics configured separately
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Clean and unmask the channel's interrupt
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usbh_ll_chan_intr_read_and_clear ( chan_obj - > regs ) ;             //Clear the interrupt bits for that channel
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usbh_ll_haintmsk_en_chan_intr ( hal - > dev ,  1  < <  chan_obj - > flags . chan_idx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usbh_ll_chan_set_intr_mask ( chan_obj - > regs ,  CHAN_INTRS_EN_MSK ) ;   //Unmask interrupts for this channel
 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-09 10:29:01 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    usbh_ll_chan_set_pid ( chan_obj - > regs ,  0 ) ;         //Set the initial PID to zero
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    usbh_ll_chan_hctsiz_init ( chan_obj - > regs ) ;        //Set the non changing parts of the HCTSIZ registers (e.g., do_ping and sched info)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  usbh_hal_chan_free ( usbh_hal_context_t  * hal ,  usbh_hal_chan_t  * chan_obj ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( chan_obj - > type  = =  USB_PRIV_XFER_TYPE_INTR  | |  chan_obj - > type  = =  USB_PRIV_XFER_TYPE_ISOCHRONOUS )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //Unschedule this channel
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  ( int  i  =  0 ;  i  <  hal - > frame_list_len ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            hal - > periodic_frame_list [ i ]  & =  ~ ( 1  < <  chan_obj - > flags . chan_idx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    //Can only free a channel when in the disabled state and descriptor list released
 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-25 21:42:09 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    HAL_ASSERT ( ! chan_obj - > flags . active ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 23:04:19 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    //Disable channel's interrupt
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usbh_ll_haintmsk_dis_chan_intr ( hal - > dev ,  1  < <  chan_obj - > flags . chan_idx ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    //Deallocate channel
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    hal - > channels . hdls [ chan_obj - > flags . chan_idx ]  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    hal - > channels . num_allocd - - ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-19 10:53:21 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    HAL_ASSERT ( hal - > channels . num_allocd  > =  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// ---------------- Channel Configuration ------------------
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								void  usbh_hal_chan_set_ep_char ( usbh_hal_context_t  * hal ,  usbh_hal_chan_t  * chan_obj ,  usbh_hal_ep_char_t  * ep_char ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Cannot change ep_char whilst channel is still active or in error
 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-25 21:42:09 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    HAL_ASSERT ( ! chan_obj - > flags . active ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    //Set the endpoint characteristics of the pipe
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usbh_ll_chan_hcchar_init ( chan_obj - > regs , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                             ep_char - > dev_addr , 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-05 20:51:25 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                             ep_char - > bEndpointAddress  &  BENDPOINTADDRESS_NUM_MSK , 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								                             ep_char - > mps , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                             ep_char - > type , 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-05 20:51:25 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                             ep_char - > bEndpointAddress  &  BENDPOINTADDRESS_DIR_MSK , 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-09 10:29:01 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                             ep_char - > ls_via_fs_hub ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    //Save channel type
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    chan_obj - > type  =  ep_char - > type ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //If this is a periodic endpoint/channel, set its schedule in the frame list
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ep_char - > type  = =  USB_PRIV_XFER_TYPE_ISOCHRONOUS  | |  ep_char - > type  = =  USB_PRIV_XFER_TYPE_INTR )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-19 10:53:21 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        HAL_ASSERT ( ( int ) ep_char - > periodic . interval  < =  ( int ) hal - > frame_list_len ) ;     //Interval cannot exceed the length of the frame list
 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        //Find the effective offset in the frame list (in case the phase_offset_frames > interval)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        int  offset  =  ep_char - > periodic . phase_offset_frames  %  ep_char - > periodic . interval ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //Schedule the channel in the frame list
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  ( int  i  =  offset ;  i  <  hal - > frame_list_len ;  i + =  ep_char - > periodic . interval )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            hal - > periodic_frame_list [ i ]  | =  1  < <  chan_obj - > flags . chan_idx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// ------------------- Channel Control ---------------------
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								void  usbh_hal_chan_activate ( usbh_hal_chan_t  * chan_obj ,  void  * xfer_desc_list ,  int  desc_list_len ,  int  start_idx ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    //Cannot activate a channel that has already been enabled or is pending error handling
 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-25 21:42:09 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    HAL_ASSERT ( ! chan_obj - > flags . active ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    //Set start address of the QTD list and starting QTD index
 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    usbh_ll_chan_set_dma_addr_non_iso ( chan_obj - > regs ,  xfer_desc_list ,  start_idx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usbh_ll_chan_set_qtd_list_len ( chan_obj - > regs ,  desc_list_len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usbh_ll_chan_start ( chan_obj - > regs ) ;  //Start the channel
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    chan_obj - > flags . active  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								bool  usbh_hal_chan_request_halt ( usbh_hal_chan_t  * chan_obj ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Cannot request halt on a channel that is pending error handling
 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-24 23:20:50 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( usbh_ll_chan_is_active ( chan_obj - > regs ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-25 21:42:09 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        //If the register indicates that the channel is still active, the active flag must have been previously set
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        HAL_ASSERT ( chan_obj - > flags . active ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        usbh_ll_chan_halt ( chan_obj - > regs ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        chan_obj - > flags . halt_requested  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-24 23:20:50 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-25 21:42:09 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        //We just clear the active flag here as it could still be set (if we have a pending channel interrupt)
 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-24 23:20:50 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        chan_obj - > flags . active  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  true ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// ------------------------------------------------- Event Handling ----------------------------------------------------
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								usbh_hal_port_event_t  usbh_hal_decode_intr ( usbh_hal_context_t  * hal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint32_t  intrs_core  =  usb_ll_intr_read_and_clear ( hal - > dev ) ;   //Read and clear core interrupts
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint32_t  intrs_port  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( intrs_core  &  USB_LL_INTR_CORE_PRTINT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //There are host port interrupts. Read and clear those as well.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        intrs_port  =  usbh_ll_hprt_intr_read_and_clear ( hal - > dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Note: Do not change order of checks. Regressing events (e.g. enable -> disabled, connected -> connected)
 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-24 23:20:50 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    //always take precedence. ENABLED < DISABLED < CONN < DISCONN < OVRCUR
 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-09 10:29:01 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    usbh_hal_port_event_t  event  =  USBH_HAL_PORT_EVENT_NONE ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Check if this is a core or port event
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ( intrs_core  &  CORE_EVENTS_INTRS_MSK )  | |  ( intrs_port  &  PORT_EVENTS_INTRS_MSK ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //Do not change the order of the following checks. Some events/interrupts take precedence over others
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( intrs_core  &  USB_LL_INTR_CORE_DISCONNINT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            event  =  USBH_HAL_PORT_EVENT_DISCONN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            debounce_lock_enable ( hal ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            //Mask the port connection and disconnection interrupts to prevent repeated triggering
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  if  ( intrs_port  &  USBH_LL_INTR_HPRT_PRTOVRCURRCHNG )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            //Check if this is an overcurrent or an overcurrent cleared
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( usbh_ll_hprt_get_port_overcur ( hal - > dev ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                event  =  USBH_HAL_PORT_EVENT_OVRCUR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                event  =  USBH_HAL_PORT_EVENT_OVRCUR_CLR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  if  ( intrs_port  &  USBH_LL_INTR_HPRT_PRTENCHNG )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( usbh_ll_hprt_get_port_en ( hal - > dev ) )  {    //Host port was enabled
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                event  =  USBH_HAL_PORT_EVENT_ENABLED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }  else  {     //Host port has been disabled
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                event  =  USBH_HAL_PORT_EVENT_DISABLED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  if  ( intrs_port  &  USBH_LL_INTR_HPRT_PRTCONNDET  & &  ! hal - > flags . dbnc_lock_enabled )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            event  =  USBH_HAL_PORT_EVENT_CONN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            debounce_lock_enable ( hal ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-24 23:20:50 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    //Port events always take precedence over channel events
 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-09 10:29:01 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( event  = =  USBH_HAL_PORT_EVENT_NONE  & &  ( intrs_core  &  USB_LL_INTR_CORE_HCHINT ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        //One or more channels have pending interrupts. Store the mask of those channels
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        hal - > channels . chan_pend_intrs_msk  =  usbh_ll_get_chan_intrs_msk ( hal - > dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        event  =  USBH_HAL_PORT_EVENT_CHAN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  event ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								usbh_hal_chan_t  * usbh_hal_get_chan_pending_intr ( usbh_hal_context_t  * hal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  chan_num  =  __builtin_ffs ( hal - > channels . chan_pend_intrs_msk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( chan_num )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        hal - > channels . chan_pend_intrs_msk  & =  ~ ( 1  < <  ( chan_num  -  1 ) ) ;       //Clear the pending bit for that channel
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  hal - > channels . hdls [ chan_num  -  1 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								usbh_hal_chan_event_t  usbh_hal_chan_decode_intr ( usbh_hal_chan_t  * chan_obj ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint32_t  chan_intrs  =  usbh_ll_chan_intr_read_and_clear ( chan_obj - > regs ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    usbh_hal_chan_event_t  chan_event ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-25 21:42:09 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    //Note: We don't assert on (chan_obj->flags.active) here as it could have been already cleared by usbh_hal_chan_request_halt()
 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( chan_intrs  &  CHAN_INTRS_ERROR_MSK )  {     //Note: Errors are uncommon, so we check against the entire interrupt mask to reduce frequency of entering this call path
 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-19 10:53:21 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        HAL_ASSERT ( chan_intrs  &  USBH_LL_INTR_CHAN_CHHLTD ) ;   //An error should have halted the channel
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        //Store the error in hal context
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        usbh_hal_chan_error_t  error ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-09 10:29:01 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( chan_intrs  &  USBH_LL_INTR_CHAN_STALL )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								            error  =  USBH_HAL_CHAN_ERROR_STALL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  if  ( chan_intrs  &  USBH_LL_INTR_CHAN_BBLEER )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            error  =  USBH_HAL_CHAN_ERROR_PKT_BBL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  if  ( chan_intrs  &  USBH_LL_INTR_CHAN_BNAINTR )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            error  =  USBH_HAL_CHAN_ERROR_BNA ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  {     //USBH_LL_INTR_CHAN_XCS_XACT_ERR
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            error  =  USBH_HAL_CHAN_ERROR_XCS_XACT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //Update flags
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        chan_obj - > error  =  error ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        chan_obj - > flags . active  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        //Save the error to be handled later
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        chan_event  =  USBH_HAL_CHAN_EVENT_ERROR ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    }  else  if  ( chan_intrs  &  USBH_LL_INTR_CHAN_CHHLTD )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( chan_obj - > flags . halt_requested )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            chan_obj - > flags . halt_requested  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            chan_event  =  USBH_HAL_CHAN_EVENT_HALT_REQ ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        }  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            //Must have been halted due to QTD HOC
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            chan_event  =  USBH_HAL_CHAN_EVENT_CPLT ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        chan_obj - > flags . active  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  if  ( chan_intrs  &  USBH_LL_INTR_CHAN_XFERCOMPL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        A  transfer  complete  interrupt  WITHOUT  the  channel  halting  only  occurs  when  receiving  a  short  interrupt  IN  packet 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        and  the  underlying  QTD  does  not  have  the  HOC  bit  set .  This  signifies  the  last  packet  of  the  Interrupt  transfer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        as  all  interrupt  packets  must  MPS  sized  except  the  last . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //The channel isn't halted yet, so we need to halt it manually to stop the execution of the next QTD/packet
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        usbh_ll_chan_halt ( chan_obj - > regs ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        After  setting  the  halt  bit ,  this  will  generate  another  channel  halted  interrupt .  We  treat  this  interrupt  as 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        a  NONE  event ,  then  cycle  back  with  the  channel  halted  interrupt  to  handle  the  CPLT  event . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        chan_event  =  USBH_HAL_CHAN_EVENT_NONE ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-11 20:50:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        abort ( ) ;     //Should never reach this point
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-28 18:42:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  chan_event ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}