#!/usr/bin/env python3 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# simple boardd wrapper that updates the panda first 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  os 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  usb1 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  time 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  json 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  subprocess 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  typing  import  List ,  NoReturn 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  functools  import  cmp_to_key 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  panda  import  Panda ,  PandaDFU ,  PandaProtocolMismatch ,  FW_PATH 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  common . basedir  import  BASEDIR 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  common . params  import  Params 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  selfdrive . boardd . set_time  import  set_time 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  system . hardware  import  HARDWARE 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  system . swaglog  import  cloudlog 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  get_expected_signature ( panda :  Panda )  - >  bytes : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  try : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    fn  =  os . path . join ( FW_PATH ,  panda . get_mcu_type ( ) . config . app_fn ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  Panda . get_signature_from_firmware ( fn ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  except  Exception : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cloudlog . exception ( " Error computing expected signature " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  b " " 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  read_panda_logs ( panda :  Panda )  - >  None : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  """ 
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Forward  panda  logs  to  the  cloud 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  """ 
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  params  =  Params ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  serial  =  panda . get_usb_serial ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  log_state  =  { } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  try : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    l  =  json . loads ( params . get ( " PandaLogState " ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  k ,  v  in  l . items ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  isinstance ( k ,  str )  and  isinstance ( v ,  int ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        log_state [ k ]  =  v 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  except  ( TypeError ,  json . JSONDecodeError ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cloudlog . exception ( " failed to parse PandaLogState " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  try : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  serial  in  log_state : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      logs  =  panda . get_logs ( last_id = log_state [ serial ] ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      logs  =  panda . get_logs ( get_all = True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # truncate logs to 100 entries if needed 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    MAX_LOGS  =  100 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  len ( logs )  >  MAX_LOGS : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cloudlog . warning ( f " Panda  { serial }  has  { len ( logs ) }  logs, truncating to  { MAX_LOGS } " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      logs  =  logs [ - MAX_LOGS : ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # update log state 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  len ( logs )  >  0 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      log_state [ serial ]  =  logs [ - 1 ] [ " id " ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  log  in  logs : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  log [ ' timestamp ' ]  is  not  None : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        log [ ' timestamp ' ]  =  log [ ' timestamp ' ] . isoformat ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cloudlog . event ( " panda_log " ,  * * log ,  serial = serial ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    params . put ( " PandaLogState " ,  json . dumps ( log_state ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  except  Exception : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cloudlog . exception ( f " Error getting logs for panda  { serial } " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  flash_panda ( panda_serial :  str )  - >  Panda : 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  try : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    panda  =  Panda ( panda_serial ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  except  PandaProtocolMismatch : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cloudlog . warning ( " detected protocol mismatch, reflashing panda " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HARDWARE . recover_internal_panda ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    raise 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  fw_signature  =  get_expected_signature ( panda ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  internal_panda  =  panda . is_internal ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  panda_version  =  " bootstub "  if  panda . bootstub  else  panda . get_version ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  panda_signature  =  b " "  if  panda . bootstub  else  panda . get_signature ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  cloudlog . warning ( f " Panda  { panda_serial }  connected, version:  { panda_version } , signature  { panda_signature . hex ( ) [ : 16 ] } , expected  { fw_signature . hex ( ) [ : 16 ] } " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  panda . bootstub  or  panda_signature  !=  fw_signature : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cloudlog . info ( " Panda firmware out of date, update required " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    panda . flash ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cloudlog . info ( " Done flashing " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  panda . bootstub : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bootstub_version  =  panda . get_version ( ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    cloudlog . info ( f " Flashed firmware not booting, flashing development bootloader.  { bootstub_version =} ,  { internal_panda =} " ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  internal_panda : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      HARDWARE . recover_internal_panda ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    panda . recover ( reset = ( not  internal_panda ) ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    cloudlog . info ( " Done flashing bootstub " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  panda . bootstub : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cloudlog . info ( " Panda still not booting, exiting " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    raise  AssertionError 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  panda_signature  =  panda . get_signature ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  panda_signature  !=  fw_signature : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cloudlog . info ( " Version mismatch after flashing, exiting " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    raise  AssertionError 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  panda 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  panda_sort_cmp ( a :  Panda ,  b :  Panda ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  a_type  =  a . get_type ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  b_type  =  b . get_type ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # make sure the internal one is always first 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  a . is_internal ( )  and  not  b . is_internal ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  - 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  not  a . is_internal ( )  and  b . is_internal ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # sort by hardware type 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  a_type  !=  b_type : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  a_type  <  b_type 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # last resort: sort by serial number 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  a . get_usb_serial ( )  <  b . get_usb_serial ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  main ( )  - >  NoReturn : 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  count  =  0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  first_run  =  True 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  params  =  Params ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  while  True : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    try : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      count  + =  1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cloudlog . event ( " pandad.flash_and_connect " ,  count = count ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      params . remove ( " PandaSignatures " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      # Flash all Pandas in DFU mode 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      dfu_serials  =  PandaDFU . list ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  len ( dfu_serials )  >  0 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  serial  in  dfu_serials : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          cloudlog . info ( f " Panda in DFU mode found, flashing recovery  { serial } " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          PandaDFU ( serial ) . recover ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        time . sleep ( 1 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      panda_serials  =  Panda . list ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  len ( panda_serials )  ==  0 : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  first_run : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								          cloudlog . info ( " No pandas found, resetting internal panda " ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								          HARDWARE . reset_internal_panda ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          time . sleep ( 2 )   # wait to come back up 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        continue 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cloudlog . info ( f " { len ( panda_serials ) }  panda(s) found, connecting -  { panda_serials } " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      # Flash pandas 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      pandas :  List [ Panda ]  =  [ ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      for  serial  in  panda_serials : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        pandas . append ( flash_panda ( serial ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      # Ensure internal panda is present if expected 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      internal_pandas  =  [ panda  for  panda  in  pandas  if  panda . is_internal ( ) ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  HARDWARE . has_internal_panda ( )  and  len ( internal_pandas )  ==  0 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        cloudlog . error ( " Internal panda is missing, resetting " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        HARDWARE . reset_internal_panda ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        time . sleep ( 2 )   # wait to come back up 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        continue 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      # sort pandas to have deterministic order 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      pandas . sort ( key = cmp_to_key ( panda_sort_cmp ) ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      panda_serials  =  list ( map ( lambda  p :  p . get_usb_serial ( ) ,  pandas ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      # log panda fw versions 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      params . put ( " PandaSignatures " ,  b ' , ' . join ( p . get_signature ( )  for  p  in  pandas ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      for  panda  in  pandas : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # check health for lost heartbeat 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        health  =  panda . health ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  health [ " heartbeat_lost " ] : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          params . put_bool ( " PandaHeartbeatLost " ,  True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          cloudlog . event ( " heartbeat lost " ,  deviceState = health ,  serial = panda . get_usb_serial ( ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								        read_panda_logs ( panda ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  first_run : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								          if  panda . is_internal ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # update time from RTC 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            set_time ( cloudlog ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          # reset panda to ensure we're in a good state 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								          cloudlog . info ( f " Resetting panda  { panda . get_usb_serial ( ) } " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  panda . is_internal ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            HARDWARE . reset_internal_panda ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            panda . reset ( reconnect = False ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      for  p  in  pandas : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        p . close ( ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # TODO: wrap all panda exceptions in a base panda exception 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    except  ( usb1 . USBErrorNoDevice ,  usb1 . USBErrorPipe ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      # a panda was disconnected while setting everything up. let's try again 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cloudlog . exception ( " Panda USB exception while setting up " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      continue 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    except  PandaProtocolMismatch : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cloudlog . exception ( " pandad.protocol_mismatch " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      continue 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    except  Exception : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cloudlog . exception ( " pandad.uncaught_exception " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      continue 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    first_run  =  False 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # run boardd with all connected serials as arguments 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    os . environ [ ' MANAGER_DAEMON ' ]  =  ' boardd ' 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    os . chdir ( os . path . join ( BASEDIR ,  " selfdrive/boardd " ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    subprocess . run ( [ " ./boardd " ,  * panda_serials ] ,  check = True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if  __name__  ==  " __main__ " : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  main ( )