summaryrefslogtreecommitdiff
path: root/plugins/packet_radio/tnc_profiles.c
diff options
context:
space:
mode:
authorinfo@mode42.com <info@mode42.com>2026-08-08 03:54:55 +0000
committerinfo@mode42.com <info@mode42.com>2026-08-08 03:54:55 +0000
commit20cb29c2f8c5c87bc590896854a20b1473ceb358 (patch)
tree2857f41513a56ad41af97b57362639298aa7f033 /plugins/packet_radio/tnc_profiles.c
#2
Diffstat (limited to 'plugins/packet_radio/tnc_profiles.c')
-rw-r--r--plugins/packet_radio/tnc_profiles.c399
1 files changed, 399 insertions, 0 deletions
diff --git a/plugins/packet_radio/tnc_profiles.c b/plugins/packet_radio/tnc_profiles.c
new file mode 100644
index 0000000..05a2397
--- /dev/null
+++ b/plugins/packet_radio/tnc_profiles.c
@@ -0,0 +1,399 @@
+#include "hybbx/tnc.h"
+#include "hybbx/log.h"
+
+#include <stdio.h>
+
+const char *hybbx_packet_radio_duplex_name(hybbx_packet_radio_duplex_t duplex)
+{
+ switch (duplex) {
+ case HYBBX_PACKET_RADIO_DUPLEX_FULL:
+ return "full";
+ case HYBBX_PACKET_RADIO_DUPLEX_HALF:
+ return "half";
+ case HYBBX_PACKET_RADIO_DUPLEX_UNSET:
+ default:
+ return "unset";
+ }
+}
+
+const char *hybbx_packet_radio_band_name(hybbx_packet_radio_band_t band)
+{
+ switch (band) {
+ case HYBBX_PACKET_RADIO_BAND_CB:
+ return "cb";
+ case HYBBX_PACKET_RADIO_BAND_AMATEUR:
+ return "amateur";
+ case HYBBX_PACKET_RADIO_BAND_UNSET:
+ default:
+ return "unset";
+ }
+}
+
+const char *hybbx_packet_radio_modulation_name(
+ hybbx_packet_radio_modulation_t modulation)
+{
+ switch (modulation) {
+ case HYBBX_PACKET_RADIO_MOD_G3RUH_FSK:
+ return "g3ruh_fsk";
+ case HYBBX_PACKET_RADIO_MOD_AFSK:
+ return "afsk";
+ case HYBBX_PACKET_RADIO_MOD_UNSET:
+ default:
+ return "unset";
+ }
+}
+
+int hybbx_packet_radio_modulation_is_g3ruh(
+ hybbx_packet_radio_modulation_t modulation)
+{
+ return modulation == HYBBX_PACKET_RADIO_MOD_G3RUH_FSK;
+}
+
+hybbx_result_t hybbx_tnc_finalize_modulation(hybbx_packet_radio_config_t *cfg)
+{
+ if (cfg == NULL) {
+ return HYBBX_ERR_INVALID;
+ }
+
+ if (cfg->params.modulation == HYBBX_PACKET_RADIO_MOD_UNSET) {
+ cfg->params.modulation = HYBBX_PACKET_RADIO_MOD_AFSK;
+ }
+
+ if (cfg->params.modulation == HYBBX_PACKET_RADIO_MOD_G3RUH_FSK) {
+ cfg->params.modem = HYBBX_TNC2C_MODEM_9600;
+ cfg->params.radio_baud = HYBBX_G3RUH_RADIO_BAUD;
+ if (cfg->tnc == HYBBX_PACKET_RADIO_TNC_TNC2C &&
+ cfg->params.clock_mhz <= HYBBX_TNC2C_CLOCK_4_9_MHZ) {
+ cfg->params.clock_mhz = HYBBX_TNC2C_CLOCK_9_8_MHZ;
+ }
+ cfg->params.txdelay = 15;
+ cfg->params.persist = 128;
+ cfg->params.slot = 3;
+ return HYBBX_OK;
+ }
+
+ if (cfg->params.radio_baud == 0) {
+ cfg->params.radio_baud = HYBBX_AFSK_RADIO_BAUD;
+ }
+ if (cfg->params.modem == 0) {
+ cfg->params.modem = HYBBX_TNC2C_MODEM_TCM3105;
+ }
+
+ return HYBBX_OK;
+}
+
+static hybbx_packet_radio_band_t default_band_for_tnc(hybbx_packet_radio_tnc_t tnc)
+{
+ switch (tnc) {
+ case HYBBX_PACKET_RADIO_TNC_PCCOM:
+ case HYBBX_PACKET_RADIO_TNC_BAYCOM:
+ return HYBBX_PACKET_RADIO_BAND_CB;
+ case HYBBX_PACKET_RADIO_TNC_TNC2C:
+ case HYBBX_PACKET_RADIO_TNC_TNC2:
+ case HYBBX_PACKET_RADIO_TNC_PK232:
+ case HYBBX_PACKET_RADIO_TNC_MFJ1278:
+ case HYBBX_PACKET_RADIO_TNC_KANTRONICS:
+ case HYBBX_PACKET_RADIO_TNC_GENERIC:
+ default:
+ return HYBBX_PACKET_RADIO_BAND_AMATEUR;
+ }
+}
+
+const char *hybbx_packet_radio_tnc_name(hybbx_packet_radio_tnc_t tnc)
+{
+ switch (tnc) {
+ case HYBBX_PACKET_RADIO_TNC_BAYCOM:
+ return "baycom";
+ case HYBBX_PACKET_RADIO_TNC_PCCOM:
+ return "pccom";
+ case HYBBX_PACKET_RADIO_TNC_GENERIC:
+ return "generic";
+ case HYBBX_PACKET_RADIO_TNC_TNC2:
+ return "tnc2";
+ case HYBBX_PACKET_RADIO_TNC_PK232:
+ return "pk232";
+ case HYBBX_PACKET_RADIO_TNC_MFJ1278:
+ return "mfj1278";
+ case HYBBX_PACKET_RADIO_TNC_KANTRONICS:
+ return "kantronics";
+ case HYBBX_PACKET_RADIO_TNC_TNC2C:
+ default:
+ return "tnc2c";
+ }
+}
+
+const char *hybbx_kiss_entry_name(hybbx_kiss_entry_t entry)
+{
+ switch (entry) {
+ case HYBBX_KISS_ENTRY_NONE:
+ return "none";
+ case HYBBX_KISS_ENTRY_KISS_ON:
+ return "kiss_on";
+ case HYBBX_KISS_ENTRY_ESC_AT_K:
+ return "esc_at_k";
+ case HYBBX_KISS_ENTRY_AUTO:
+ return "auto";
+ case HYBBX_KISS_ENTRY_UNSET:
+ default:
+ return "unset";
+ }
+}
+
+static hybbx_kiss_entry_t default_kiss_entry_for_tnc(hybbx_packet_radio_tnc_t tnc)
+{
+ (void)tnc;
+ return HYBBX_KISS_ENTRY_NONE;
+}
+
+hybbx_result_t hybbx_tnc_finalize_kiss_entry(hybbx_packet_radio_config_t *cfg)
+{
+ if (cfg == NULL) {
+ return HYBBX_ERR_INVALID;
+ }
+
+ if (cfg->params.kiss_entry == HYBBX_KISS_ENTRY_UNSET) {
+ cfg->params.kiss_entry = default_kiss_entry_for_tnc(cfg->tnc);
+ }
+
+ if (cfg->params.kiss_exit == HYBBX_KISS_EXIT_UNSET) {
+ if (cfg->params.kiss_entry == HYBBX_KISS_ENTRY_NONE) {
+ cfg->params.kiss_exit = HYBBX_KISS_EXIT_NONE;
+ } else {
+ cfg->params.kiss_exit = HYBBX_KISS_EXIT_AUTO;
+ }
+ }
+
+ return HYBBX_OK;
+}
+
+hybbx_result_t hybbx_tnc_finalize_radio_duplex(hybbx_packet_radio_config_t *cfg)
+{
+ if (cfg == NULL) {
+ return HYBBX_ERR_INVALID;
+ }
+
+ if (cfg->params.band == HYBBX_PACKET_RADIO_BAND_UNSET) {
+ cfg->params.band = default_band_for_tnc(cfg->tnc);
+ }
+
+ if (cfg->params.duplex == HYBBX_PACKET_RADIO_DUPLEX_UNSET) {
+ cfg->params.duplex = HYBBX_PACKET_RADIO_DUPLEX_HALF;
+ }
+
+ if (cfg->params.band == HYBBX_PACKET_RADIO_BAND_CB &&
+ cfg->params.duplex == HYBBX_PACKET_RADIO_DUPLEX_FULL) {
+ hybbx_log_warn("[tnc] radio_band=cb allows half-duplex only; "
+ "ignoring radio_duplex=full");
+ cfg->params.duplex = HYBBX_PACKET_RADIO_DUPLEX_HALF;
+ }
+
+ cfg->params.fullduplex =
+ (cfg->params.duplex == HYBBX_PACKET_RADIO_DUPLEX_FULL) ? 1 : 0;
+
+ return HYBBX_OK;
+}
+
+hybbx_result_t hybbx_tnc_finalize_csma(hybbx_packet_radio_config_t *cfg)
+{
+ if (cfg == NULL) {
+ return HYBBX_ERR_INVALID;
+ }
+
+ if (cfg->params.persist == 0) {
+ if (cfg->params.band == HYBBX_PACKET_RADIO_BAND_CB) {
+ cfg->params.persist = 255;
+ } else {
+ cfg->params.persist = 63;
+ }
+ } else if (cfg->params.band == HYBBX_PACKET_RADIO_BAND_CB &&
+ cfg->params.persist < 255) {
+ hybbx_log_warn("[tnc] CB band persist=%u overridden to 255 for beacon TX",
+ cfg->params.persist);
+ cfg->params.persist = 255;
+ }
+
+ if (cfg->params.txdelay == 0) {
+ cfg->params.txdelay = 50;
+ }
+
+ if (cfg->params.slot == 0) {
+ cfg->params.slot = 10;
+ }
+
+ return HYBBX_OK;
+}
+
+hybbx_result_t hybbx_tnc_finalize_serial_line(hybbx_packet_radio_config_t *cfg)
+{
+ if (cfg == NULL) {
+ return HYBBX_ERR_INVALID;
+ }
+
+ if (cfg->params.data_bits == 0) {
+ if (cfg->tnc == HYBBX_PACKET_RADIO_TNC_TNC2C ||
+ cfg->tnc == HYBBX_PACKET_RADIO_TNC_MFJ1278) {
+ cfg->params.data_bits = HYBBX_TNC2C_DATA_BITS;
+ } else {
+ cfg->params.data_bits = 8;
+ }
+ }
+
+ if (cfg->params.serial_parity == HYBBX_TNC_SERIAL_PARITY_UNSET) {
+ if (cfg->tnc == HYBBX_PACKET_RADIO_TNC_TNC2C ||
+ cfg->tnc == HYBBX_PACKET_RADIO_TNC_MFJ1278) {
+ cfg->params.serial_parity = HYBBX_TNC_SERIAL_PARITY_EVEN;
+ } else {
+ cfg->params.serial_parity = HYBBX_TNC_SERIAL_PARITY_NONE;
+ }
+ }
+
+ if (cfg->params.stop_bits == 0) {
+ cfg->params.stop_bits = 1;
+ }
+
+ if (cfg->params.assert_modem_lines < 0) {
+ cfg->params.assert_modem_lines =
+ (cfg->tnc == HYBBX_PACKET_RADIO_TNC_TNC2C) ? 1 : 0;
+ }
+
+ return HYBBX_OK;
+}
+
+hybbx_result_t hybbx_tnc_profile_apply_defaults(hybbx_packet_radio_config_t *cfg)
+{
+ if (cfg == NULL) {
+ return HYBBX_ERR_INVALID;
+ }
+
+ switch (cfg->tnc) {
+ case HYBBX_PACKET_RADIO_TNC_BAYCOM:
+ if (cfg->baud == 0) {
+ cfg->baud = HYBBX_PACKET_RADIO_DEFAULT_BAUD;
+ }
+ if (cfg->params.band == HYBBX_PACKET_RADIO_BAND_UNSET) {
+ cfg->params.band = HYBBX_PACKET_RADIO_BAND_CB;
+ }
+ cfg->params.radio_baud = 1200;
+ cfg->params.modem = HYBBX_TNC2C_MODEM_TCM3105;
+ if (cfg->protocol == 0) {
+ cfg->protocol = HYBBX_PACKET_RADIO_PROTO_KISS;
+ }
+ if (cfg->params.txdelay == 0) {
+ cfg->params.txdelay = 30;
+ }
+ if (cfg->params.persist == 0) {
+ cfg->params.persist = 63;
+ }
+ if (cfg->params.slot == 0) {
+ cfg->params.slot = 10;
+ }
+ break;
+
+ case HYBBX_PACKET_RADIO_TNC_PCCOM:
+ if (cfg->baud == 0) {
+ cfg->baud = HYBBX_PACKET_RADIO_DEFAULT_BAUD;
+ }
+ if (cfg->params.band == HYBBX_PACKET_RADIO_BAND_UNSET) {
+ cfg->params.band = HYBBX_PACKET_RADIO_BAND_CB;
+ }
+ cfg->params.radio_baud = 1200;
+ cfg->params.modem = HYBBX_TNC2C_MODEM_TCM3105;
+ if (cfg->protocol == 0) {
+ cfg->protocol = HYBBX_PACKET_RADIO_PROTO_HOSTMODE;
+ }
+ if (cfg->params.duplex == HYBBX_PACKET_RADIO_DUPLEX_UNSET) {
+ cfg->params.duplex = HYBBX_PACKET_RADIO_DUPLEX_HALF;
+ }
+ if (cfg->params.txdelay == 0) {
+ cfg->params.txdelay = 25;
+ }
+ if (cfg->params.persist == 0) {
+ cfg->params.persist = 128;
+ }
+ if (cfg->params.slot == 0) {
+ cfg->params.slot = 10;
+ }
+ cfg->params.host_connect_on_start = 1;
+ break;
+
+ case HYBBX_PACKET_RADIO_TNC_GENERIC:
+ if (cfg->baud == 0) {
+ cfg->baud = HYBBX_PACKET_RADIO_DEFAULT_BAUD;
+ }
+ if (cfg->protocol == 0) {
+ cfg->protocol = HYBBX_PACKET_RADIO_PROTO_KISS;
+ }
+ break;
+
+ case HYBBX_PACKET_RADIO_TNC_TNC2:
+ if (cfg->baud == 0) {
+ cfg->baud = 9600;
+ }
+ if (cfg->params.radio_baud == 0) {
+ cfg->params.radio_baud = HYBBX_TNC2C_DEFAULT_RADIO_BAUD;
+ }
+ if (cfg->protocol == 0) {
+ cfg->protocol = HYBBX_PACKET_RADIO_PROTO_KISS;
+ }
+ break;
+
+ case HYBBX_PACKET_RADIO_TNC_PK232:
+ if (cfg->baud == 0) {
+ cfg->baud = 9600;
+ }
+ if (cfg->params.radio_baud == 0) {
+ cfg->params.radio_baud = HYBBX_TNC2C_DEFAULT_RADIO_BAUD;
+ }
+ if (cfg->protocol == 0) {
+ cfg->protocol = HYBBX_PACKET_RADIO_PROTO_KISS;
+ }
+ break;
+
+ case HYBBX_PACKET_RADIO_TNC_MFJ1278:
+ if (cfg->baud == 0) {
+ cfg->baud = 4800;
+ }
+ if (cfg->params.radio_baud == 0) {
+ cfg->params.radio_baud = HYBBX_TNC2C_DEFAULT_RADIO_BAUD;
+ }
+ if (cfg->protocol == 0) {
+ cfg->protocol = HYBBX_PACKET_RADIO_PROTO_KISS;
+ }
+ break;
+
+ case HYBBX_PACKET_RADIO_TNC_KANTRONICS:
+ if (cfg->baud == 0) {
+ cfg->baud = 9600;
+ }
+ if (cfg->params.radio_baud == 0) {
+ cfg->params.radio_baud = HYBBX_TNC2C_DEFAULT_RADIO_BAUD;
+ }
+ if (cfg->protocol == 0) {
+ cfg->protocol = HYBBX_PACKET_RADIO_PROTO_KISS;
+ }
+ break;
+
+ case HYBBX_PACKET_RADIO_TNC_TNC2C:
+ default:
+ if (cfg->params.radio_baud == 0) {
+ cfg->params.radio_baud = HYBBX_TNC2C_DEFAULT_RADIO_BAUD;
+ }
+ if (cfg->params.clock_mhz == 0.0f) {
+ cfg->params.clock_mhz = HYBBX_TNC2C_CLOCK_4_9_MHZ;
+ }
+ if (cfg->protocol == 0) {
+ cfg->protocol = HYBBX_PACKET_RADIO_PROTO_KISS;
+ }
+ break;
+ }
+
+ if (cfg->protocol == 0) {
+ cfg->protocol = HYBBX_PACKET_RADIO_PROTO_KISS;
+ }
+
+ (void)hybbx_tnc_finalize_modulation(cfg);
+ (void)hybbx_tnc_finalize_radio_duplex(cfg);
+ (void)hybbx_tnc_finalize_csma(cfg);
+ (void)hybbx_tnc_finalize_serial_line(cfg);
+ return hybbx_tnc_finalize_kiss_entry(cfg);
+}
git clone -b <branch> https://cgit.mode42.com/<repo>.git
git clone -b <branch> git://cgit.mode42.com/<repo>.git

info@mode42.com