# include  "selfdrive/pandad/panda.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <cassert> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <stdexcept> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <memory> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "common/swaglog.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  libusb_context  * init_usb_ctx ( )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  libusb_context  * context  =  nullptr ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  err  =  libusb_init ( & context ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( err  ! =  0 )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LOGE ( " libusb initialization error " ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  nullptr ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if LIBUSB_API_VERSION >= 0x01000106 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  libusb_set_option ( context ,  LIBUSB_OPTION_LOG_LEVEL ,  LIBUSB_LOG_LEVEL_INFO ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  libusb_set_debug ( context ,  3 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  context ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								PandaUsbHandle : : PandaUsbHandle ( std : : string  serial )  :  PandaCommsHandle ( serial )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // init libusb
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ssize_t  num_devices ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  libusb_device  * * dev_list  =  NULL ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  err  =  0 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ctx  =  init_usb_ctx ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( ! ctx )  {  goto  fail ;  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // connect by serial
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  num_devices  =  libusb_get_device_list ( ctx ,  & dev_list ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( num_devices  <  0 )  {  goto  fail ;  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for  ( size_t  i  =  0 ;  i  <  num_devices ;  + + i )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    libusb_device_descriptor  desc ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    libusb_get_device_descriptor ( dev_list [ i ] ,  & desc ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( desc . idVendor  = =  0xbbaa  & &  desc . idProduct  = =  0xddcc )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      int  ret  =  libusb_open ( dev_list [ i ] ,  & dev_handle ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( dev_handle  = =  NULL  | |  ret  <  0 )  {  goto  fail ;  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      unsigned  char  desc_serial [ 26 ]  =  {  0  } ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ret  =  libusb_get_string_descriptor_ascii ( dev_handle ,  desc . iSerialNumber ,  desc_serial ,  std : : size ( desc_serial ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ret  <  0 )  {  goto  fail ;  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      hw_serial  =  std : : string ( ( char  * ) desc_serial ,  ret ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( serial . empty ( )  | |  serial  = =  hw_serial )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      libusb_close ( dev_handle ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dev_handle  =  NULL ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( dev_handle  = =  NULL )  goto  fail ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  libusb_free_device_list ( dev_list ,  1 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  dev_list  =  nullptr ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( libusb_kernel_driver_active ( dev_handle ,  0 )  = =  1 )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    libusb_detach_kernel_driver ( dev_handle ,  0 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  err  =  libusb_set_configuration ( dev_handle ,  1 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( err  ! =  0 )  {  goto  fail ;  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  err  =  libusb_claim_interface ( dev_handle ,  0 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( err  ! =  0 )  {  goto  fail ;  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								fail : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( dev_list  ! =  NULL )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    libusb_free_device_list ( dev_list ,  1 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  cleanup ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  throw  std : : runtime_error ( " Error connecting to panda " ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								PandaUsbHandle : : ~ PandaUsbHandle ( )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : lock_guard  lk ( hw_lock ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  cleanup ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  connected  =  false ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  PandaUsbHandle : : cleanup ( )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( dev_handle )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    libusb_release_interface ( dev_handle ,  0 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    libusb_close ( dev_handle ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( ctx )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    libusb_exit ( ctx ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								std : : vector < std : : string >  PandaUsbHandle : : list ( )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  std : : unique_ptr < libusb_context ,  decltype ( & libusb_exit ) >  context ( init_usb_ctx ( ) ,  libusb_exit ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // init libusb
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ssize_t  num_devices ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  libusb_device  * * dev_list  =  NULL ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : vector < std : : string >  serials ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( ! context )  {  return  serials ;  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  num_devices  =  libusb_get_device_list ( context . get ( ) ,  & dev_list ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( num_devices  <  0 )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LOGE ( " libusb can't get device list " ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    goto  finish ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for  ( size_t  i  =  0 ;  i  <  num_devices ;  + + i )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    libusb_device  * device  =  dev_list [ i ] ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    libusb_device_descriptor  desc ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    libusb_get_device_descriptor ( device ,  & desc ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( desc . idVendor  = =  0xbbaa  & &  desc . idProduct  = =  0xddcc )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      libusb_device_handle  * handle  =  NULL ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      int  ret  =  libusb_open ( device ,  & handle ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ret  <  0 )  {  goto  finish ;  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      unsigned  char  desc_serial [ 26 ]  =  {  0  } ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ret  =  libusb_get_string_descriptor_ascii ( handle ,  desc . iSerialNumber ,  desc_serial ,  std : : size ( desc_serial ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      libusb_close ( handle ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ret  <  0 )  {  goto  finish ;  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      serials . push_back ( std : : string ( ( char  * ) desc_serial ,  ret ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								finish : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( dev_list  ! =  NULL )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    libusb_free_device_list ( dev_list ,  1 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  serials ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  PandaUsbHandle : : handle_usb_issue ( int  err ,  const  char  func [ ] )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  LOGE_100 ( " usb error %d  \" %s \"  in %s " ,  err ,  libusb_strerror ( ( enum  libusb_error ) err ) ,  func ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( err  = =  LIBUSB_ERROR_NO_DEVICE )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LOGE ( " lost connection " ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    connected  =  false ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // TODO: check other errors, is simply retrying okay?
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  PandaUsbHandle : : control_write ( uint8_t  bRequest ,  uint16_t  wValue ,  uint16_t  wIndex ,  unsigned  int  timeout )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  err ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  const  uint8_t  bmRequestType  =  LIBUSB_ENDPOINT_OUT  |  LIBUSB_REQUEST_TYPE_VENDOR  |  LIBUSB_RECIPIENT_DEVICE ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( ! connected )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  LIBUSB_ERROR_NO_DEVICE ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : lock_guard  lk ( hw_lock ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  do  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    err  =  libusb_control_transfer ( dev_handle ,  bmRequestType ,  bRequest ,  wValue ,  wIndex ,  NULL ,  0 ,  timeout ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( err  <  0 )  handle_usb_issue ( err ,  __func__ ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  }  while  ( err  <  0  & &  connected ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  err ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  PandaUsbHandle : : control_read ( uint8_t  bRequest ,  uint16_t  wValue ,  uint16_t  wIndex ,  unsigned  char  * data ,  uint16_t  wLength ,  unsigned  int  timeout )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  err ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  const  uint8_t  bmRequestType  =  LIBUSB_ENDPOINT_IN  |  LIBUSB_REQUEST_TYPE_VENDOR  |  LIBUSB_RECIPIENT_DEVICE ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( ! connected )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  LIBUSB_ERROR_NO_DEVICE ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : lock_guard  lk ( hw_lock ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  do  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    err  =  libusb_control_transfer ( dev_handle ,  bmRequestType ,  bRequest ,  wValue ,  wIndex ,  data ,  wLength ,  timeout ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( err  <  0 )  handle_usb_issue ( err ,  __func__ ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  }  while  ( err  <  0  & &  connected ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  err ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  PandaUsbHandle : : bulk_write ( unsigned  char  endpoint ,  unsigned  char *  data ,  int  length ,  unsigned  int  timeout )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  err ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  transferred  =  0 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( ! connected )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  0 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : lock_guard  lk ( hw_lock ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  do  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Try sending can messages. If the receive buffer on the panda is full it will NAK
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // and libusb will try again. After 5ms, it will time out. We will drop the messages.
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    err  =  libusb_bulk_transfer ( dev_handle ,  endpoint ,  data ,  length ,  & transferred ,  timeout ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( err  = =  LIBUSB_ERROR_TIMEOUT )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      LOGW ( " Transmit buffer full " ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      break ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  if  ( err  ! =  0  | |  length  ! =  transferred )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      handle_usb_issue ( err ,  __func__ ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  }  while  ( err  ! =  0  & &  connected ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  transferred ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  PandaUsbHandle : : bulk_read ( unsigned  char  endpoint ,  unsigned  char *  data ,  int  length ,  unsigned  int  timeout )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  err ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  transferred  =  0 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( ! connected )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  0 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : lock_guard  lk ( hw_lock ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  do  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    err  =  libusb_bulk_transfer ( dev_handle ,  endpoint ,  data ,  length ,  & transferred ,  timeout ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( err  = =  LIBUSB_ERROR_TIMEOUT )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      break ;  // timeout is okay to exit, recv still happened
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  if  ( err  = =  LIBUSB_ERROR_OVERFLOW )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      comms_healthy  =  false ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      LOGE_100 ( " overflow got 0x%x " ,  transferred ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  if  ( err  ! =  0 )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      handle_usb_issue ( err ,  __func__ ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  }  while  ( err  ! =  0  & &  connected ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  transferred ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}