/* * can_db.c (Flash-resident map; no HAL here) */ #include #include "can_schema.h" #include "can_db_symbols.h" #include #include "injection.h" #if ENABLE_AUDI_IMMO #include "audi_immo.h" #endif #if defined(T06301) #include "ford_immo.h" #endif #if defined(T06301) #define ID_EMPF1 0x112 #define ID_EMPF2 0x222 #define ID_EMPF3 0x712 #define ID_EMPF4 0x312 #define ID_SEND1 0x100 #define ID_SEND2 0x221 #define ID_SEND3 0x700 #define ID_SEND4 0x300 #elif defined(T06215) || defined(T06211) #define ID_EMPF1 0x112 #define ID_EMPF2 0x512 #define ID_EMPF3 0x712 #define ID_SEND1 0x100 #define ID_SEND2 0x500 #define ID_SEND3 0x700 #elif defined(T15021) || defined(T31804) #define ID_EMPF1 0x114 #define ID_EMPF2 0x516 #define ID_EMPF3 0x714 #define ID_SEND1 0x10E #define ID_SEND2 0x502 #define ID_SEND3 0x702 #elif defined(T06209) || defined(T06216) #define ID_EMPF1 0x028 #define ID_EMPF2 0x508 #define ID_EMPF3 0x708 #define ID_SEND1 0x020 #define ID_SEND2 0x500 #define ID_SEND3 0x700 #else #error "Define CFG" #endif #define ID_SEND_CUST 0x720 /* ===== Extern RAM variables declared elsewhere ===== */ extern uint16_t BitStatus; extern float PHI_AD; extern float RPM; extern float Temp; extern float ME, MEPI, B_FB_KW, B_FB_NW, dFi, B_PHIAD; extern uint8_t cilCount, safetySHUTOFF; extern uint8_t inj_mode, request_syncout_activation; extern uint8_t memWrite; extern uint32_t quart_hour_counter; extern float FBKW_DEMAND, FBKW_DC, FBKW_FEEDBACK, T_ein, PSG_Voltage; extern float actual_phi1, real_eoi, target_eoi; extern uint32_t sensorfail, canfails; extern uint8_t hasCapturedTeeth, T_ein_status; /* ===== STARTUP MESSAGE (template-only) ===== */ /* ===== Common scales ===== */ static const CanScaleDef SCALE_DEG_KW = { "degKW", 3.0f/256.0f, 0.0f }; static const CanScaleDef SCALE_PHIAD = { "degNW", 3.0f/256.0f, 0.0f }; static const CanScaleDef SCALE_PHIAD_2 = { "degNW", 3.0f/64.0f, 0.0f }; #if defined(T06215) static const CanScaleDef SCALE_ME = { "mg/H", 1.0f/32.0f, 0.0f }; static const CanScaleDef SCALE_TEMP = { "degC", 1.0f/16.0f, -273.0f }; static const CanScaleDef SCALE_FBKW = { "FBKW", 3.0f/256.0f, 0.0f }; #elif defined(T06301) static const CanScaleDef SCALE_ME = { "mg/H", 1.0f/16.0f, 0.0f }; static const CanScaleDef SCALE_TEMP = { "degC", 1.0f/4.0f, -273.0f }; static const CanScaleDef SCALE_FBKW = { "FBKW", 1.0f/16.0f, 0.0f }; #else static const CanScaleDef SCALE_ME = { "mg/H", 1.0f/32.0f, 0.0f }; static const CanScaleDef SCALE_TEMP = { "degC", 1.0f/16.0f, -273.0f }; static const CanScaleDef SCALE_FBKW = { "FBKW", 3.0f/256.0f, 0.0f }; #endif static const CanScaleDef SCALE_ME_RAM = { "mg/H", 1.0f/32.0f, 0.0f }; static const CanScaleDef SCALE_DC = { "%", 100.0f/4095.0f, 0.0f }; static const CanScaleDef SCALE_TEIN = { "uS", 1.0f/2.0f, 0.0f }; static const CanScaleDef SCALE_RPM = { "1/min", 1.0f/4.0f, 0.0f }; static const CanScaleDef SCALE_VOLTAGE= { "V", 0.0185f, -0.05f }; /* ===== TX: ID 0x114 EMPF1 ===== */ uint8_t injectionStatus = 0b0101; //---* tein, --*- feedback, -*-- rpm, uint8_t QTY_valve_status = 1; //---* tein, --*- feedback, -*-- rpm, static CanSymbolDef SYM_ID_EMPF1[] = { #if defined(T06301) { "TEIN_STATUS", 8, 1, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &T_ein_status, NULL, CAN_STORE_U8, INVERTED}, { "QTY_VALVE_STATUS", 9, 1, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &QTY_valve_status, NULL, CAN_STORE_U8}, { "ANGLESENSOR_STATUS", 10, 1, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &hasCapturedTeeth, NULL, CAN_STORE_U8, INVERTED}, { "CIL_COUNT", 0, 3, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &cilCount, NULL, CAN_STORE_U8}, { "NW_N", 32, 16, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &RPM, NULL, CAN_STORE_FLOAT}, #elif defined(T06215) { "STATUS", 0, 16, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &BitStatus, NULL, CAN_STORE_U32}, { "PHIAD_AKT", 16, 13, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &PHI_AD, &SCALE_PHIAD, CAN_STORE_FLOAT}, { "CIL_COUNT", 29, 3, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &cilCount, NULL, CAN_STORE_U8}, { "NW_N", 32, 16, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &RPM, &SCALE_RPM, CAN_STORE_FLOAT}, { "THYBR", 48, 16, CAN_ENDIAN_INTEL, CAN_SYM_SX, 0,0, &Temp, &SCALE_TEMP, CAN_STORE_FLOAT}, #elif defined(T15021) || defined(T31804) #elif defined(T06209) || defined(T06211) || defined(T06216) { "STATUS", 0, 16, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &BitStatus, NULL, CAN_STORE_U32}, { "PHIAD_AKT", 16, 13, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &PHI_AD, &SCALE_PHIAD, CAN_STORE_FLOAT}, { "CIL_COUNT", 29, 3, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &cilCount, NULL, CAN_STORE_U8}, { "NW_N", 32, 16, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &RPM, &SCALE_RPM, CAN_STORE_FLOAT}, { "THYBR", 48, 16, CAN_ENDIAN_INTEL, CAN_SYM_SX, 0,0, &Temp, &SCALE_TEMP, CAN_STORE_FLOAT}, #else #error "Define CFG" #endif }; uint16_t fbkwStatus = 0x0001; //alternative 0x0001 uint16_t fa02 = 0x0001; uint16_t status2 = 0xfffe; const CanAddressEntry CAN_ANSWERS[] = { #if defined(T15021) || defined(T31804) { 0xD282, &FBKW_DC, CAN_SYM_UX, &SCALE_DC , CAN_STORE_FLOAT }, { 0xF882, &FBKW_FEEDBACK, CAN_SYM_SX, &SCALE_DEG_KW, CAN_STORE_FLOAT }, { 0x7A81, &fbkwStatus, CAN_SYM_UX, NULL, CAN_STORE_U16 }, { 0x4281, &PSG_Voltage, CAN_SYM_UX, &SCALE_VOLTAGE, CAN_STORE_FLOAT }, #else { 0x5E00, &FBKW_DEMAND, CAN_SYM_SX, &SCALE_DEG_KW, CAN_STORE_FLOAT }, { 0xD202, &FBKW_DC, CAN_SYM_UX, &SCALE_DC , CAN_STORE_FLOAT }, //d402always 0 { 0xF802, &FBKW_FEEDBACK, CAN_SYM_SX, &SCALE_DEG_KW, CAN_STORE_FLOAT }, { 0xFA02, &fa02, CAN_SYM_SX, &SCALE_DEG_KW, CAN_STORE_FLOAT }, { 0x7800, &T_ein, CAN_SYM_UX, &SCALE_TEIN , CAN_STORE_FLOAT }, { 0x4201, &PSG_Voltage, CAN_SYM_UX, &SCALE_VOLTAGE, CAN_STORE_FLOAT }, { 0x4400, &ME, CAN_SYM_UX, &SCALE_ME_RAM, CAN_STORE_FLOAT }, { 0x4800, &PHI_AD, CAN_SYM_SX, &SCALE_DEG_KW, CAN_STORE_FLOAT }, { 0x4C00, &actual_phi1, CAN_SYM_SX, &SCALE_DEG_KW, CAN_STORE_FLOAT }, { 0x5800, &real_eoi, CAN_SYM_SX, &SCALE_DEG_KW, CAN_STORE_FLOAT }, { 0x5A00, &target_eoi, CAN_SYM_SX, &SCALE_DEG_KW, CAN_STORE_FLOAT }, { 0x7A01, &fbkwStatus, CAN_SYM_UX, NULL, CAN_STORE_U16 }, { 0x7C01, &status2, CAN_SYM_UX, NULL, CAN_STORE_U16 }, { 0xBABA, &quart_hour_counter, CAN_SYM_UX, NULL , CAN_STORE_U32 }, #endif #if ENABLE_AUDI_IMMO { 0x0404, &audi_immo_key_part_0, CAN_SYM_UX, NULL, CAN_STORE_U16 }, { 0xFA04, &audi_immo_key_part_1, CAN_SYM_UX, NULL, CAN_STORE_U16 }, { 0x0204, &audi_immo_key_part_2, CAN_SYM_UX, NULL, CAN_STORE_U16 }, { 0x0004, &audi_immo_key_part_3, CAN_SYM_UX, NULL, CAN_STORE_U16 }, #endif { 0x0008, &canfails, CAN_SYM_UX, NULL, CAN_STORE_U32 }, { 0x0108, &sensorfail, CAN_SYM_UX, NULL, CAN_STORE_U32 }, }; extern volatile uint8_t EMPF2_BYTES[8]; static CanSymbolDef SYM_ID_EMPF2[] = { // name, start, len, endian, raw, factor, offset, ptr, scale, storage { "B0", 0, 8, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, (void*)&EMPF2_BYTES[0], NULL, CAN_STORE_U8 }, { "B1", 8, 8, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, (void*)&EMPF2_BYTES[1], NULL, CAN_STORE_U8 }, { "B2", 16, 8, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, (void*)&EMPF2_BYTES[2], NULL, CAN_STORE_U8 }, { "B3", 24, 8, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, (void*)&EMPF2_BYTES[3], NULL, CAN_STORE_U8 }, { "B4", 32, 8, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, (void*)&EMPF2_BYTES[4], NULL, CAN_STORE_U8 }, { "B5", 40, 8, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, (void*)&EMPF2_BYTES[5], NULL, CAN_STORE_U8 }, { "B6", 48, 8, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, (void*)&EMPF2_BYTES[6], NULL, CAN_STORE_U8 }, { "B7", 56, 8, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, (void*)&EMPF2_BYTES[7], NULL, CAN_STORE_U8 }, }; const size_t CAN_ANSWERS_COUNT = sizeof(CAN_ANSWERS)/sizeof(CAN_ANSWERS[0]); //static const uint8_t STARTUP_PAYLOAD[8] = {0x07, 0x0C, 0x5D, 0x1C, 0xE6, 0x7B, 0x9D, 0xD8}; //0xDC bit immo 1 //static const uint8_t STARTUP_PAYLOAD_2[8] = {0x81, 0x7F, 0x5D, 0x1C, 0xE6, 0x7B, 0x9D, 0xD8}; //0xD8 bit immo 0 #if defined(T06301) static const uint8_t STARTUP_PAYLOAD[8] = {0x07, 0x05, 0x1C, 0x38, 0x1C, 0xFC, 0xF5, 0x71}; //0x75 immo 1 0x71 immo 0 static const uint8_t STARTUP_PAYLOAD_2[8] = {0x81, 0x7F, 0x1C, 0x38, 0x1C, 0xFC, 0xF5, 0x71}; #elif defined(T06211) static const uint8_t STARTUP_PAYLOAD[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //0x75 immo 1 0x71 immo 0 #elif defined(T06209) || defined(T06216) static const uint8_t STARTUP_PAYLOAD[8] = {0x00, 0x00, 0x21, 0xD7, 0x46, 0xBA, 0xE9, 0x5F}; //0x75 immo 1 0x71 immo 0 #endif //static const uint8_t STARTUP_PAYLOAD[8] = {0x00, 0x00, 0x1C, 0x38, 0x01c, 0xFC, 0xF5, 0x71}; //0x75 immo 1 0x71 immo 0 //static const uint8_t STARTUP_PAYLOAD_2[8] = {0x00, 0x00, 0x1C, 0x38, 0x1c, 0xFC, 0xF5, 0x71}; uint8_t pepe = 1; /* ===== TX: ID 0x312 EMPF4 ===== */ #if defined(T06301) static CanSymbolDef SYM_ID_EMPF4[] = { { "FIEONA-PER0", 0, 16, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &FIEONA_FIRSTWORD, NULL, CAN_STORE_U16}, { "FIEONA-PER1", 16, 16, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &FIEONA_SECONDWORD, NULL, CAN_STORE_U16}, { "FIEONA-SHUTOFF", 16, 1, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &safetySHUTOFF, NULL, CAN_STORE_U8}, { "THYBR", 32, 16, CAN_ENDIAN_INTEL, CAN_SYM_SX, 0,0, &Temp, &SCALE_TEMP, CAN_STORE_FLOAT}, { "STATUS", 48, 16, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &BitStatus, NULL, CAN_STORE_U32}, }; #endif const CanMessageDef MSG_ID_EMPF1 = { .can_id = ID_EMPF1, .dir = CAN_DIR_TX, .dlc = 8, .name = "ID_EMPF1", .symbols= SYM_ID_EMPF1, .symbol_count = (uint8_t)(sizeof(SYM_ID_EMPF1)/sizeof(SYM_ID_EMPF1[0])), .tx_template = NULL, .send_on_boot = 0, .rx_handler = NULL }; /* ===== TX: EMPF2 — reply to addressed requests (8 bytes, 4 words) ===== */ const CanMessageDef MSG_ID_EMPF2 = { .can_id = ID_EMPF2, .dir = CAN_DIR_TX, .dlc = 8, .name = "ID_EMPF2", .symbols = SYM_ID_EMPF2, // payload is built by the handler (no symbols) .symbol_count = (uint8_t)(sizeof(SYM_ID_EMPF2)/sizeof(SYM_ID_EMPF2[0])), .tx_template = NULL, // no template; handler writes all 8 bytes .send_on_boot = 0, .rx_handler = NULL }; const CanMessageDef MSG_ID_EMPF3 = { .can_id = ID_EMPF3, // you set 0x714 .dir = CAN_DIR_TX, .dlc = 8, .name = "BOOT_TEMPLATE", .symbols = NULL, .symbol_count = 0, .tx_template = STARTUP_PAYLOAD, .send_on_boot = 0, .rx_handler = NULL }; #if defined(T06301) const CanMessageDef MSG_ID_EMPF3_MOD = { .can_id = ID_EMPF3, // you set 0x714 .dir = CAN_DIR_TX, .dlc = 8, .name = "BOOT_TEMPLATE", .symbols = NULL, .symbol_count = 0, .tx_template = STARTUP_PAYLOAD_2, .send_on_boot = 0, .rx_handler = NULL }; const CanMessageDef MSG_ID_EMPF4 = { .can_id = ID_EMPF4, .dir = CAN_DIR_TX, .dlc = 8, .name = "ID_EMPF4", .symbols= SYM_ID_EMPF4, .symbol_count = (uint8_t)(sizeof(SYM_ID_EMPF4)/sizeof(SYM_ID_EMPF4[0])), .tx_template = NULL, .send_on_boot = 0, .rx_handler = NULL }; #endif /* ===== RX: ID 0x100 SEND1 ===== */ static CanSymbolDef SYM_ID_SEND1[] = { #if defined(T06301) { "MESOLL", 0, 12, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &ME, &SCALE_ME, CAN_STORE_FLOAT}, //{ "B_PHIAD", 32, 16, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &B_PHIAD, &SCALE_PHIAD, CAN_STORE_FLOAT}, { "FB_KW", 12, 12, CAN_ENDIAN_INTEL, CAN_SYM_SX, 0,0, &B_FB_KW, &SCALE_FBKW, CAN_STORE_FLOAT}, //{ "FB_NW", 48, 16, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &B_FB_NW, &SCALE_FBKW, CAN_STORE_FLOAT}, #elif defined(T06215) { "MESOLL", 0, 12, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &ME, &SCALE_ME, CAN_STORE_FLOAT}, { "B_PHIAD", 12, 24, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &B_PHIAD, &SCALE_PHIAD, CAN_STORE_FLOAT}, { "FB_KW", 32, 16, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &B_FB_KW, &SCALE_FBKW, CAN_STORE_FLOAT}, { "FB_NW", 48, 16, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &B_FB_NW, &SCALE_FBKW, CAN_STORE_FLOAT}, #elif defined(T15021) || defined(T31804) { "MESOLL", 0, 12, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &ME, &SCALE_ME, CAN_STORE_FLOAT}, { "B_PHIAD", 12, 24, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &B_PHIAD, &SCALE_PHIAD, CAN_STORE_FLOAT}, { "FB_KW", 32, 16, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &B_FB_KW, &SCALE_FBKW, CAN_STORE_FLOAT}, { "FB_NW", 48, 16, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &B_FB_NW, &SCALE_FBKW, CAN_STORE_FLOAT}, #elif defined(T06209) || defined(T06211) || defined(T06216) { "MESOLL", 0, 12, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &ME, &SCALE_ME, CAN_STORE_FLOAT}, { "B_PHIAD", 12, 24, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &B_PHIAD, &SCALE_PHIAD, CAN_STORE_FLOAT}, { "FB_KW", 32, 16, CAN_ENDIAN_INTEL, CAN_SYM_SX, 0,0, &B_FB_KW, &SCALE_FBKW, CAN_STORE_FLOAT}, { "FB_NW", 48, 16, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &B_FB_NW, &SCALE_FBKW, CAN_STORE_FLOAT}, #else #error "Define CFG" #endif }; #if defined(T06301) static CanSymbolDef SYM_ID_SEND4[] = { { "FIEONA-SHUTOFF-SEND", 32, 1, CAN_ENDIAN_INTEL, CAN_SYM_UX, 0,0, &safetySHUTOFF, NULL, CAN_STORE_U8}, }; #elif defined(cfgejemplo) #endif /* ===== RX: ID 0x720 SEND ===== */ static CanSymbolDef SYM_ID_SEND_CUSTOM[] = { { "PHI_OFFSET", 0, 16, CAN_ENDIAN_INTEL, CAN_SYM_SX, 0,0, &dFi, &SCALE_DEG_KW, CAN_STORE_FLOAT}, { "INJMODE", 16, 8, CAN_ENDIAN_INTEL, CAN_SYM_UX, 1,0, &inj_mode, NULL, CAN_STORE_U8}, { "SYNCMODE", 24, 8, CAN_ENDIAN_INTEL, CAN_SYM_UX, 1,0, &request_syncout_activation, NULL, CAN_STORE_U8}, { "memWrite", 63, 1, CAN_ENDIAN_INTEL, CAN_SYM_UX, 1,0, &memWrite, NULL, CAN_STORE_U8}, }; const CanMessageDef MSG_ID_SEND1 = { .can_id = ID_SEND1, .dir = CAN_DIR_RX, .dlc = 8, .name = "ID_SEND1", .symbols= SYM_ID_SEND1, .symbol_count = (uint8_t)(sizeof(SYM_ID_SEND1)/sizeof(SYM_ID_SEND1[0])), .tx_template = NULL, .send_on_boot = 0, .rx_handler = SEND1_Handler }; /* ===== RX: ID 0x502 SEND2 request (addressed read -> handler replies) ===== */ const CanMessageDef MSG_ID_SEND2 = { .can_id = ID_SEND2, .dir = CAN_DIR_RX, .dlc = 8, .name = "ID_SEND2_REQ", .symbols = NULL, // parsed by handler .symbol_count = 0, .tx_template = NULL, .send_on_boot = 0, .rx_handler = NULL }; const CanMessageDef MSG_ID_SEND3 = { .can_id = ID_SEND3, .dir = CAN_DIR_RX, .dlc = 8, .name = "ID_SEND3", .symbols = NULL, .symbol_count = 0, .tx_template = NULL, .send_on_boot = 0, .rx_handler = NULL }; #if defined(T06301) const CanMessageDef MSG_ID_SEND4 = { .can_id = ID_SEND4, .dir = CAN_DIR_RX, .dlc = 8, .name = "ID_SEND4", .symbols = SYM_ID_SEND4, .symbol_count = (uint8_t)(sizeof(SYM_ID_SEND4)/sizeof(SYM_ID_SEND4[0])), .tx_template = NULL, .send_on_boot = 0, .rx_handler = Fieona_SEND4_Handler }; #elif defined(cfgejemplo) #endif const CanMessageDef MSG_ID_SEND_CUSTOM = { .can_id = ID_SEND_CUST, .dir = CAN_DIR_RX, .dlc = 8, .name = "ID_SEND_CUSTOM", .symbols= SYM_ID_SEND_CUSTOM, .symbol_count = (uint8_t)(sizeof(SYM_ID_SEND_CUSTOM)/sizeof(SYM_ID_SEND_CUSTOM[0])), .tx_template = NULL, .send_on_boot = 0, .rx_handler = NULL }; /* ===== Registry ===== */ static const CanMessageDef* const CAN_DB[] = { &MSG_ID_EMPF1, &MSG_ID_EMPF2, &MSG_ID_EMPF3, &MSG_ID_SEND1, &MSG_ID_SEND2, &MSG_ID_SEND3, #if defined(T06301) &MSG_ID_EMPF3_MOD, &MSG_ID_EMPF4, &MSG_ID_SEND4, #endif &MSG_ID_SEND_CUSTOM, }; const CanMessageDef* can_db_find(uint16_t id, CanDirection dir) { size_t n = sizeof(CAN_DB)/sizeof(CAN_DB[0]); for (size_t i = 0; i < n; ++i) if (CAN_DB[i]->can_id == id && CAN_DB[i]->dir == dir) return CAN_DB[i]; return NULL; } /* New helper that actually returns the pointer array */ const CanMessageDef* const* can_db_all_ptr(size_t *count) { if (count) *count = sizeof(CAN_DB)/sizeof(CAN_DB[0]); return CAN_DB; } const CanMessageDef* can_db_all(size_t *count) { if (count) *count = sizeof(CAN_DB)/sizeof(CAN_DB[0]); return (const CanMessageDef*)CAN_DB; // manager casts back to ptr-of-ptr }