nopenpilot/selfdrive/hardware/eon/rat.cc

184 lines
4.0 KiB
C++

#include <semaphore.h>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <map>
#include "json11.hpp"
#include "libdiag.h"
#include "selfdrive/common/swaglog.h"
#define DIAG_NV_READ_F 38
#define DIAG_NV_WRITE_F 39
#define DIAG_SUBSYS_CMD 75
#define DIAG_SUBSYS_CMD_VER_2 128
#define DIAG_SUBSYS_FS 19
#define EFS2_DIAG_SYNC_NO_WAIT 48
struct __attribute__((packed)) NvPacket {
uint8_t cmd_code;
uint16_t nv_id;
uint8_t data[128];
uint16_t status;
};
enum NvStatus {
NV_DONE,
NV_BUSY,
NV_FULL,
NV_FAIL,
NV_NOTACTIVE,
NV_BADPARAM,
NV_READONLY,
NV_BADRG,
NV_NOMEM,
NV_NOTALLOC,
};
struct __attribute__((packed)) Efs2DiagSyncReq {
uint8_t cmd_code;
uint8_t subsys_id;
uint16_t subsys_cmd_code;
uint16_t sequence_num;
char path[8];
};
struct __attribute__((packed)) Efs2DiagSyncResp {
uint8_t cmd_code;
uint8_t subsys_id;
uint16_t subsys_cmd_code;
uint16_t sequence_num;
uint32_t sync_token;
int32_t diag_errno;
};
struct SendDiagSyncState {
sem_t sem;
int len;
};
static void diag_send_sync_cb(unsigned char *ptr, int len, void *data_ptr) {
SendDiagSyncState *s = (SendDiagSyncState*)data_ptr;
s->len = len;
sem_post(&s->sem);
}
static int diag_send_sync(int client_id, unsigned char* req_pkt, size_t pkt_len,
unsigned char* res_pkt, size_t res_pkt_size) {
SendDiagSyncState s = {0};
sem_init(&s.sem, 0, 0);
int err = diag_send_dci_async_req(client_id, req_pkt, pkt_len, res_pkt, res_pkt_size,
diag_send_sync_cb, &s);
assert(err == DIAG_DCI_NO_ERROR);
sem_wait(&s.sem);
return s.len;
}
static void efs_sync(int client_id) {
unsigned char res_pkt[DIAG_MAX_RX_PKT_SIZ];
Efs2DiagSyncReq req_pkt = {
.cmd_code = DIAG_SUBSYS_CMD,
.subsys_id = DIAG_SUBSYS_FS,
.subsys_cmd_code = EFS2_DIAG_SYNC_NO_WAIT,
.sequence_num = (uint16_t)(rand() % 100),
};
req_pkt.path[0] = '/';
req_pkt.path[1] = 0;
int res_len = diag_send_sync(client_id, (unsigned char*)&req_pkt, sizeof(req_pkt),
res_pkt, sizeof(res_pkt));
Efs2DiagSyncResp *resp = (Efs2DiagSyncResp*)res_pkt;
if (res_len != sizeof(Efs2DiagSyncResp)
|| resp->cmd_code != DIAG_SUBSYS_CMD
|| resp->subsys_id != DIAG_SUBSYS_FS
|| resp->subsys_cmd_code != EFS2_DIAG_SYNC_NO_WAIT) {
LOGW("efs_sync: bad response!");
return;
}
if (resp->diag_errno != 0) {
LOGW("efs_sync: error %d", resp->diag_errno);
}
}
static int nv_read(int client_id, uint16_t nv_id, NvPacket &resp) {
NvPacket req = {
.cmd_code = DIAG_NV_READ_F,
.nv_id = nv_id,
};
int res_len = diag_send_sync(client_id, (unsigned char*)&req, sizeof(req),
(unsigned char*)&resp, sizeof(resp));
// hexdump((uint8_t*)&resp, res_len);
if (resp.cmd_code != DIAG_NV_READ_F || resp.nv_id != nv_id) {
LOGW("nv_read: diag command failed");
return -1;
}
if (resp.status != NV_DONE) {
LOGW("nv_read: read failed: %d", resp.status);
return -1;
}
return 0;
}
static uint32_t nv_read_u32(int client_id, uint16_t nv_id) {
NvPacket resp = {0};
if (nv_read(client_id, nv_id, resp) < 0) {
return 0;
}
return *(uint32_t*)resp.data;
}
int main() {
int err;
int client_id = 0;
// setup diag
bool ok = Diag_LSM_Init(NULL);
assert(ok);
uint16_t list = DIAG_CON_APSS | DIAG_CON_MPSS;
int signal_type = SIGCONT;
err = diag_register_dci_client(&client_id, &list, 0, &signal_type);
assert(err == DIAG_DCI_NO_ERROR);
// log some stuff
std::map<std::string, uint16_t> to_log = {
{"B13", 6502},
{"B7", 6553},
{"B17", 6606},
{"B40", 6658},
{"B1", 6710},
};
auto log = json11::Json::object {};
for (auto const &kv : to_log) {
NvPacket resp = {0};
nv_read(client_id, kv.second, resp);
log[kv.first] = *(uint8_t*)resp.data;
}
printf("%s\n", json11::Json(log).dump().c_str());
// cleanup
err = diag_release_dci_client(&client_id);
assert(err == DIAG_DCI_NO_ERROR);
Diag_LSM_DeInit();
}