From 4c394202c01c2d57ea5fa55fe12bdaca11cd4378 Mon Sep 17 00:00:00 2001 From: Jacob Eva Date: Thu, 31 Jul 2025 19:08:40 +0100 Subject: [PATCH] Bugfixing and extension of functions --- src/librnode.c | 116 ++++++++++++++++++++++++++++++++++--------------- src/librnode.h | 50 ++++++++++++++++++++- tests/test.c | 66 ++++++++++++++++++++++------ 3 files changed, 183 insertions(+), 49 deletions(-) diff --git a/src/librnode.c b/src/librnode.c index 7a8b0e4..c648fe8 100755 --- a/src/librnode.c +++ b/src/librnode.c @@ -129,23 +129,11 @@ int rnode_handle_resp(struct RNode* rn, bool* in_frame, uint8_t* cmd, uint8_t* c } } } else if (*cmd == CMD_INTERFACES) { - if (sbyte == FESC) { - escape = true; - } else { - if (escape) { - if (sbyte == TFEND) { - sbyte = FEND; - } else if (sbyte == TFESC) { - sbyte = FESC; - } - escape = false; - } - cmd_buf[*cmd_buf_l] = sbyte; - (*cmd_buf_l)++; - if (*cmd_buf_l == 2) { - rn->interfaces[cmd_buf[0]] = cmd_buf[1]; - *cmd_buf_l = 0; - } + cmd_buf[*cmd_buf_l] = sbyte; + (*cmd_buf_l)++; + if (*cmd_buf_l == 2) { + rn->interfaces[cmd_buf[0]] = cmd_buf[1]; + *cmd_buf_l = 0; } } else if (*cmd == CMD_FREQUENCY) { if (sbyte == FESC) { @@ -233,6 +221,8 @@ int rnode_handle_resp(struct RNode* rn, bool* in_frame, uint8_t* cmd, uint8_t* c rn->lt_alock = at / 100.0; *cmd_buf_l = 0; } + } else if (*cmd == CMD_RADIO_STATE) { + rn->int_state[rn->sel_int] = sbyte; } else if (*cmd == CMD_ROM_READ) { if (sbyte == FESC) { escape = true; @@ -283,15 +273,15 @@ int rnode_handle_resp(struct RNode* rn, bool* in_frame, uint8_t* cmd, uint8_t* c */ int rnode_detect(struct RNode* rn) { int err_code; - uint8_t tx_buf[20]; + uint8_t tx_buf[16]; bool in_frame = false; uint8_t cmd = CMD_UNKNOWN; uint8_t cmd_buf[10] = {0}; uint8_t cmd_buf_l = 0; uint16_t frame_len = 0; - memcpy(tx_buf, (uint8_t[20]){FEND, CMD_DETECT, DETECT_REQ, FEND, FEND, CMD_FW_VERSION, 0x00, FEND, FEND, CMD_PLATFORM, 0x00, FEND, FEND, CMD_MCU, 0x00, FEND, FEND, CMD_INTERFACES, 0x00, FEND}, 20*sizeof(uint8_t)); - err_code = write_port(rn->fd, tx_buf, 20); + memcpy(tx_buf, (uint8_t[16]){FEND, CMD_DETECT, DETECT_REQ, FEND, FEND, CMD_FW_VERSION, 0x00, FEND, FEND, CMD_PLATFORM, 0x00, FEND, FEND, CMD_MCU, 0x00, FEND}, 16*sizeof(uint8_t)); + err_code = write_port(rn->fd, tx_buf, 16); if (!err_code) { sleep_ms(100); err_code = rnode_handle_resp(rn, &in_frame, &cmd, cmd_buf, &cmd_buf_l, &frame_len); @@ -541,8 +531,14 @@ int rnode_get_interfaces(struct RNode* rn) { sleep_ms(100); err_code = rnode_handle_resp(rn, &in_frame, &cmd, cmd_buf, &cmd_buf_l, &frame_len); } + + if (err_code > 0) { + return 0; + } else { + return err_code; + } + - return err_code; } /* Radio configuration functions */ @@ -739,8 +735,8 @@ int rnode_set_txp(struct RNode* rn, uint8_t txp) { if (!err_code) { sleep_ms(100); err_code = rnode_handle_resp(rn, &in_frame, &cmd, cmd_buf, &cmd_buf_l, &frame_len); - if (!err_code) { - return rn->txp; + if (err_code > 0) { + return txp == rn->txp ? 0 : -1; } else { return err_code; } @@ -803,8 +799,8 @@ int rnode_set_sf(struct RNode* rn, uint8_t sf) { if (!err_code) { sleep_ms(100); err_code = rnode_handle_resp(rn, &in_frame, &cmd, cmd_buf, &cmd_buf_l, &frame_len); - if (!err_code) { - return rn->sf; + if (err_code > 0) { + return sf == rn->sf ? 0 : -1; } else { return err_code; } @@ -816,6 +812,7 @@ int rnode_set_sf(struct RNode* rn, uint8_t sf) { /* Get spreading factor on an RNode * Scope: public * Returns + * >=5 - spreading factor * 0 - success * -1 - generic error */ @@ -867,8 +864,8 @@ int rnode_set_cr(struct RNode* rn, uint8_t cr) { if (!err_code) { sleep_ms(100); err_code = rnode_handle_resp(rn, &in_frame, &cmd, cmd_buf, &cmd_buf_l, &frame_len); - if (!err_code) { - return rn->cr; + if (err_code > 0) { + return cr == rn->cr ? 0 : -1; } else { return err_code; } @@ -880,6 +877,7 @@ int rnode_set_cr(struct RNode* rn, uint8_t cr) { /* Get coding rate on an RNode * Scope: public * Returns + * >=5 - coding rate * 0 - success * -1 - generic error */ @@ -899,7 +897,7 @@ int rnode_get_cr(struct RNode* rn) { if (!err_code) { sleep_ms(100); err_code = rnode_handle_resp(rn, &in_frame, &cmd, cmd_buf, &cmd_buf_l, &frame_len); - if (!err_code) { + if (err_code > 0) { return rn->cr; } else { return err_code; @@ -934,8 +932,8 @@ float rnode_set_st_alock(struct RNode* rn, float at_l) { if (!err_code) { sleep_ms(100); err_code = rnode_handle_resp(rn, &in_frame, &cmd, cmd_buf, &cmd_buf_l, &frame_len); - if (!err_code) { - return rn->st_alock; + if (err_code > 0) { + return at_l == rn->st_alock ? 0 : -1; } else { return err_code; } @@ -969,8 +967,8 @@ float rnode_set_lt_alock(struct RNode* rn, float at_l) { if (!err_code) { sleep_ms(100); err_code = rnode_handle_resp(rn, &in_frame, &cmd, cmd_buf, &cmd_buf_l, &frame_len); - if (!err_code) { - return rn->lt_alock; + if (err_code > 0) { + return at_l == rn->lt_alock ? 0 : -1; } else { return err_code; } @@ -979,6 +977,48 @@ float rnode_set_lt_alock(struct RNode* rn, float at_l) { } } +/* Start or stop selected interface on an RNode + * Scope: public + * Returns + * 0 - success + * -1 - generic error + */ +int rnode_set_interface_state(struct RNode* rn, bool state) { + int err_code; + uint8_t tx_buf[4]; + bool in_frame = false; + uint8_t cmd = CMD_UNKNOWN; + uint8_t cmd_buf[10] = {0}; + uint8_t cmd_buf_l = 0; + uint16_t frame_len = 0; + + memcpy(tx_buf, (uint8_t[4]){FEND, CMD_RADIO_STATE, state, FEND}, 4*sizeof(uint8_t)); + + err_code = write_port(rn->fd, tx_buf, 4); + + if (!err_code) { + sleep_ms(100); + err_code = rnode_handle_resp(rn, &in_frame, &cmd, cmd_buf, &cmd_buf_l, &frame_len); + if (err_code > 0) { + return state == rn->int_state[rn->sel_int] ? 0 : -1; + } else { + return err_code; + } + } else { + return err_code; + } +} + +/* Get selected interface state on an RNode + * Scope: public + * Returns + * 0 - success + * -1 - generic error + */ +int rnode_get_interface_state(struct RNode* rn) { + return rn->int_state[rn->sel_int]; +} + /* Mode selection functions */ /* Enable the host-controlled (normal) mode of operation on an RNode @@ -1115,6 +1155,12 @@ int rnode_set_hw_rev(struct RNode* rn, uint8_t hw_rev) { return rnode_write_eeprom(rn, ADDR_HW_REV, hw_rev); } +/* Sets an RNode's serial in its EEPROM + * Scope: public + * Returns + * 0 - success + * -1 - generic error + */ int rnode_set_serial(struct RNode* rn, uint8_t* serial) { int err_code = 0; for (int i = 0; i < 4; i++) { @@ -1206,6 +1252,7 @@ int rnode_set_checksum(struct RNode* rn, uint8_t* checksum) { } /* Generate's an RNode's EEPROM signature from the checksum + * THE RETURNED POINTER MUST BE free()'D! * Scope: public * Returns * 0 - success @@ -1327,7 +1374,7 @@ int rnode_dump_eeprom(struct RNode* rn) { uint8_t tx_buf[4]; bool in_frame = false; uint8_t cmd = CMD_UNKNOWN; - uint8_t cmd_buf[10] = {0}; + uint8_t cmd_buf[256] = {0}; uint8_t cmd_buf_l = 0; uint16_t frame_len = 0; @@ -1335,10 +1382,11 @@ int rnode_dump_eeprom(struct RNode* rn) { err_code = write_port(rn->fd, tx_buf, 4); if (!err_code) { + sleep_ms(100); err_code = rnode_handle_resp(rn, &in_frame, &cmd, cmd_buf, &cmd_buf_l, &frame_len); } - return err_code; + return err_code > 0 ? 0 : -1; } /* Verify an RNode's EEPROM matches the expected values diff --git a/src/librnode.h b/src/librnode.h index a2db305..2c3138d 100644 --- a/src/librnode.h +++ b/src/librnode.h @@ -120,6 +120,8 @@ struct RNode { uint8_t interfaces[MAX_INTERFACES]; + uint8_t int_state[MAX_INTERFACES]; + // void (*prog_cb)(uint8_t); @@ -340,13 +342,22 @@ float rnode_set_st_alock(struct RNode* rn, float at_l); */ float rnode_set_lt_alock(struct RNode* rn, float at_l); -/* Set radio modem state (on or off) + +/* Start or stop selected interface on an RNode * Scope: public * Returns * 0 - success * -1 - generic error */ -int rnode_set_radio_state(struct RNode* rn, bool state); +int rnode_set_interface_state(struct RNode* rn, bool state); + +/* Get selected interface state on an RNode + * Scope: public + * Returns + * 0 - success + * -1 - generic error + */ +int rnode_get_interface_state(struct RNode* rn); /* Mode selection functions */ @@ -400,6 +411,41 @@ int rnode_set_model(struct RNode* rn, uint8_t model); */ int rnode_set_hw_rev(struct RNode* rn, uint8_t hw_rev); +/* Sets an RNode's serial in its EEPROM + * Scope: public + * Returns + * 0 - success + * -1 - generic error + */ +int rnode_set_serial(struct RNode* rn, uint8_t* serial); + +/* Sets an RNode's manufacture time in its EEPROM + * Scope: public + * Returns + * 0 - success + * -1 - generic error + */ +int rnode_set_made_time(struct RNode* rn, uint32_t time); + +/* Calculates an RNode's checksum for its EEPROM. Must ONLY be called AFTER + * rnode_set_product, rnode_set_model, rnode_set_hw_rev, rnode_set_serial and + * rnode_set_made_time are all called. OR alternatively, after rnode_get_eeprom. + * Scope: public + * Returns + * 0 - success + * -1 - generic error + * -3 - provided array was too small + */ +int rnode_calculate_checksum(struct RNode* rn, uint8_t* checksum); + +/* Sets an RNode's checksum in its EEPROM + * Scope: public + * Returns + * 0 - success + * -1 - generic error + */ +int rnode_set_checksum(struct RNode* rn, uint8_t* checksum); + /* Generate's an RNode's EEPROM signature from the checksum * Scope: public * Returns diff --git a/tests/test.c b/tests/test.c index 17aaf1c..a2eeb3c 100644 --- a/tests/test.c +++ b/tests/test.c @@ -15,11 +15,11 @@ char* port = "/dev/ttyACM0"; //char* port = "/dev/serial/by-id/usb-Heltec_HT-n5262_1E35113239EFFE55-if00"; char* zip = "/home/elimin8/Downloads/rnode_firmware_t3s3_sx1280_pa.zip"; -char* key = "/home/elimin8/.config/rnodeconf/firmware/signing.key"; +char* key = "/home/jake/.config/rnodeconf/firmware/signing.key"; uint32_t baud = 115200; struct RNode rn = {0}; -EVP_PKEY* load_key(struct RNode* rn, char* path) { +EVP_PKEY* load_key(char* path) { EVP_PKEY *priv_key = EVP_PKEY_new(); OSSL_DECODER_CTX *dctx; const char *format = "DER"; /* NULL for any format */ @@ -68,7 +68,7 @@ void esp32_flash(struct RNode* rn, char* zip) { ok(rnode_set_platform(rn, PLATFORM_ESP32) == 0, "RNode set platform"); time_t start = time(NULL); - EVP_PKEY *priv_key = load_key(rn, key); + EVP_PKEY *priv_key = load_key(key); ok(priv_key != NULL, "Load EEPROM signing key"); rn->product = 0xf0; rn->model = 0xac; @@ -89,7 +89,7 @@ void nrf52_flash(struct RNode* rn, char* zip) { ok(rnode_set_platform(rn, PLATFORM_NRF52) == 0, "RNode set platform"); time_t start = time(NULL); - EVP_PKEY *priv_key = load_key(rn, key); + EVP_PKEY *priv_key = load_key(key); ok(priv_key != NULL, "Load EEPROM signing key"); rn->product = 0x10; rn->model = 0x12; @@ -100,10 +100,10 @@ void nrf52_flash(struct RNode* rn, char* zip) { } int main() { - //printf("--- RNode reset test ---\n\n"); ok(rnode_init(&rn, port, baud, true, false) == 0, "RNode initialisation & detection"); + //printf("--- RNode reset test ---\n\n"); //ok(rnode_reset(&rn) == 0, "RNode reset"); //sleep_ms(5000); @@ -186,21 +186,61 @@ int main() { //printf("--- RNode flash & provision test ---\n\n"); - printf("--- RNode TNC mode test ---\n\n"); + //printf("--- RNode TNC mode test ---\n\n"); - ok(rnode_get_interfaces(&rn) == 0, "Get interfaces"); + //ok(rnode_get_interfaces(&rn) == 0, "Get interfaces"); - ok(rnode_select_interface(&rn, 0) == 0, "Select interface 0"); + //ok(rnode_select_interface(&rn, 0) == 0, "Select interface 0"); - ok(rnode_set_freq(&rn, 865700000) > 0, "Set frequency"); + //ok(rnode_set_freq(&rn, 865700000) > 0, "Set frequency"); - ok(rnode_set_sf(&rn, 7) == 0, "Set spreading factor"); + //ok(rnode_set_sf(&rn, 7) == 0, "Set spreading factor"); - ok(rnode_set_cr(&rn, 7) == 0, "Set coding rate"); + //ok(rnode_set_cr(&rn, 7) == 0, "Set coding rate"); - ok(rnode_set_txp(&rn, 7) == 0, "Set TX power"); + //ok(rnode_set_txp(&rn, 7) == 0, "Set TX power"); - ok(rnode_set_tnc_mode(&rn) == 0, "Enable TNC mode"); + //ok(rnode_set_st_alock(&rn, 10) == 0, "Set ST alock"); + + //ok(rnode_set_lt_alock(&rn, 10) == 0, "Set LT alock"); + + //ok(rnode_set_interface_state(&rn, true) == 0, "Enable radio interface"); + + //ok(rnode_set_tnc_mode(&rn) == 0, "Enable TNC mode"); + + //printf("--- RNode EEPROM read test ---\n\n"); + + //ok(rnode_get_eeprom(&rn) == 0, "Retrieve EEPROM"); + + printf("--- RNode EEPROM provision test ---\n\n"); + + ok(rnode_set_product(&rn, 0x20) == 0, "Set EEPROM product"); + + ok(rnode_set_model(&rn, 0x21) == 0, "Set EEPROM product"); + + ok(rnode_set_hw_rev(&rn, 0x01) == 0, "Set hardware revision"); + + uint8_t serial[4] = {0}; + + ok(rnode_set_serial(&rn, serial) == 0, "Set serial"); + + ok(rnode_set_made_time(&rn, 3200) == 0, "Set manufacture time & date"); + + uint8_t checksum[11] = {0}; + + ok(rnode_calculate_checksum(&rn, checksum) == 0, "Calculate checksum"); + + ok(rnode_set_checksum(&rn, checksum) == 0, "Set checksum"); + + EVP_PKEY *priv_key = load_key(key); + + void* signature = rnode_generate_signature(&rn, priv_key); + + ok(signature != NULL, "Generate signature"); + + ok(rnode_set_signature(&rn, signature) == 0, "Set signature"); + + free(signature); ok(rnode_cleanup(&rn) == 0, "RNode cleanup");