From 08b4427b9c844d3e9e594fb4561562b98a687f07 Mon Sep 17 00:00:00 2001 From: Benjamin Wiegand Date: Mon, 8 Sep 2025 16:50:29 -0700 Subject: [PATCH] allow overrides to be used in stat display --- CMakeLists.txt | 1 + battery.c | 83 +++++++++++++++++++++++++++++++---------------- config_override.h | 15 ++++++++- mitm.c | 66 ++++++++++++++++++++++++++++++++++++- mitm.h | 6 ++++ override.c | 38 ++++++++++++++++++++++ override.h | 30 +++++++++++++++++ smbus.h | 5 +++ 8 files changed, 214 insertions(+), 30 deletions(-) create mode 100644 override.c create mode 100644 override.h diff --git a/CMakeLists.txt b/CMakeLists.txt index efbec42..a7b750d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,7 @@ add_executable(BattMITM_2.0 smbus.c static_queue.c mitm.c + override.c status.c display.c font.c diff --git a/battery.c b/battery.c index c88bcc5..efb2b01 100644 --- a/battery.c +++ b/battery.c @@ -24,6 +24,8 @@ #include "battery.h" #include "config.h" #include "smbus.h" +#include "mitm.h" +#include "override.h" #include "hardware/sync.h" #include "pico/stdlib.h" #include @@ -74,6 +76,57 @@ void battery_stat_request_update(battery_stat_t* batt_stat) { } +void battery_update_stat(battery_stat_t* batt_stat) { + i2c_dev_t* bms = get_bms_dev(); + cmd_reply_override override = NULL; + int ret; + + printf("updating %02x (%s)\n", batt_stat->read_command, batt_stat->friendly_name); + + if (defused_use_read_command_reply_override(batt_stat->read_command)) { + override = get_read_command_reply_override(batt_stat->read_command); + if (override != NULL) printf("using read cmd override\n"); + } + + switch (batt_stat->type) { + case SBS_BYTES: + if (override != NULL) { + ret = mitm_smbus_read_with_override(bms, batt_stat->read_command, batt_stat->cached_result.as_uint8, batt_stat->max_result_length, false, override); + } else { + ret = smbus_read(bms, batt_stat->read_command, batt_stat->cached_result.as_uint8, batt_stat->max_result_length); + } + break; + case SBS_BLOCK: + if (override != NULL) { + ret = mitm_smbus_read_with_override(bms, batt_stat->read_command, batt_stat->cached_result.as_uint8, batt_stat->max_result_length, true, override); + } else { + ret = smbus_read_block(bms, batt_stat->read_command, batt_stat->cached_result.as_uint8, batt_stat->max_result_length); + } + break; + case SBS_STRING: + if (override != NULL) { + // ret = mitm_smbus_read_text_with_override(bms, batt_stat->read_command, batt_stat->cached_result.as_uint8, batt_stat->max_result_length, override); + ret = mitm_smbus_read_with_override(bms, batt_stat->read_command, batt_stat->cached_result.as_uint8, batt_stat->max_result_length, true, override); + } else { + ret = smbus_read_text(bms, batt_stat->read_command, batt_stat->cached_result.as_uint8, batt_stat->max_result_length); + } + break; + default: + return; + } + + if (ret < 0) { + batt_stat->result_valid = false; + } else { + batt_stat->result_valid = true; + batt_stat->result_length = ret; + batt_stat->update_requested = false; + } + + batt_stat->last_updated = time_us_64(); +} + + void battery_update_cache() { if (!battery_stat_need_cache_update) return; @@ -81,40 +134,14 @@ void battery_update_cache() { battery_stat_need_cache_update = false; - i2c_dev_t* bms = get_bms_dev(); battery_stat_t* batt_stat; - int ret; for (int i = 0; i < battery_stat_cache_size; i++) { batt_stat = &battery_stat_cache[i]; if (!batt_stat->update_requested) continue; if (batt_stat->last_updated + BATTERY_STAT_MIN_RETRY_PERIOD > time_us_64()) continue; - printf("update requested for %02x (%s)\n", batt_stat->read_command, batt_stat->friendly_name); - - switch (batt_stat->type) { - case SBS_BYTES: - ret = smbus_read(bms, batt_stat->read_command, batt_stat->cached_result.as_uint8, batt_stat->max_result_length); - break; - case SBS_BLOCK: - ret = smbus_read_block(bms, batt_stat->read_command, batt_stat->cached_result.as_uint8, batt_stat->max_result_length); - break; - case SBS_STRING: - ret = smbus_read_text(bms, batt_stat->read_command, batt_stat->cached_result.as_uint8, batt_stat->max_result_length); - break; - default: - continue; - } - - if (ret < 0) { - batt_stat->result_valid = false; - } else { - batt_stat->result_valid = true; - batt_stat->result_length = ret; - batt_stat->update_requested = false; - } - - batt_stat->last_updated = time_us_64(); + battery_update_stat(batt_stat); } battery_stat_unlock(); @@ -180,7 +207,7 @@ void init_battery() { create_battery_stat(BATT_CMD_MANUFACTURER_NAME, "manufacturer", 32, SBS_STRING, BATTERY_STAT_VALID_PERIOD_CONSTANT), create_battery_stat(BATT_CMD_DEVICE_NAME, "device name", 32, SBS_STRING, BATTERY_STAT_VALID_PERIOD_CONSTANT), create_battery_stat(BATT_CMD_DEVICE_CHEMISTRY, "chemistry", 16, SBS_STRING, BATTERY_STAT_VALID_PERIOD_CONSTANT), - create_battery_stat(BATT_CMD_MANUFACTURER_DATA, "manufacturer data", 14, SBS_BLOCK, BATTERY_STAT_VALID_PERIOD_CONSTANT), + create_battery_stat(BATT_CMD_MANUFACTURER_DATA, "manufacturer data", 14, SBS_BLOCK, BATTERY_STAT_VALID_PERIOD_DEFAULT), }; battery_stat_cache_size = sizeof(battery_stat_cache_init) / sizeof(battery_stat_t); battery_stat_cache = malloc(sizeof(battery_stat_cache_init)); diff --git a/config_override.h b/config_override.h index 9a23351..aeb5176 100644 --- a/config_override.h +++ b/config_override.h @@ -159,7 +159,7 @@ int override_example_modify_manufacturer_name(uint8_t cmd, uint8_t* reply_buffer // map command codes to override functions here // for a list of command code definitions see battery.h -cmd_reply_override get_read_command_reply_override(uint8_t cmd) { +cmd_reply_override config_get_read_command_reply_override(uint8_t cmd) { switch (cmd) { // examples: @@ -172,6 +172,19 @@ cmd_reply_override get_read_command_reply_override(uint8_t cmd) { } +// defines whether the gui (defused) will use the override instead of reading directly from the battery +bool config_defused_use_read_command_reply_override(uint8_t cmd) { + // you can write a switch statement here to change this behavior per command + return true; // use the override by default +} + + +// defines whether the uart interface (not yet implemented) will use the override instead of reading directly from the battery +bool config_uart_use_read_command_reply_override(uint8_t cmd) { + // you can write a switch statement here to change this behavior per command + return false; // don't use the override by default +} + diff --git a/mitm.c b/mitm.c index 858987e..1283529 100644 --- a/mitm.c +++ b/mitm.c @@ -29,7 +29,7 @@ #include "pico/stdlib.h" #include "hardware/irq.h" #include -#include "config_override.h" +#include "override.h" enum i2c_transfer_event { I2C_READ, @@ -339,3 +339,67 @@ void mitm_loop() { } +int mitm_smbus_read_with_override(i2c_dev_t* device, uint8_t cmd, uint8_t* result, size_t length, bool is_block, cmd_reply_override override) { + int ret; + uint8_t block_length; + + if (length > MITM_REPLY_BUFFER_SIZE - 1) return -1; + + printf("reading cmd 0x%02x with override\n", cmd); + + // set up for read cmd + mitm_cmd_buffer[0] = cmd; + mitm_cmd_buffer_index = 1; + + ret = i2c_write_timeout_us(device->i2c, device->address, mitm_cmd_buffer, mitm_cmd_buffer_index, true, device->timeout); + if (ret < 0) { + printf("failed, write returned %d\n", ret); + return SMBUS_ERROR_DEVICE; + } + + + ret = override(cmd, mitm_reply_buffer); + i2c_stop_read_blocking(device); + if (ret < 0) { + printf("failed, override returned %d\n", ret); + return SMBUS_ERROR_CRC; // pretend it was corrupted + } + + // read the result from the buffer like the laptop would + + if (is_block) { + block_length = mitm_reply_buffer[0]; + if (block_length > MITM_REPLY_BUFFER_SIZE - 2) { + printf("failed, block length %d doesn't fit in reply buffer size!", block_length); + return SMBUS_ERROR_CRC; + } + if (block_length > length) { + printf("failed, block length %d is larger than max result length %d!", block_length, length); + return SMBUS_ERROR_CRC; + } + } + + if (!mitm_validate_batt_reply(mitm_reply_buffer, is_block ? block_length + 1 : length, is_block)) return SMBUS_ERROR_CRC; + + // copy to result buffer + for (uint i = 0; i < (is_block ? block_length : length); i++) { + result[i] = is_block ? mitm_reply_buffer[i + 1] : mitm_reply_buffer[i]; + } + + return is_block ? block_length : length; +} + +int mitm_smbus_read_text_with_override(i2c_dev_t* device, uint8_t cmd, char* result, size_t max_length, cmd_reply_override override) { + int ret; + + ret = mitm_smbus_read_with_override(device, cmd, result, max_length, true, override); + if (ret < 0) return ret; + + // search for possible null termination + for (int i = 0; i < ret; i++) { + if (result[i] == 0x00) return i; + } + + return ret; +} + diff --git a/mitm.h b/mitm.h index df80b24..6ce9de0 100644 --- a/mitm.h +++ b/mitm.h @@ -21,6 +21,7 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include "smbus.h" #include #include #include @@ -60,3 +61,8 @@ int mitm_generate_reply_crc(uint8_t* buffer, uint8_t crc_index, bool is_block); void init_mitm(); void mitm_loop(); + + +// like the smbus read functions but applies an override +int mitm_smbus_read_with_override(i2c_dev_t* device, uint8_t cmd, uint8_t* result, size_t length, bool is_block, cmd_reply_override override); +int mitm_smbus_read_text_with_override(i2c_dev_t* device, uint8_t cmd, char* result, size_t max_length, cmd_reply_override override); diff --git a/override.c b/override.c new file mode 100644 index 0000000..aa06e93 --- /dev/null +++ b/override.c @@ -0,0 +1,38 @@ +/** + MIT License + + Copyright (c) 2025 Benjamin Wiegand + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. + */ +#include "override.h" +#include "config_override.h" + + +cmd_reply_override get_read_command_reply_override(uint8_t cmd) { + return config_get_read_command_reply_override(cmd); +} + +bool defused_use_read_command_reply_override(uint8_t cmd) { + return config_defused_use_read_command_reply_override(cmd); +} + +bool uart_use_read_command_reply_override(uint8_t cmd) { + return config_uart_use_read_command_reply_override(cmd); +} diff --git a/override.h b/override.h new file mode 100644 index 0000000..b11f85f --- /dev/null +++ b/override.h @@ -0,0 +1,30 @@ +/** + MIT License + + Copyright (c) 2025 Benjamin Wiegand + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. + */ +#include "mitm.h" +#include + +cmd_reply_override get_read_command_reply_override(uint8_t cmd); + +bool defused_use_read_command_reply_override(uint8_t cmd); +bool uart_use_read_command_reply_override(uint8_t cmd); diff --git a/smbus.h b/smbus.h index b04f066..c138fda 100644 --- a/smbus.h +++ b/smbus.h @@ -30,6 +30,9 @@ #define SMBUS_ERROR_CRC -3 +#ifndef I2C_DEV_DEF +#define I2C_DEV_DEF + struct i2c_dev { i2c_inst_t* i2c; uint8_t address; @@ -38,6 +41,8 @@ struct i2c_dev { typedef struct i2c_dev i2c_dev_t; +#endif + i2c_dev_t* get_bms_dev(); i2c_dev_t* get_laptop_dev();