| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -6,6 +6,7 @@ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#include "common/util.h" | 
					 | 
					 | 
					 | 
					#include "common/util.h" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#include "common/swaglog.h" | 
					 | 
					 | 
					 | 
					#include "common/swaglog.h" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					#include "panda/board/comms_definitions.h" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#include "selfdrive/boardd/panda_comms.h" | 
					 | 
					 | 
					 | 
					#include "selfdrive/boardd/panda_comms.h" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -22,13 +23,6 @@ struct __attribute__((packed)) spi_header { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint16_t max_rx_len; | 
					 | 
					 | 
					 | 
					  uint16_t max_rx_len; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}; | 
					 | 
					 | 
					 | 
					}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					struct __attribute__((packed)) spi_control_packet { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint16_t request; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint16_t param1; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint16_t param2; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint16_t length; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					PandaSpiHandle::PandaSpiHandle(std::string serial) : PandaCommsHandle(serial) { | 
					 | 
					 | 
					 | 
					PandaSpiHandle::PandaSpiHandle(std::string serial) : PandaCommsHandle(serial) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  LOGD("opening SPI panda: %s", serial.c_str()); | 
					 | 
					 | 
					 | 
					  LOGD("opening SPI panda: %s", serial.c_str()); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -40,7 +34,7 @@ PandaSpiHandle::PandaSpiHandle(std::string serial) : PandaCommsHandle(serial) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  spi_fd = open(serial.c_str(), O_RDWR); | 
					 | 
					 | 
					 | 
					  spi_fd = open(serial.c_str(), O_RDWR); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (spi_fd < 0) { | 
					 | 
					 | 
					 | 
					  if (spi_fd < 0) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOGE("failed setting SPI mode %d", err); | 
					 | 
					 | 
					 | 
					    LOGE("failed opening SPI device %d", err); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    goto fail; | 
					 | 
					 | 
					 | 
					    goto fail; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -85,41 +79,23 @@ void PandaSpiHandle::cleanup() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					int PandaSpiHandle::control_write(uint8_t request, uint16_t param1, uint16_t param2, unsigned int timeout) { | 
					 | 
					 | 
					 | 
					int PandaSpiHandle::control_write(uint8_t request, uint16_t param1, uint16_t param2, unsigned int timeout) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  int err; | 
					 | 
					 | 
					 | 
					  ControlPacket_t packet = { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  std::lock_guard lk(hw_lock); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  do { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    spi_control_packet packet = { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    .request = request, | 
					 | 
					 | 
					 | 
					    .request = request, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    .param1 = param1, | 
					 | 
					 | 
					 | 
					    .param1 = param1, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    .param2 = param2, | 
					 | 
					 | 
					 | 
					    .param2 = param2, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    .length = 0 | 
					 | 
					 | 
					 | 
					    .length = 0 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }; | 
					 | 
					 | 
					 | 
					  }; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					  return spi_transfer_retry(0, (uint8_t *) &packet, sizeof(packet), NULL, 0); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // TODO: handle error
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    err = spi_transfer(0, (uint8_t *) &packet, sizeof(packet), NULL, 0); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } while (err < 0 && connected); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  return err; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					int PandaSpiHandle::control_read(uint8_t request, uint16_t param1, uint16_t param2, unsigned char *data, uint16_t length, unsigned int timeout) { | 
					 | 
					 | 
					 | 
					int PandaSpiHandle::control_read(uint8_t request, uint16_t param1, uint16_t param2, unsigned char *data, uint16_t length, unsigned int timeout) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  int err; | 
					 | 
					 | 
					 | 
					  ControlPacket_t packet = { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  std::lock_guard lk(hw_lock); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  do { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    spi_control_packet packet = { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    .request = request, | 
					 | 
					 | 
					 | 
					    .request = request, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    .param1 = param1, | 
					 | 
					 | 
					 | 
					    .param1 = param1, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    .param2 = param2, | 
					 | 
					 | 
					 | 
					    .param2 = param2, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    .length = length | 
					 | 
					 | 
					 | 
					    .length = length | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }; | 
					 | 
					 | 
					 | 
					  }; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					  return spi_transfer_retry(0, (uint8_t *) &packet, sizeof(packet), data, length); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // TODO: handle error
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    err = spi_transfer(0, (uint8_t *) &packet, sizeof(packet), data, length); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } while (err < 0 && connected); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  return err; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					int PandaSpiHandle::bulk_write(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout) { | 
					 | 
					 | 
					 | 
					int PandaSpiHandle::bulk_write(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout) { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -144,6 +120,46 @@ void add_checksum(uint8_t *data, int data_len) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					bool check_checksum(uint8_t *data, int data_len) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  uint8_t checksum = SPI_CHECKSUM_START; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  for (uint16_t i = 0U; i < data_len; i++) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    checksum ^= data[i]; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  return checksum == 0U; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					int PandaSpiHandle::spi_transfer_retry(uint8_t endpoint, uint8_t *tx_data, uint16_t tx_len, uint8_t *rx_data, uint16_t max_rx_len) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  int err; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  std::lock_guard lk(hw_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  do { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    // TODO: handle error
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    err = spi_transfer(endpoint, tx_data, tx_len, rx_data, max_rx_len); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } while (err < 0 && connected && !PANDA_NO_RETRY); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  return err; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					int PandaSpiHandle::wait_for_ack(spi_ioc_transfer &transfer, uint8_t ack) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  // TODO: add timeout?
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  while (true) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    int ret = util::safe_ioctl(spi_fd, SPI_IOC_MESSAGE(1), &transfer); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    if (ret < 0) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      LOGE("SPI: failed to send ACK request"); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      return ret; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    if (rx_buf[0] == ack) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    } else if (rx_buf[0] == SPI_NACK) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      LOGW("SPI: got header NACK"); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      return -1; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  return 0; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					int PandaSpiHandle::spi_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx_len, uint8_t *rx_data, uint16_t max_rx_len) { | 
					 | 
					 | 
					 | 
					int PandaSpiHandle::spi_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx_len, uint8_t *rx_data, uint16_t max_rx_len) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  int ret; | 
					 | 
					 | 
					 | 
					  int ret; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -178,20 +194,10 @@ int PandaSpiHandle::spi_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // Wait for (N)ACK
 | 
					 | 
					 | 
					 | 
					  // Wait for (N)ACK
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  tx_buf[0] = 0x12; | 
					 | 
					 | 
					 | 
					  tx_buf[0] = 0x12; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  transfer.len = 1; | 
					 | 
					 | 
					 | 
					  transfer.len = 1; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  while (true) { | 
					 | 
					 | 
					 | 
					  ret = wait_for_ack(transfer, SPI_HACK); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ret = util::safe_ioctl(spi_fd, SPI_IOC_MESSAGE(1), &transfer); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (ret < 0) { | 
					 | 
					 | 
					 | 
					  if (ret < 0) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      LOGE("SPI: failed to send ACK request"); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      goto transfer_fail; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (rx_buf[0] == SPI_HACK) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      break; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } else if (rx_buf[0] == SPI_NACK) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      LOGW("SPI: got header NACK"); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    goto transfer_fail; | 
					 | 
					 | 
					 | 
					    goto transfer_fail; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // Send data
 | 
					 | 
					 | 
					 | 
					  // Send data
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (tx_data != NULL) { | 
					 | 
					 | 
					 | 
					  if (tx_data != NULL) { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -208,44 +214,40 @@ int PandaSpiHandle::spi_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // Wait for (N)ACK
 | 
					 | 
					 | 
					 | 
					  // Wait for (N)ACK
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  tx_buf[0] = 0xab; | 
					 | 
					 | 
					 | 
					  tx_buf[0] = 0xab; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  transfer.len = 1; | 
					 | 
					 | 
					 | 
					  transfer.len = 1; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  while (true) { | 
					 | 
					 | 
					 | 
					  ret = wait_for_ack(transfer, SPI_DACK); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ret = util::safe_ioctl(spi_fd, SPI_IOC_MESSAGE(1), &transfer); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (ret < 0) { | 
					 | 
					 | 
					 | 
					  if (ret < 0) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      LOGE("SPI: failed to send ACK request"); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    goto transfer_fail; | 
					 | 
					 | 
					 | 
					    goto transfer_fail; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (rx_buf[0] == SPI_DACK) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      break; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } else if (rx_buf[0] == SPI_NACK) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      LOGE("SPI: got data NACK"); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      goto transfer_fail; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // Read data len
 | 
					 | 
					 | 
					 | 
					  // Read data len
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  transfer.len = 2; | 
					 | 
					 | 
					 | 
					  transfer.len = 2; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  transfer.rx_buf = (uint64_t)(rx_buf + 1); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  ret = util::safe_ioctl(spi_fd, SPI_IOC_MESSAGE(1), &transfer); | 
					 | 
					 | 
					 | 
					  ret = util::safe_ioctl(spi_fd, SPI_IOC_MESSAGE(1), &transfer); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (ret < 0) { | 
					 | 
					 | 
					 | 
					  if (ret < 0) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOGE("SPI: failed to read rx data len"); | 
					 | 
					 | 
					 | 
					    LOGE("SPI: failed to read rx data len"); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    goto transfer_fail; | 
					 | 
					 | 
					 | 
					    goto transfer_fail; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  rx_data_len = *(uint16_t *)rx_buf; | 
					 | 
					 | 
					 | 
					  rx_data_len = *(uint16_t *)(rx_buf+1); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  assert(rx_data_len < SPI_BUF_SIZE); | 
					 | 
					 | 
					 | 
					  assert(rx_data_len < SPI_BUF_SIZE); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // Read data
 | 
					 | 
					 | 
					 | 
					  // Read data
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  transfer.len = rx_data_len + 1; | 
					 | 
					 | 
					 | 
					  transfer.len = rx_data_len + 1; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  transfer.rx_buf = (uint64_t)(rx_buf + 2 + 1); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  ret = util::safe_ioctl(spi_fd, SPI_IOC_MESSAGE(1), &transfer); | 
					 | 
					 | 
					 | 
					  ret = util::safe_ioctl(spi_fd, SPI_IOC_MESSAGE(1), &transfer); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (ret < 0) { | 
					 | 
					 | 
					 | 
					  if (ret < 0) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOGE("SPI: failed to read rx data"); | 
					 | 
					 | 
					 | 
					    LOGE("SPI: failed to read rx data"); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    goto transfer_fail; | 
					 | 
					 | 
					 | 
					    goto transfer_fail; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // TODO: check checksum
 | 
					 | 
					 | 
					 | 
					  if (!check_checksum(rx_buf, rx_data_len + 4)) { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    LOGE("SPI: bad checksum"); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    goto transfer_fail; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (rx_data != NULL) { | 
					 | 
					 | 
					 | 
					  if (rx_data != NULL) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    memcpy(rx_data, rx_buf, rx_data_len); | 
					 | 
					 | 
					 | 
					    memcpy(rx_data, rx_buf + 3, rx_data_len); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  ret = rx_data_len; | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  return rx_data_len; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					transfer_fail: | 
					 | 
					 | 
					 | 
					transfer_fail: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  return ret; | 
					 | 
					 | 
					 | 
					  return ret; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
  |