From bf804f25bf4aff09d46c8f3f6bb5c2d4ebf8cf7d Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Sat, 21 Jan 2023 19:42:10 -0800 Subject: [PATCH] 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 old-commit-hash: 66ff2de0a29438c80e8834ac78a696ca21b30601 --- selfdrive/boardd/boardd.cc | 4 +-- selfdrive/boardd/panda.cc | 31 ++++++++------------ selfdrive/boardd/panda.h | 2 +- selfdrive/boardd/panda_comms.cc | 2 +- selfdrive/boardd/panda_comms.h | 1 + selfdrive/boardd/spi.cc | 50 +++++++++++++++++++++++++-------- 6 files changed, 54 insertions(+), 36 deletions(-) diff --git a/selfdrive/boardd/boardd.cc b/selfdrive/boardd/boardd.cc index e626882191..bc454aa54e 100644 --- a/selfdrive/boardd/boardd.cc +++ b/selfdrive/boardd/boardd.cc @@ -225,9 +225,9 @@ void can_send_thread(std::vector 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()); } } } diff --git a/selfdrive/boardd/panda.cc b/selfdrive/boardd/panda.cc index b12b26fb62..600a46c809 100644 --- a/selfdrive/boardd/panda.cc +++ b/selfdrive/boardd/panda.cc @@ -3,20 +3,18 @@ #include #include -#include #include -#include #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(serial); - } else { + // try USB first, then SPI + try { handle = std::make_unique(serial); + } catch (std::exception &e) { + handle = std::make_unique(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 Panda::list() { std::vector 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); } } diff --git a/selfdrive/boardd/panda.h b/selfdrive/boardd/panda.h index 156efe7ef3..69df2e2b66 100644 --- a/selfdrive/boardd/panda.h +++ b/selfdrive/boardd/panda.h @@ -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 list(); diff --git a/selfdrive/boardd/panda_comms.cc b/selfdrive/boardd/panda_comms.cc index e73cb69318..120d2f67d5 100644 --- a/selfdrive/boardd/panda_comms.cc +++ b/selfdrive/boardd/panda_comms.cc @@ -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; } diff --git a/selfdrive/boardd/panda_comms.h b/selfdrive/boardd/panda_comms.h index 9d1f69e671..b669d77e7f 100644 --- a/selfdrive/boardd/panda_comms.h +++ b/selfdrive/boardd/panda_comms.h @@ -21,6 +21,7 @@ public: virtual ~PandaCommsHandle() {}; virtual void cleanup() = 0; + std::string hw_serial; std::atomic connected = true; std::atomic comms_healthy = true; static std::vector list(); diff --git a/selfdrive/boardd/spi.cc b/selfdrive/boardd/spi.cc index 2779494ae4..bcc446b050 100644 --- a/selfdrive/boardd/spi.cc +++ b/selfdrive/boardd/spi.cc @@ -5,6 +5,8 @@ #include #include #include +#include +#include #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 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 {}; }