Skip to content

Commit

Permalink
Update CAN data handling functions for raw data and size parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
deanlee committed May 7, 2024
1 parent d058bc9 commit 08377cd
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 52 deletions.
58 changes: 29 additions & 29 deletions can/common.cc
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#include "opendbc/can/common.h"


unsigned int honda_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d) {
unsigned int honda_checksum(uint32_t address, const Signal &sig, const uint8_t *data, size_t size) {
int s = 0;
bool extended = address > 0x7FF;
while (address) { s += (address & 0xF); address >>= 4; }
for (int i = 0; i < d.size(); i++) {
uint8_t x = d[i];
if (i == d.size()-1) x >>= 4; // remove checksum
for (int i = 0; i < size; i++) {
uint8_t x = data[i];
if (i == size-1) x >>= 4; // remove checksum
s += (x & 0xF) + (x >> 4);
}
s = 8-s;
Expand All @@ -16,30 +16,30 @@ unsigned int honda_checksum(uint32_t address, const Signal &sig, const std::vect
return s & 0xF;
}

unsigned int toyota_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d) {
unsigned int s = d.size();
unsigned int toyota_checksum(uint32_t address, const Signal &sig, const uint8_t *data, size_t size) {
unsigned int s = size;
while (address) { s += address & 0xFF; address >>= 8; }
for (int i = 0; i < d.size() - 1; i++) { s += d[i]; }
for (int i = 0; i < size - 1; i++) { s += data[i]; }

return s & 0xFF;
}

unsigned int subaru_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d) {
unsigned int subaru_checksum(uint32_t address, const Signal &sig, const uint8_t *data, size_t size) {
unsigned int s = 0;
while (address) { s += address & 0xFF; address >>= 8; }

// skip checksum in first byte
for (int i = 1; i < d.size(); i++) { s += d[i]; }
for (int i = 1; i < size; i++) { s += data[i]; }

return s & 0xFF;
}

unsigned int chrysler_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d) {
unsigned int chrysler_checksum(uint32_t address, const Signal &sig, const uint8_t *data, size_t size) {
// jeep chrysler canbus checksum from http://illmatics.com/Remote%20Car%20Hacking.pdf
uint8_t checksum = 0xFF;
for (int j = 0; j < (d.size() - 1); j++) {
for (int j = 0; j < (size - 1); j++) {
uint8_t shift = 0x80;
uint8_t curr = d[j];
uint8_t curr = data[j];
for (int i = 0; i < 8; i++) {
uint8_t bit_sum = curr & shift;
uint8_t temp_chk = checksum & 0x80U;
Expand Down Expand Up @@ -108,22 +108,22 @@ void init_crc_lookup_tables() {
gen_crc_lookup_table_16(0x1021, crc16_lut_xmodem); // CRC-16 XMODEM for HKG CAN FD
}

unsigned int volkswagen_mqb_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d) {
unsigned int volkswagen_mqb_checksum(uint32_t address, const Signal &sig, const uint8_t *data, size_t size) {
// Volkswagen uses standard CRC8 8H2F/AUTOSAR, but they compute it with
// a magic variable padding byte tacked onto the end of the payload.
// https://www.autosar.org/fileadmin/user_upload/standards/classic/4-3/AUTOSAR_SWS_CRCLibrary.pdf

uint8_t crc = 0xFF; // Standard init value for CRC8 8H2F/AUTOSAR

// CRC the payload first, skipping over the first byte where the CRC lives.
for (int i = 1; i < d.size(); i++) {
crc ^= d[i];
for (int i = 1; i < size; i++) {
crc ^= data[i];
crc = crc8_lut_8h2f[crc];
}

// Look up and apply the magic final CRC padding byte, which permutes by CAN
// address, and additionally (for SOME addresses) by the message counter.
uint8_t counter = d[1] & 0x0F;
uint8_t counter = data[1] & 0x0F;
switch (address) {
case 0x86: // LWI_01 Steering Angle
crc ^= (uint8_t[]){0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86}[counter];
Expand Down Expand Up @@ -189,27 +189,27 @@ unsigned int volkswagen_mqb_checksum(uint32_t address, const Signal &sig, const
return crc ^ 0xFF; // Return after standard final XOR for CRC8 8H2F/AUTOSAR
}

unsigned int xor_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d) {
unsigned int xor_checksum(uint32_t address, const Signal &sig, const uint8_t *data, size_t size) {
uint8_t checksum = 0;
int checksum_byte = sig.start_bit / 8;

// Simple XOR over the payload, except for the byte where the checksum lives.
for (int i = 0; i < d.size(); i++) {
for (int i = 0; i < size; i++) {
if (i != checksum_byte) {
checksum ^= d[i];
checksum ^= data[i];
}
}

return checksum;
}

unsigned int pedal_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d) {
unsigned int pedal_checksum(uint32_t address, const Signal &sig, const uint8_t *data, size_t size) {
uint8_t crc = 0xFF;
uint8_t poly = 0xD5; // standard crc8

// skip checksum byte
for (int i = d.size()-2; i >= 0; i--) {
crc ^= d[i];
for (int i = size-2; i >= 0; i--) {
crc ^= data[i];
for (int j = 0; j < 8; j++) {
if ((crc & 0x80) != 0) {
crc = (uint8_t)((crc << 1) ^ poly);
Expand All @@ -221,24 +221,24 @@ unsigned int pedal_checksum(uint32_t address, const Signal &sig, const std::vect
return crc;
}

unsigned int hkg_can_fd_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d) {
unsigned int hkg_can_fd_checksum(uint32_t address, const Signal &sig, const uint8_t *data, size_t size) {
uint16_t crc = 0;

for (int i = 2; i < d.size(); i++) {
crc = (crc << 8) ^ crc16_lut_xmodem[(crc >> 8) ^ d[i]];
for (int i = 2; i < size; i++) {
crc = (crc << 8) ^ crc16_lut_xmodem[(crc >> 8) ^ data[i]];
}

// Add address to crc
crc = (crc << 8) ^ crc16_lut_xmodem[(crc >> 8) ^ ((address >> 0) & 0xFF)];
crc = (crc << 8) ^ crc16_lut_xmodem[(crc >> 8) ^ ((address >> 8) & 0xFF)];

if (d.size() == 8) {
if (size == 8) {
crc ^= 0x5f29;
} else if (d.size() == 16) {
} else if (size == 16) {
crc ^= 0x041d;
} else if (d.size() == 24) {
} else if (size == 24) {
crc ^= 0x819d;
} else if (d.size() == 32) {
} else if (size == 32) {
crc ^= 0x9f5b;
}

Expand Down
18 changes: 9 additions & 9 deletions can/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@
void init_crc_lookup_tables();

// Car specific functions
unsigned int honda_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d);
unsigned int toyota_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d);
unsigned int subaru_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d);
unsigned int chrysler_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d);
unsigned int volkswagen_mqb_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d);
unsigned int xor_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d);
unsigned int hkg_can_fd_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d);
unsigned int pedal_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d);
unsigned int honda_checksum(uint32_t address, const Signal &sig, const uint8_t *data, size_t size);
unsigned int toyota_checksum(uint32_t address, const Signal &sig, const uint8_t *data, size_t size);
unsigned int subaru_checksum(uint32_t address, const Signal &sig, const uint8_t *data, size_t size);
unsigned int chrysler_checksum(uint32_t address, const Signal &sig, const uint8_t *data, size_t size);
unsigned int volkswagen_mqb_checksum(uint32_t address, const Signal &sig, const uint8_t *data, size_t size);
unsigned int xor_checksum(uint32_t address, const Signal &sig, const uint8_t *data, size_t size);
unsigned int hkg_can_fd_checksum(uint32_t address, const Signal &sig, const uint8_t *data, size_t size);
unsigned int pedal_checksum(uint32_t address, const Signal &sig, const uint8_t *data, size_t size);

class MessageState {
public:
Expand All @@ -54,7 +54,7 @@ class MessageState {
bool ignore_checksum = false;
bool ignore_counter = false;

bool parse(uint64_t nanos, const std::vector<uint8_t> &dat);
bool parse(uint64_t nanos, const uint8_t *msg, const size_t msg_size);
bool update_counter_generic(int64_t v, int cnt_size);
};

Expand Down
4 changes: 2 additions & 2 deletions can/common_dbc.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct Signal {
double factor, offset;
bool is_little_endian;
SignalType type;
unsigned int (*calc_checksum)(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d);
unsigned int (*calc_checksum)(uint32_t address, const Signal &sig, const uint8_t *data, const size_t size);
};

struct Msg {
Expand Down Expand Up @@ -68,7 +68,7 @@ typedef struct ChecksumState {
int counter_start_bit;
bool little_endian;
SignalType checksum_type;
unsigned int (*calc_checksum)(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d);
unsigned int (*calc_checksum)(uint32_t address, const Signal &sig, const uint8_t *data, const size_t size);
} ChecksumState;

DBC* dbc_parse(const std::string& dbc_path);
Expand Down
2 changes: 1 addition & 1 deletion can/packer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ std::vector<uint8_t> CANPacker::pack(uint32_t address, const std::vector<SignalP
if (sig_it_checksum != signal_lookup.end()) {
const auto &sig = sig_it_checksum->second;
if (sig.calc_checksum != nullptr) {
unsigned int checksum = sig.calc_checksum(address, sig, ret);
unsigned int checksum = sig.calc_checksum(address, sig, ret.data(), ret.size());
set_value(ret, sig, checksum);
}
}
Expand Down
18 changes: 7 additions & 11 deletions can/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
#include "cereal/logger/logger.h"
#include "opendbc/can/common.h"

int64_t get_raw_value(const std::vector<uint8_t> &msg, const Signal &sig) {
int64_t get_raw_value(const uint8_t *msg, size_t msg_size, const Signal &sig) {
int64_t ret = 0;

int i = sig.msb / 8;
int bits = sig.size;
while (i >= 0 && i < msg.size() && bits > 0) {
while (i >= 0 && i < msg_size && bits > 0) {
int lsb = (int)(sig.lsb / 8) == i ? sig.lsb : i*8;
int msb = (int)(sig.msb / 8) == i ? sig.msb : (i+1)*8 - 1;
int size = msb - lsb + 1;
Expand All @@ -33,23 +33,23 @@ int64_t get_raw_value(const std::vector<uint8_t> &msg, const Signal &sig) {
}


bool MessageState::parse(uint64_t nanos, const std::vector<uint8_t> &dat) {
bool MessageState::parse(uint64_t nanos, const uint8_t *msg, size_t msg_size) {
std::vector<double> tmp_vals(parse_sigs.size());
bool checksum_failed = false;
bool counter_failed = false;

for (int i = 0; i < parse_sigs.size(); i++) {
const auto &sig = parse_sigs[i];

int64_t tmp = get_raw_value(dat, sig);
int64_t tmp = get_raw_value(msg, msg_size, sig);
if (sig.is_signed) {
tmp -= ((tmp >> (sig.size-1)) & 0x1) ? (1ULL << sig.size) : 0;
}

//DEBUG("parse 0x%X %s -> %ld\n", address, sig.name, tmp);

if (!ignore_checksum) {
if (sig.calc_checksum != nullptr && sig.calc_checksum(address, sig, dat) != tmp) {
if (sig.calc_checksum != nullptr && sig.calc_checksum(address, sig, msg, msg_size) != tmp) {
checksum_failed = true;
}
}
Expand Down Expand Up @@ -238,9 +238,7 @@ void CANParser::UpdateCans(uint64_t nanos, const capnp::List<cereal::CanData>::R
// continue;
//}

std::vector<uint8_t> data(dat.size(), 0);
memcpy(data.data(), dat.begin(), dat.size());
state_it->second.parse(nanos, data);
state_it->second.parse(nanos, dat.begin(), dat.size());
}

// update bus timeout
Expand Down Expand Up @@ -268,9 +266,7 @@ void CANParser::UpdateCans(uint64_t nanos, const capnp::DynamicStruct::Reader& c

auto dat = cmsg.get("dat").as<capnp::Data>();
if (dat.size() > 64) return; // shouldn't ever happen
std::vector<uint8_t> data(dat.size(), 0);
memcpy(data.data(), dat.begin(), dat.size());
state_it->second.parse(nanos, data);
state_it->second.parse(nanos, dat.begin(), dat.size());
}

void CANParser::UpdateValid(uint64_t nanos) {
Expand Down

0 comments on commit 08377cd

Please sign in to comment.