#!/usr/bin/env python3 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  os 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  sys 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  common . basedir  import  BASEDIR 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  selfdrive . car . fingerprints  import  IGNORED_FINGERPRINTS 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# messages reserved for CAN based ignition (see can_ignition_hook function in panda/board/drivers/can) 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# (addr, len) 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								CAN_IGNITION_MSGS  =  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ' gm ' :  [ ( 0x1F1 ,  8 ) ,  ( 0x160 ,  5 ) ] , 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  #'tesla' : [(0x348, 8)], 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  _get_fingerprints ( ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # read all the folders in selfdrive/car and return a dict where: 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # - keys are all the car names that which we have a fingerprint dict for 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # - values are dicts of fingeprints for each trim 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  fingerprints  =  { } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for  car_folder  in  [ x [ 0 ]  for  x  in  os . walk ( BASEDIR  +  ' /selfdrive/car ' ) ] : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    car_name  =  car_folder . split ( ' / ' ) [ - 1 ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    try : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      fingerprints [ car_name ]  =  __import__ ( ' selfdrive.car. %s .values '  %  car_name ,  fromlist = [ ' FINGERPRINTS ' ] ) . FINGERPRINTS 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    except  ( ImportError ,  IOError ,  AttributeError ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      pass 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  fingerprints 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  check_fingerprint_consistency ( f1 ,  f2 ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # return false if it finds a fingerprint fully included in another 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # max message worth checking is 1800, as above that they usually come too infrequently and not 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # usable for fingerprinting 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  max_msg  =  1800 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  is_f1_in_f2  =  True 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for  k  in  f1 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( k  not  in  f2  or  f1 [ k ]  !=  f2 [ k ] )  and  k  <  max_msg : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       is_f1_in_f2  =  False 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  is_f2_in_f1  =  True 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for  k  in  f2 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( k  not  in  f1  or  f2 [ k ]  !=  f1 [ k ] )  and  k  <  max_msg : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       is_f2_in_f1  =  False 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  not  is_f1_in_f2  and  not  is_f2_in_f1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  check_can_ignition_conflicts ( fingerprints ,  brands ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # loops through all the fingerprints and exits if CAN ignition dedicated messages 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # are found in unexpected fingerprints 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for  brand_can ,  msgs_can  in  CAN_IGNITION_MSGS . items ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  i ,  f  in  enumerate ( fingerprints ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      for  msg_can  in  msgs_can : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  brand_can  !=  brands [ i ]  and  msg_can [ 0 ]  in  f  and  msg_can [ 1 ]  ==  f [ msg_can [ 0 ] ] : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          print ( " CAN ignition dedicated msg  %d  with len  %d  found in  %s  fingerprints! "  %  ( msg_can [ 0 ] ,  msg_can [ 1 ] ,  brands [ i ] ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          print ( " TEST FAILED " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          sys . exit ( 1 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								fingerprints  =  _get_fingerprints ( ) 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								fingerprints_flat  =  [ ] 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								car_names  =  [ ] 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								brand_names  =  [ ] 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								for  brand  in  fingerprints : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for  car  in  fingerprints [ brand ] : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  car  in  IGNORED_FINGERPRINTS : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      continue 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    fingerprints_flat  + =  fingerprints [ brand ] [ car ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  i  in  range ( len ( fingerprints [ brand ] [ car ] ) ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      car_names . append ( car ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      brand_names . append ( brand ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# first check if CAN ignition specific messages are unexpectedly included in other fingerprints 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								check_can_ignition_conflicts ( fingerprints_flat ,  brand_names ) 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								valid  =  True 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								for  idx1 ,  f1  in  enumerate ( fingerprints_flat ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for  idx2 ,  f2  in  enumerate ( fingerprints_flat ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  idx1  <  idx2  and  not  check_fingerprint_consistency ( f1 ,  f2 ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      valid  =  False 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      print ( " Those two fingerprints are inconsistent  {0}   {1} " . format ( car_names [ idx1 ] ,  car_names [ idx2 ] ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      print ( " " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      print ( ' ,  ' . join ( " %d :  %d "  %  v  for  v  in  sorted ( f1 . items ( ) ) ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      print ( " " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      print ( ' ,  ' . join ( " %d :  %d "  %  v  for  v  in  sorted ( f2 . items ( ) ) ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      print ( " " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								print ( " Found  {0}  individual fingerprints " . format ( len ( fingerprints_flat ) ) ) 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if  not  valid  or  len ( fingerprints_flat )  ==  0 : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  print ( " TEST FAILED " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  sys . exit ( 1 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								else : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  print ( " TEST SUCESSFUL " )