523 lines
11 KiB
C
523 lines
11 KiB
C
/* Copyright (c) 2025 - Jacob Eva (Liberated Embedded Systems)
|
|
* This program is free software: you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the Free
|
|
* Software Foundation, either version 3 of the License, or (at your option)
|
|
* any later version.
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef LIBRNODE_H
|
|
|
|
#define LIBRNODE_H
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <openssl/evp.h>
|
|
#include <openssl/rsa.h>
|
|
|
|
#define MIN_FW_VER 1.66
|
|
|
|
// PLATFORMS
|
|
#define PLATFORM_ESP32 0x80
|
|
#define PLATFORM_NRF52 0x70
|
|
//
|
|
|
|
#define SERIAL_SIZE 4
|
|
|
|
#define MADE_SIZE 4
|
|
|
|
#define CHECKSUM_SIZE 16
|
|
|
|
#define SIGNATURE_SIZE 128
|
|
|
|
#define FW_HASH_SIZE 256 / 8
|
|
|
|
#define RESP_BUF_SIZE 512
|
|
|
|
#define EEPROM_SIZE 296
|
|
|
|
#define MAX_INTERFACES 256
|
|
|
|
#define FILE_MAX_SIZE 4 * 1024 * 1024 // 4MB max file size for single fw binary
|
|
|
|
// BLUETOOTH VALUES
|
|
#define BT_OFF 0
|
|
#define BT_ON 1
|
|
#define BT_PAIRING 2
|
|
//
|
|
|
|
struct RNode {
|
|
char* port;
|
|
int fd;
|
|
uint32_t baud;
|
|
|
|
uint8_t platform;
|
|
uint8_t mcu;
|
|
|
|
// EEPROM below here!
|
|
|
|
uint8_t product;
|
|
uint8_t model;
|
|
uint8_t hw_rev;
|
|
|
|
uint8_t serial[4];
|
|
|
|
uint8_t made[4];
|
|
|
|
uint8_t checksum[16];
|
|
|
|
uint8_t signature[128];
|
|
|
|
uint8_t lock_byte;
|
|
|
|
// All these have their own getter functions as they can change on runtime; the cached EEPROM values may not reflect the true status of the radio
|
|
uint8_t sf;
|
|
uint8_t cr;
|
|
uint8_t txp;
|
|
uint32_t bw;
|
|
uint32_t freq;
|
|
|
|
uint8_t cfg_ok;
|
|
|
|
bool bt;
|
|
|
|
bool disp_set;
|
|
uint8_t disp_int;
|
|
uint8_t disp_addr;
|
|
|
|
// This is where the EEPROM read directly from the RNode is stored
|
|
uint8_t r_eeprom[EEPROM_SIZE];
|
|
|
|
// END EEPROM
|
|
|
|
float st_alock;
|
|
float lt_alock;
|
|
|
|
uint32_t bt_pairing_pin;
|
|
|
|
// ESP32 only!
|
|
|
|
uint32_t boot_app0_addr;
|
|
uint32_t bootloader_addr;
|
|
uint32_t bin_addr;
|
|
uint32_t partitions_addr;
|
|
uint32_t console_image_addr;
|
|
|
|
//
|
|
|
|
float fw_ver;
|
|
|
|
bool connected;
|
|
|
|
// Multiple modems
|
|
|
|
uint8_t sel_int;
|
|
|
|
uint8_t interfaces[MAX_INTERFACES];
|
|
|
|
uint8_t int_state[MAX_INTERFACES];
|
|
|
|
//
|
|
|
|
void (*prog_cb)(uint8_t);
|
|
};
|
|
|
|
/* Establishes communication with an RNode
|
|
* Params: port (e.g. /dev/ttyACM0), baud rate (e.g. 115200), detect (attempt
|
|
* to communicate with RNode), force_detect (fail if cannot communicate with
|
|
* RNode)
|
|
* Scope: public
|
|
* Returns:
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_init(struct RNode* rn, char* path, uint32_t baud, bool detect, bool force_detect);
|
|
|
|
/* Resets an RNode
|
|
* Scope: public
|
|
* Returns:
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_reset(struct RNode* rn);
|
|
|
|
/* Sets an RNode's platform attribute manually
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_set_platform(struct RNode* rn, uint8_t platform);
|
|
|
|
/* Enable / disable Bluetooth on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* > 0 - bluetooth pairing pin value
|
|
* 0 - success
|
|
* -1 - generic error
|
|
* -4 - rnode did not respond
|
|
*/
|
|
int rnode_set_bt(struct RNode* rn, uint8_t val);
|
|
|
|
/* Attempt to retrieve the BT pairing code of an RNode. Blocking function,
|
|
* should be run in a separate thread.
|
|
* Params: timeout (in ms, minimum value 200)
|
|
* Scope: public
|
|
* Returns
|
|
* > 0 - bluetooth pairing code
|
|
* 0 - success
|
|
* -1 - generic error
|
|
* -4 - rnode did not respond
|
|
*/
|
|
int rnode_get_bt_pin(struct RNode* rn, uint32_t timeout);
|
|
|
|
/* Display related functions */
|
|
|
|
/* Set display intensity on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_set_disp_int(struct RNode* rn, uint8_t disp_int);
|
|
|
|
/* Set display timeout on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_set_disp_timeout(struct RNode* rn, uint8_t timeout);
|
|
|
|
/* Set display address on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_set_disp_addr(struct RNode* rn, uint8_t addr);
|
|
|
|
#define DISPLAY_PORTRAIT 0
|
|
#define DISPLAY_LANDSCAPE 1
|
|
#define DISPLAY_PORTRAIT_INV 2
|
|
#define DISPLAY_LANDSCAPE_INV 3
|
|
/* Set display rotation on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_set_disp_rot(struct RNode* rn, uint8_t rot);
|
|
|
|
/* Start display reconditioning on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_start_disp_recon(struct RNode* rn);
|
|
|
|
/* Set neopixel intensity on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_set_np_int(struct RNode* rn, uint8_t np_int);
|
|
|
|
/* Get available interfaces on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_get_interfaces(struct RNode* rn);
|
|
|
|
/* Select interface on an RNode (in preparation for running rnode_set_freq, etc)
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_select_interface(struct RNode* rn, uint8_t modem);
|
|
|
|
/* Set frequency on an RNode (in preparation for TNC mode)
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_set_freq(struct RNode* rn, uint32_t freq);
|
|
|
|
/* Get frequency on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_get_freq(struct RNode* rn);
|
|
|
|
/* Set bandwidth on an RNode (in preparation for TNC mode)
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_set_bw(struct RNode* rn, uint32_t bw);
|
|
|
|
/* Get bandwidth on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_get_bw(struct RNode* rn);
|
|
|
|
/* Set transmission power on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_set_txp(struct RNode* rn, uint8_t txp);
|
|
|
|
/* Get transmission power on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_get_txp(struct RNode* rn);
|
|
|
|
/* Set spreading factor on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_set_sf(struct RNode* rn, uint8_t sf);
|
|
|
|
/* Get spreading factor on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_get_sf(struct RNode* rn);
|
|
|
|
/* Set coding rate on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_set_cr(struct RNode* rn, uint8_t cr);
|
|
|
|
/* Get coding rate on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_get_cr(struct RNode* rn);
|
|
|
|
/* Set short term airtime limit on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
float rnode_set_st_alock(struct RNode* rn, float at_l);
|
|
|
|
/* Set long term airtime limit on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
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);
|
|
|
|
/* 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 */
|
|
|
|
/* Enable the host-controlled (normal) mode of operation on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_set_normal_mode(struct RNode* rn);
|
|
|
|
/* Enable the serial TNC mode of operation on an RNode
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_set_tnc_mode(struct RNode* rn);
|
|
|
|
/* EEPROM related functions */
|
|
|
|
/* Sets the firmware hash on an RNode.
|
|
* Scope: public
|
|
* Returns:
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_set_fw_hash(struct RNode* rn, uint8_t* hash);
|
|
|
|
/* Sets an RNode's product in its EEPROM
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_set_product(struct RNode* rn, uint8_t product);
|
|
|
|
/* Sets an RNode's model in its EEPROM
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_set_model(struct RNode* rn, uint8_t model);
|
|
|
|
/* Sets an RNode's hardware revision in its EEPROM
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
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
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
void* rnode_generate_signature(struct RNode* rn, EVP_PKEY *signing_key);
|
|
|
|
/* Sets an RNode's signature in its EEPROM
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_set_signature(struct RNode* rn, uint8_t* data);
|
|
|
|
/* Sets an RNode's lock byte in its EEPROM
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_set_lock(struct RNode* rn);
|
|
|
|
/* Retrieve an RNode's EEPROM values into its struct
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_get_eeprom(struct RNode* rn);
|
|
|
|
/* Dump an RNode's entire EEPROM to r_eeprom
|
|
* Note: This will populate r_eeprom but not the cached EEPROM values. If you
|
|
* want to update the cached values, call rnode_get_eeprom instead.
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* -1 - generic error
|
|
*/
|
|
int rnode_dump_eeprom(struct RNode* rn);
|
|
|
|
/* Verify an RNode's EEPROM matches the expected values
|
|
* Scope: public
|
|
* Returns
|
|
* 0 - success
|
|
* value > 0 or value < 0 - EEPROM invalid
|
|
*/
|
|
int rnode_verify_eeprom(struct RNode* rn);
|
|
|
|
/* Wipes an RNode's EEPROM.
|
|
* Scope: public
|
|
* Returns:
|
|
* 0 - success
|
|
* -1 - generic error
|
|
* -2 - rnode not supported (firmware too old, please update)
|
|
*/
|
|
int rnode_wipe_eeprom(struct RNode* rn);
|
|
|
|
|
|
/* Flashes an RNode.
|
|
* Scope: public
|
|
* Returns:
|
|
* 0 - success
|
|
* -1 - generic error
|
|
* -9 - ESP32 image invalid, SHA256 digest incorrect
|
|
*/
|
|
int rnode_flash(struct RNode* rn, char* zip_path, bool update, uint8_t* serial, EVP_PKEY* priv_key, bool touch);
|
|
|
|
|
|
int rnode_cleanup(struct RNode* rn);
|
|
|
|
|
|
#endif
|