| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -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
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  err = util::safe_ioctl(spi_fd, SPI_IOC_WR_MODE, &spi_mode); | 
					 | 
					 | 
					 | 
					  ret = util::safe_ioctl(spi_fd, SPI_IOC_WR_MODE, &spi_mode); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (err < 0) { | 
					 | 
					 | 
					 | 
					  if (ret < 0) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOGE("failed setting SPI mode %d", err); | 
					 | 
					 | 
					 | 
					    LOGE("failed setting SPI mode %d", ret); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    goto fail; | 
					 | 
					 | 
					 | 
					    goto fail; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  err = 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 (err < 0) { | 
					 | 
					 | 
					 | 
					  if (ret < 0) { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOGE("failed setting SPI speed"); | 
					 | 
					 | 
					 | 
					    LOGE("failed setting SPI speed"); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    goto fail; | 
					 | 
					 | 
					 | 
					    goto fail; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  err = 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 (err < 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 {}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
  |