@ -5,6 +5,8 @@ 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					# include  <cassert>  
					 
					 
					 
					# include  <cassert>  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					# include  <cmath>  
					 
					 
					 
					# include  <cmath>  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					# include  <cstring>  
					 
					 
					 
					# include  <cstring>  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					# include  <iomanip>  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					# include  <sstream>  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					# include  "common/util.h"  
					 
					 
					 
					# include  "common/util.h"  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					# include  "common/timing.h"  
					 
					 
					 
					# include  "common/timing.h"  
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -28,6 +30,7 @@ struct __attribute__((packed)) spi_header { 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					const  int  SPI_MAX_RETRIES  =  5 ;  
					 
					 
					 
					const  int  SPI_MAX_RETRIES  =  5 ;  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					const  int  SPI_ACK_TIMEOUT  =  50 ;  // milliseconds
  
					 
					 
					 
					const  int  SPI_ACK_TIMEOUT  =  50 ;  // milliseconds
  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					const  std : : string  SPI_DEVICE  =  " /dev/spidev0.0 " ;  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					class  LockEx  {  
					 
					 
					 
					class  LockEx  {  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					public :  
					 
					 
					 
					public :  
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -48,38 +51,56 @@ private: 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					PandaSpiHandle : : PandaSpiHandle ( std : : string  serial )  :  PandaCommsHandle ( serial )  {  
					 
					 
					 
					PandaSpiHandle : : PandaSpiHandle ( std : : string  serial )  :  PandaCommsHandle ( serial )  {  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					  LOGD ( " opening SPI panda: %s " ,  serial . c_str ( ) ) ;   
					 
					 
					 
					  int  ret ;   
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					  const  int  uid_len  =  12 ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					  uint8_t  uid [ uid_len ]  =  { 0 } ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					  int  err ;   
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					  uint32_t  spi_mode  =  SPI_MODE_0 ;   
					 
					 
					 
					  uint32_t  spi_mode  =  SPI_MODE_0 ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					  uint32_t  spi_speed  =  30000000 ;   
					 
					 
					 
					  uint32_t  spi_speed  =  30000000 ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					  uint8_t  spi_bits_per_word  =  8 ;   
					 
					 
					 
					  uint8_t  spi_bits_per_word  =  8 ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					  spi_fd  =  open ( serial . c_str ( ) ,  O_RDWR ) ;   
					 
					 
					 
					  spi_fd  =  open ( SPI_DEVICE . c_str ( ) ,  O_RDWR ) ;   
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					  if  ( spi_fd  <  0 )  {   
					 
					 
					 
					  if  ( spi_fd  <  0 )  {   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    LOGE ( " failed opening SPI device %d " ,  err ) ;   
					 
					 
					 
					    LOGE ( " failed opening SPI device %d " ,  spi_fd ) ;   
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					    goto  fail ;   
					 
					 
					 
					    goto  fail ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					  }   
					 
					 
					 
					  }   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					  // SPI settings
   
					 
					 
					 
					  // SPI settings
   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					  er r  =  util : : safe_ioctl ( spi_fd ,  SPI_IOC_WR_MODE ,  & spi_mode ) ;   
					 
					 
					 
					  ret   =  util : : safe_ioctl ( spi_fd ,  SPI_IOC_WR_MODE ,  & spi_mode ) ;   
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					  if  ( er r  <  0 )  {   
					 
					 
					 
					  if  ( ret   <  0 )  {   
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					    LOGE ( " failed setting SPI mode %d " ,  er r) ;   
					 
					 
					 
					    LOGE ( " failed setting SPI mode %d " ,  ret  ) ;   
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					    goto  fail ;   
					 
					 
					 
					    goto  fail ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					  }   
					 
					 
					 
					  }   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					  er r  =  util : : safe_ioctl ( spi_fd ,  SPI_IOC_WR_MAX_SPEED_HZ ,  & spi_speed ) ;   
					 
					 
					 
					  ret   =  util : : safe_ioctl ( spi_fd ,  SPI_IOC_WR_MAX_SPEED_HZ ,  & spi_speed ) ;   
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					  if  ( er r  <  0 )  {   
					 
					 
					 
					  if  ( ret   <  0 )  {   
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					    LOGE ( " failed setting SPI speed " ) ;   
					 
					 
					 
					    LOGE ( " failed setting SPI speed " ) ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    goto  fail ;   
					 
					 
					 
					    goto  fail ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					  }   
					 
					 
					 
					  }   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					  er r  =  util : : safe_ioctl ( spi_fd ,  SPI_IOC_WR_BITS_PER_WORD ,  & spi_bits_per_word ) ;   
					 
					 
					 
					  ret   =  util : : safe_ioctl ( spi_fd ,  SPI_IOC_WR_BITS_PER_WORD ,  & spi_bits_per_word ) ;   
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					  if  ( er r  <  0 )  {   
					 
					 
					 
					  if  ( ret   <  0 )  {   
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					    LOGE ( " failed setting SPI bits per word " ) ;   
					 
					 
					 
					    LOGE ( " failed setting SPI bits per word " ) ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    goto  fail ;   
					 
					 
					 
					    goto  fail ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					  }   
					 
					 
					 
					  }   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					  // get hw UID/serial
   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					  ret  =  control_read ( 0xc3 ,  0 ,  0 ,  uid ,  uid_len ) ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					  if  ( ret  = =  uid_len )  {   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    std : : stringstream  stream ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    for  ( int  i  =  0 ;  i  <  uid_len ;  i + + )  {   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					      stream  < <  std : : hex  < <  std : : setw ( 2 )  < <  std : : setfill ( ' 0 ' )  < <  int ( uid [ i ] ) ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    }   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    hw_serial  =  stream . str ( ) ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					  }  else  {   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    LOGD ( " failed to get serial %d " ,  ret ) ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    goto  fail ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					  }   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					  if  ( ! serial . empty ( )  & &  ( serial  ! =  hw_serial ) )  {   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    goto  fail ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					  }   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					  return ;   
					 
					 
					 
					  return ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					fail :  
					 
					 
					 
					fail :  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					 
					@ -163,7 +184,12 @@ int PandaSpiHandle::bulk_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t t 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					}  
					 
					 
					 
					}  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					std : : vector < std : : string >  PandaSpiHandle : : list ( )  {  
					 
					 
					 
					std : : vector < std : : string >  PandaSpiHandle : : list ( )  {  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					  // TODO: list all pandas available over SPI
   
					 
					 
					 
					  try  {   
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    PandaSpiHandle  sh ( " " ) ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    return  { sh . hw_serial } ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					  }  catch  ( std : : exception  & e )  {   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    // no panda on SPI
   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					  }   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					  return  { } ;   
					 
					 
					 
					  return  { } ;   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					}  
					 
					 
					 
					}