mirror of https://github.com/rusefi/opendbc.git
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:
parent
47b79c4d5a
commit
fe6241dcc6
|
@ -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;
|
||||
|
||||
|
|
14
can/common.h
14
can/common.h
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
21
can/dbc.cc
21
can/dbc.cc
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue