refactor per-manufacturer checksum calculation (#650)

* synchronize function signatures

* if-spaghetti reduction

* add to cython

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
This commit is contained in:
Jason Young 2022-06-30 14:31:58 -04:00 committed by GitHub
parent 47b79c4d5a
commit fe6241dcc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 41 additions and 64 deletions

View File

@ -1,6 +1,6 @@
#include "common.h"
unsigned int honda_checksum(uint32_t address, const std::vector<uint8_t> &d) {
unsigned int honda_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d) {
int s = 0;
bool extended = address > 0x7FF;
while (address) { s += (address & 0xF); address >>= 4; }
@ -15,7 +15,7 @@ unsigned int honda_checksum(uint32_t address, const std::vector<uint8_t> &d) {
return s & 0xF;
}
unsigned int toyota_checksum(uint32_t address, const std::vector<uint8_t> &d) {
unsigned int toyota_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d) {
unsigned int s = d.size();
while (address) { s += address & 0xFF; address >>= 8; }
for (int i = 0; i < d.size() - 1; i++) { s += d[i]; }
@ -23,7 +23,7 @@ unsigned int toyota_checksum(uint32_t address, const std::vector<uint8_t> &d) {
return s & 0xFF;
}
unsigned int subaru_checksum(uint32_t address, const std::vector<uint8_t> &d) {
unsigned int subaru_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d) {
unsigned int s = 0;
while (address) { s += address & 0xFF; address >>= 8; }
@ -33,7 +33,7 @@ unsigned int subaru_checksum(uint32_t address, const std::vector<uint8_t> &d) {
return s & 0xFF;
}
unsigned int chrysler_checksum(uint32_t address, const std::vector<uint8_t> &d) {
unsigned int chrysler_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d) {
/* 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++) {
@ -107,7 +107,7 @@ void init_crc_lookup_tables() {
gen_crc_lookup_table_16(0x1021, crc16_lut_xmodem); // CRC-16 XMODEM for HKG CAN FD
}
unsigned int volkswagen_crc(uint32_t address, const std::vector<uint8_t> &d) {
unsigned int volkswagen_mqb_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d) {
// 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
@ -188,7 +188,7 @@ unsigned int volkswagen_crc(uint32_t address, const std::vector<uint8_t> &d) {
return crc ^ 0xFF; // Return after standard final XOR for CRC8 8H2F/AUTOSAR
}
unsigned int pedal_checksum(const std::vector<uint8_t> &d) {
unsigned int pedal_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d) {
uint8_t crc = 0xFF;
uint8_t poly = 0xD5; // standard crc8
@ -206,7 +206,7 @@ unsigned int pedal_checksum(const std::vector<uint8_t> &d) {
return crc;
}
unsigned int hkg_can_fd_checksum(uint32_t address, const std::vector<uint8_t> &d) {
unsigned int hkg_can_fd_checksum(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d) {
uint16_t crc = 0;

View File

@ -22,13 +22,13 @@
void init_crc_lookup_tables();
// Car specific functions
unsigned int honda_checksum(uint32_t address, const std::vector<uint8_t> &d);
unsigned int toyota_checksum(uint32_t address, const std::vector<uint8_t> &d);
unsigned int subaru_checksum(uint32_t address, const std::vector<uint8_t> &d);
unsigned int chrysler_checksum(uint32_t address, const std::vector<uint8_t> &d);
unsigned int volkswagen_crc(uint32_t address, const std::vector<uint8_t> &d);
unsigned int hkg_can_fd_checksum(uint32_t address, const std::vector<uint8_t> &d);
unsigned int pedal_checksum(const std::vector<uint8_t> &d);
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 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);
class MessageState {
public:

View File

@ -9,6 +9,8 @@ from libcpp.vector cimport vector
from libcpp.unordered_set cimport unordered_set
ctypedef unsigned int (*calc_checksum_type)(uint32_t, const Signal&, const vector[uint8_t] &)
cdef extern from "common_dbc.h":
ctypedef enum SignalType:
DEFAULT,
@ -17,8 +19,8 @@ cdef extern from "common_dbc.h":
TOYOTA_CHECKSUM,
PEDAL_CHECKSUM,
PEDAL_COUNTER,
VOLKSWAGEN_CHECKSUM,
VOLKSWAGEN_COUNTER,
VOLKSWAGEN_MQB_CHECKSUM,
VOLKSWAGEN_MQB_COUNTER,
SUBARU_CHECKSUM,
CHRYSLER_CHECKSUM
HKG_CAN_FD_CHECKSUM,
@ -31,6 +33,7 @@ cdef extern from "common_dbc.h":
double factor, offset
bool is_little_endian
SignalType type
calc_checksum_type calc_checksum
cdef struct Msg:
string name

View File

@ -36,8 +36,8 @@ enum SignalType {
TOYOTA_CHECKSUM,
PEDAL_CHECKSUM,
PEDAL_COUNTER,
VOLKSWAGEN_CHECKSUM,
VOLKSWAGEN_COUNTER,
VOLKSWAGEN_MQB_CHECKSUM,
VOLKSWAGEN_MQB_COUNTER,
SUBARU_CHECKSUM,
CHRYSLER_CHECKSUM,
HKG_CAN_FD_CHECKSUM,
@ -51,6 +51,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);
};
struct Msg {

View File

@ -9,6 +9,7 @@
#include <mutex>
#include <cstring>
#include "common.h"
#include "common_dbc.h"
std::regex bo_regexp(R"(^BO_ (\w+) (\w+) *: (\w+) (\w+))");
@ -54,35 +55,39 @@ typedef struct ChecksumState {
bool little_endian;
SignalType checksum_type;
SignalType counter_type;
unsigned int (*calc_checksum)(uint32_t address, const Signal &sig, const std::vector<uint8_t> &d);
} ChecksumState;
ChecksumState* get_checksum(const std::string& dbc_name) {
ChecksumState* s = nullptr;
if (startswith(dbc_name, {"honda_", "acura_"})) {
s = new ChecksumState({4, 2, 3, 5, false, HONDA_CHECKSUM, HONDA_COUNTER});
s = new ChecksumState({4, 2, 3, 5, false, HONDA_CHECKSUM, HONDA_COUNTER, &honda_checksum});
} else if (startswith(dbc_name, {"toyota_", "lexus_"})) {
s = new ChecksumState({8, -1, 7, -1, false, TOYOTA_CHECKSUM});
s = new ChecksumState({8, -1, 7, -1, false, TOYOTA_CHECKSUM, DEFAULT, &toyota_checksum});
} else if (startswith(dbc_name, "kia_ev6")) {
s = new ChecksumState({16, 8, 0, 0, true, HKG_CAN_FD_CHECKSUM, HKG_CAN_FD_COUNTER});
} else if (startswith(dbc_name, {"vw_", "volkswagen_", "audi_", "seat_", "skoda_"})) {
s = new ChecksumState({8, 4, 0, 0, true, VOLKSWAGEN_CHECKSUM, VOLKSWAGEN_COUNTER});
s = new ChecksumState({16, 8, 0, 0, true, HKG_CAN_FD_CHECKSUM, HKG_CAN_FD_COUNTER, &hkg_can_fd_checksum});
} else if (startswith(dbc_name, {"vw_mqb_2010"})) {
s = new ChecksumState({8, 4, 0, 0, true, VOLKSWAGEN_MQB_CHECKSUM, VOLKSWAGEN_MQB_COUNTER, &volkswagen_mqb_checksum});
} else if (startswith(dbc_name, "subaru_global_")) {
s = new ChecksumState({8, -1, 0, -1, true, SUBARU_CHECKSUM});
s = new ChecksumState({8, -1, 0, -1, true, SUBARU_CHECKSUM, DEFAULT, &subaru_checksum});
} else if (startswith(dbc_name, "chrysler_")) {
s = new ChecksumState({8, -1, 7, -1, false, CHRYSLER_CHECKSUM});
s = new ChecksumState({8, -1, 7, -1, false, CHRYSLER_CHECKSUM, DEFAULT, &chrysler_checksum});
} else if (startswith(dbc_name, "comma_body")) {
s = new ChecksumState({8, 4, 7, 3, false, PEDAL_CHECKSUM, PEDAL_COUNTER});
s = new ChecksumState({8, 4, 7, 3, false, PEDAL_CHECKSUM, PEDAL_COUNTER, &pedal_checksum});
}
return s;
}
void set_signal_type(Signal& s, ChecksumState* chk, const std::string& dbc_name, int line_num) {
s.calc_checksum = nullptr;
if (chk) {
if (s.name == "CHECKSUM") {
DBC_ASSERT(chk->checksum_size == -1 || s.size == chk->checksum_size, "CHECKSUM is not " << chk->checksum_size << " bits long");
DBC_ASSERT(chk->checksum_start_bit == -1 || (s.start_bit % 8) == chk->checksum_start_bit, " CHECKSUM starts at wrong bit");
DBC_ASSERT(s.is_little_endian == chk->little_endian, "CHECKSUM has wrong endianness");
DBC_ASSERT(chk->calc_checksum != nullptr, "CHECKSUM calculate function not supplied");
s.type = chk->checksum_type;
s.calc_checksum = chk->calc_checksum;
} else if (s.name == "COUNTER") {
DBC_ASSERT(chk->counter_size == -1 || s.size == chk->counter_size, "COUNTER is not " << chk->counter_size << " bits long");
DBC_ASSERT(chk->counter_start_bit == -1 || (s.start_bit % 8) == chk->counter_start_bit, "COUNTER starts at wrong bit");

View File

@ -70,7 +70,7 @@ std::vector<uint8_t> CANPacker::pack(uint32_t address, const std::vector<SignalP
}
const auto& sig = sig_it->second;
if ((sig.type != SignalType::HONDA_COUNTER) && (sig.type != SignalType::VOLKSWAGEN_COUNTER)) {
if ((sig.type != SignalType::HONDA_COUNTER) && (sig.type != SignalType::VOLKSWAGEN_MQB_COUNTER)) {
//WARN("COUNTER signal type not valid\n");
}
@ -81,29 +81,9 @@ std::vector<uint8_t> CANPacker::pack(uint32_t address, const std::vector<SignalP
auto sig_it_checksum = signal_lookup.find(std::make_pair(address, "CHECKSUM"));
if (sig_it_checksum != signal_lookup.end()) {
const auto &sig = sig_it_checksum->second;
if (sig.type == SignalType::HONDA_CHECKSUM) {
unsigned int chksm = honda_checksum(address, ret);
set_value(ret, sig, chksm);
} else if (sig.type == SignalType::TOYOTA_CHECKSUM) {
unsigned int chksm = toyota_checksum(address, ret);
set_value(ret, sig, chksm);
} else if (sig.type == SignalType::VOLKSWAGEN_CHECKSUM) {
unsigned int chksm = volkswagen_crc(address, ret);
set_value(ret, sig, chksm);
} else if (sig.type == SignalType::SUBARU_CHECKSUM) {
unsigned int chksm = subaru_checksum(address, ret);
set_value(ret, sig, chksm);
} else if (sig.type == SignalType::CHRYSLER_CHECKSUM) {
unsigned int chksm = chrysler_checksum(address, ret);
set_value(ret, sig, chksm);
} else if (sig.type == SignalType::PEDAL_CHECKSUM) {
unsigned int chksm = pedal_checksum(ret);
set_value(ret, sig, chksm);
} else if (sig.type == SignalType::HKG_CAN_FD_CHECKSUM) {
unsigned int chksm = hkg_can_fd_checksum(address, ret);
set_value(ret, sig, chksm);
} else {
//WARN("CHECKSUM signal type not valid\n");
if (sig.calc_checksum != nullptr) {
unsigned int checksum = sig.calc_checksum(address, sig, ret);
set_value(ret, sig, checksum);
}
}

View File

@ -45,26 +45,14 @@ bool MessageState::parse(uint64_t sec, const std::vector<uint8_t> &dat) {
bool checksum_failed = false;
if (!ignore_checksum) {
if (sig.type == SignalType::HONDA_CHECKSUM && honda_checksum(address, dat) != tmp) {
checksum_failed = true;
} else if (sig.type == SignalType::TOYOTA_CHECKSUM && toyota_checksum(address, dat) != tmp) {
checksum_failed = true;
} else if (sig.type == SignalType::VOLKSWAGEN_CHECKSUM && volkswagen_crc(address, dat) != tmp) {
checksum_failed = true;
} else if (sig.type == SignalType::SUBARU_CHECKSUM && subaru_checksum(address, dat) != tmp) {
checksum_failed = true;
} else if (sig.type == SignalType::CHRYSLER_CHECKSUM && chrysler_checksum(address, dat) != tmp) {
checksum_failed = true;
} else if (sig.type == SignalType::HKG_CAN_FD_CHECKSUM && hkg_can_fd_checksum(address, dat) != tmp) {
checksum_failed = true;
} else if (sig.type == SignalType::PEDAL_CHECKSUM && pedal_checksum(dat) != tmp) {
if (sig.calc_checksum != nullptr && sig.calc_checksum(address, sig, dat) != tmp) {
checksum_failed = true;
}
}
bool counter_failed = false;
if (!ignore_counter) {
if (sig.type == SignalType::HONDA_COUNTER || sig.type == SignalType::VOLKSWAGEN_COUNTER || sig.type == SignalType::PEDAL_COUNTER) {
if (sig.type == SignalType::HONDA_COUNTER || sig.type == SignalType::VOLKSWAGEN_MQB_COUNTER || sig.type == SignalType::PEDAL_COUNTER) {
counter_failed = !update_counter_generic(tmp, sig.size);
}
}