boardd: connect to SPI panda by UID (#27035)

* move list

* connect by serial

* cleanup hw serial

* little more

* rm excessive print

Co-authored-by: Comma Device <device@comma.ai>
old-commit-hash: 66ff2de0a2
beeps
Adeeb Shihadeh 2 years ago committed by GitHub
parent fc2743e9df
commit bf804f25bf
  1. 4
      selfdrive/boardd/boardd.cc
  2. 31
      selfdrive/boardd/panda.cc
  3. 2
      selfdrive/boardd/panda.h
  4. 2
      selfdrive/boardd/panda_comms.cc
  5. 1
      selfdrive/boardd/panda_comms.h
  6. 50
      selfdrive/boardd/spi.cc

@ -225,9 +225,9 @@ void can_send_thread(std::vector<Panda *> pandas, bool fake_send) {
//Dont send if older than 1 second
if ((nanos_since_boot() - event.getLogMonoTime() < 1e9) && !fake_send) {
for (const auto& panda : pandas) {
LOGT("sending sendcan to panda: %s", (panda->hw_serial).c_str());
LOGT("sending sendcan to panda: %s", (panda->hw_serial()).c_str());
panda->can_send(event.getSendcan());
LOGT("sendcan sent to panda: %s", (panda->hw_serial).c_str());
LOGT("sendcan sent to panda: %s", (panda->hw_serial()).c_str());
}
}
}

@ -3,20 +3,18 @@
#include <unistd.h>
#include <cassert>
#include <iomanip>
#include <stdexcept>
#include <sstream>
#include "cereal/messaging/messaging.h"
#include "common/swaglog.h"
#include "common/util.h"
Panda::Panda(std::string serial, uint32_t bus_offset) : bus_offset(bus_offset) {
// TODO: support SPI here one day...
if (serial.find("spi") != std::string::npos) {
handle = std::make_unique<PandaSpiHandle>(serial);
} else {
// try USB first, then SPI
try {
handle = std::make_unique<PandaUsbHandle>(serial);
} catch (std::exception &e) {
handle = std::make_unique<PandaSpiHandle>(serial);
}
hw_type = get_hw_type();
@ -41,23 +39,16 @@ bool Panda::comms_healthy() {
return handle->comms_healthy;
}
std::string Panda::hw_serial() {
return handle->hw_serial;
}
std::vector<std::string> Panda::list() {
std::vector<std::string> serials = PandaUsbHandle::list();
// check SPI
const int uid_len = 12;
uint8_t uid[uid_len] = {0};
PandaSpiHandle spi_handle("/dev/spidev0.0");
int ret = spi_handle.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]);
}
// might be on USB too
if (std::find(serials.begin(), serials.end(), stream.str()) == serials.end()) {
serials.push_back(stream.str());
for (auto s : PandaSpiHandle::list()) {
if (std::find(serials.begin(), serials.end(), s) == serials.end()) {
serials.push_back(s);
}
}

@ -48,13 +48,13 @@ private:
public:
Panda(std::string serial="", uint32_t bus_offset=0);
std::string hw_serial;
cereal::PandaState::PandaType hw_type = cereal::PandaState::PandaType::UNKNOWN;
bool has_rtc = false;
const uint32_t bus_offset;
bool connected();
bool comms_healthy();
std::string hw_serial();
// Static functions
static std::vector<std::string> list();

@ -44,7 +44,7 @@ PandaUsbHandle::PandaUsbHandle(std::string serial) : PandaCommsHandle(serial) {
ret = libusb_get_string_descriptor_ascii(dev_handle, desc.iSerialNumber, desc_serial, std::size(desc_serial));
if (ret < 0) { goto fail; }
auto hw_serial = std::string((char *)desc_serial, ret);
hw_serial = std::string((char *)desc_serial, ret);
if (serial.empty() || serial == hw_serial) {
break;
}

@ -21,6 +21,7 @@ public:
virtual ~PandaCommsHandle() {};
virtual void cleanup() = 0;
std::string hw_serial;
std::atomic<bool> connected = true;
std::atomic<bool> comms_healthy = true;
static std::vector<std::string> list();

@ -5,6 +5,8 @@
#include <cassert>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <sstream>
#include "common/util.h"
#include "common/timing.h"
@ -28,6 +30,7 @@ struct __attribute__((packed)) spi_header {
const int SPI_MAX_RETRIES = 5;
const int SPI_ACK_TIMEOUT = 50; // milliseconds
const std::string SPI_DEVICE = "/dev/spidev0.0";
class LockEx {
public:
@ -48,38 +51,56 @@ private:
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_speed = 30000000;
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) {
LOGE("failed opening SPI device %d", err);
LOGE("failed opening SPI device %d", spi_fd);
goto fail;
}
// SPI settings
err = util::safe_ioctl(spi_fd, SPI_IOC_WR_MODE, &spi_mode);
if (err < 0) {
LOGE("failed setting SPI mode %d", err);
ret = util::safe_ioctl(spi_fd, SPI_IOC_WR_MODE, &spi_mode);
if (ret < 0) {
LOGE("failed setting SPI mode %d", ret);
goto fail;
}
err = util::safe_ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed);
if (err < 0) {
ret = util::safe_ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed);
if (ret < 0) {
LOGE("failed setting SPI speed");
goto fail;
}
err = util::safe_ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits_per_word);
if (err < 0) {
ret = util::safe_ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits_per_word);
if (ret < 0) {
LOGE("failed setting SPI bits per word");
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;
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() {
// TODO: list all pandas available over SPI
try {
PandaSpiHandle sh("");
return {sh.hw_serial};
} catch (std::exception &e) {
// no panda on SPI
}
return {};
}

Loading…
Cancel
Save