Files
2026-03-30 18:36:35 +02:00

151 lines
5.7 KiB
Plaintext

/*
* audi_immobiliser.c
*
* Created on: Sep 17, 2025
* Author: herli
*/
#include "audi_immobiliser.h"
#include "timeouts.h" // for Timeout_StartIfStopped
#include <string.h>
#include <stddef.h>
#include "can_db_symbols.h" // MSG_ID_SEND2, MSG_ID_EMPF2
#include "can_manager.h" // can_manager_register_handler_msg, can_manager_rx_address_request
#include "can_port.h" // can_port_send_msg_def
extern bool can_manager_empf2_has_pending(void);
extern void can_manager_empf2_clear_pending(void);
// Option B (simple flag): uncomment if you used a raw flag in your code
extern volatile uint8_t s_empf2_pending;
volatile uint8_t EMPF2_BYTES[8] = {0};
/* === Local storage for the four fields (defaults from your spec/trace) === */
//static char g_mod_index[8] = "000006"; // full value in storage
static char g_mod_index[8] = "pelele"; // full value in storage
//static char g_client_model[16] = "059 130 106L"; // client model
static char g_client_model[16] = "tonto el que"; // client model
//static char g_serial[16] = "686759"; // serial number
static char g_serial[16] = "lo lea"; // serial number
//static char g_sw[24] = "C150_1.V79"; // software version
static char g_sw[24] = "kkkvcdskk"; // software version
//static char g_pin[8] = "389"; // custom pin
static char g_pin[8] = " si"; // custom pin
/* Full ASCII payload built as: "<client_model> <serial> <sw> <pin>" */
static char g_full_str[40] = {0};
static uint16_t g_full_len = 0;
/* ---- Public setters ---- */
void audi_immobiliser_set_client_model(const char *ascii) {
if (ascii) { strncpy(g_client_model, ascii, sizeof(g_client_model)-1); g_client_model[sizeof(g_client_model)-1] = '\0'; }
}
void audi_immobiliser_set_serial(const char *ascii) {
if (ascii) { strncpy(g_serial, ascii, sizeof(g_serial)-1); g_serial[sizeof(g_serial)-1] = '\0'; }
}
void audi_immobiliser_set_sw(const char *ascii) {
if (ascii) { strncpy(g_sw, ascii, sizeof(g_sw)-1); g_sw[sizeof(g_sw)-1] = '\0'; }
}
void audi_immobiliser_set_pin(const char *ascii) {
if (ascii) { strncpy(g_pin, ascii, sizeof(g_pin)-1); g_pin[sizeof(g_pin)-1] = '\0'; }
}
/* Build the concatenated ASCII */
void audi_immobiliser_init(void)
{
size_t off = 0;
memset(g_full_str, 0, sizeof(g_full_str));
// Trim exactly one leading '0' so "000006" -> "00006"
const char *mod = g_mod_index;
if (mod[0] == '0' && mod[1] != '\0') mod++;
// Concatenate in the correct order, with NO added spaces between tokens
// (client model already has its spaces inside, e.g., "059 130 106L")
const char *parts[] = { mod, g_client_model, g_sw, g_serial, g_pin };
for (int i = 0; i < (int)(sizeof(parts)/sizeof(parts[0])); ++i) {
size_t plen = strlen(parts[i]);
if (off + plen >= sizeof(g_full_str)) plen = sizeof(g_full_str) - 1 - off;
memcpy(&g_full_str[off], parts[i], plen);
off += plen;
if (off >= sizeof(g_full_str) - 1) break;
}
g_full_len = (uint16_t)off;
}
/* ---- Immobiliser chunking: index A5..AB maps to 6-byte slices ---- */
static inline int is_immo_index(uint16_t idx) { return (idx >= 0xA5u) && (idx <= 0xABu); }
/* Copy 6 bytes from g_full_str starting at (idx - A5)*6; pad with 0x00 if past end */
static void immo_slice_fill(uint16_t idx, uint8_t out6[6])
{
uint16_t start = (uint16_t)((idx - 0xA5u) * 6u);
for (uint8_t i = 0; i < 6; ++i) {
uint16_t pos = (uint16_t)(start + i);
out6[i] = (pos < g_full_len) ? (uint8_t)g_full_str[pos] : 0x00;
}
}
/* ---- Wrapper handler for 0x502 (MSG_ID_SEND2) ----
* If payload is immobiliser request: [FF FF] [idx_hi idx_lo] [.. ..] [.. ..]
* -> we build EMPF2_BYTES = [idx_hi idx_lo d0 d1 d2 d3 d4 d5] and SEND EMPF2 immediately.
* Else: forward to the normal address→value handler.
*/
static void audi_immo_502_wrapper(const CanMessageDef *msg, const uint8_t in[8], CanTxFn tx)
{
(void)tx;
const uint16_t word0 = (uint16_t)((in[0] << 8) | in[1]); // must be 0xFFFF
const uint8_t idx_hi = in[2]; // A5..AB
const uint8_t idx_lo = in[3]; // must be 0x00
if (word0 == 0xFFFFu && idx_lo == 0x00u && is_immo_index(idx_hi)) {
// Build 6-byte slice from the concatenated immobiliser string
uint8_t slice[6];
immo_slice_fill(idx_hi, slice);
// Fill the common EMPF2 byte buffer (data-only mapping in can_db.c)
EMPF2_BYTES[0] = idx_hi; // e.g., A5
EMPF2_BYTES[1] = 0x00;
EMPF2_BYTES[2] = slice[0];
EMPF2_BYTES[3] = slice[1];
EMPF2_BYTES[4] = slice[2];
EMPF2_BYTES[5] = slice[3];
EMPF2_BYTES[6] = slice[4];
EMPF2_BYTES[7] = slice[5];
// Mark pending and start the 60 ms window (index 17) ONLY if not already running
// Use whichever pending API you kept:
// Option A (helpers):
// if (!can_manager_empf2_has_pending()) s_empf2_pending = 1; // or use a setter
// Option B (simple flag):
s_empf2_pending = 1;
Timeout_StartIfStopped(17, (uint16_t)TIM16->CNT);
// Do NOT send now; the 60 ms timeout (or your event path when RPM>250)
// will transmit EMPF2 and clear the pending flag.
return;
}
// Not immobiliser → fall back to standard 0x502 address→value handling
can_manager_rx_address_request(msg, in, tx);
}
void audi_immobiliser_register(void)
{
// Ensure we have a built payload
if (g_full_len == 0) audi_immobiliser_init();
// Hook our wrapper to the 0x502 definition (DB remains data-only)
can_manager_register_handler_msg(&MSG_ID_SEND2, audi_immo_502_wrapper);
}
*/