mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-02-18 22:23:56 +08:00
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
This commit is contained in:
@@ -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 {};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user