1 // ----------------------------------------------------------------------------
2 // kiss_io.cxx
3 //
4 // support for KISS interface
5 //
6 // Copyright (c) 2014, 2016
7 //		Robert Stiles, KK5VD
8 //
9 // This file is part of fldigi.
10 //
11 // Fldigi is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // Fldigi is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with fldigi.  If not, see <http://www.gnu.org/licenses/>.
23 // ----------------------------------------------------------------------------
24 
25 
26 #include <fstream>
27 #include <sstream>
28 #include <string>
29 #include <cstdlib>
30 #include <ctime>
31 #include <errno.h>
32 #include <float.h>
33 
34 #include <sys/types.h>
35 #if !defined(__MINGW32__) && !defined(__APPLE__)
36 #  include <sys/ipc.h>
37 #  include <sys/msg.h>
38 #endif
39 
40 #include <signal.h>
41 
42 #include "config.h"
43 
44 #ifdef __MINGW32__
45 #  include "compat.h"
46 #endif
47 
48 #include "main.h"
49 #include "configuration.h"
50 #include "fl_digi.h"
51 #include "trx.h"
52 #include "kiss_io.h"
53 #include "globals.h"
54 
55 #include "threads.h"
56 #include "socket.h"
57 #include "debug.h"
58 #include "qrunner.h"
59 #include "data_io.h"
60 #include "status.h"
61 #include "psm/psm.h"
62 
63 #include <FL/Fl.H>
64 #include <FL/fl_ask.H>
65 #include <FL/Fl_Check_Button.H>
66 
67 #include "confdialog.h"
68 #include "configuration.h"
69 #include "status.h"
70 
71 LOG_FILE_SOURCE(debug::LOG_KISSCONTROL);
72 
73 //#define EXTENED_DEBUG_INFO
74 //#undef EXTENED_DEBUG_INFO
75 
76 using namespace std;
77 //======================================================================
78 // Socket KISS i/o used on all platforms
79 //======================================================================
80 
81 #define KISSLOOP_TIMING   100 // msec
82 #define KISSLOOP_FRACTION 10  // msec
83 
84 static string errstring;
85 
86 // =====================================================================
87 static pthread_t kiss_thread;
88 static pthread_t kiss_rx_socket_thread;
89 static pthread_t kiss_watchdog_thread;
90 
91 static pthread_cond_t kiss_watchdog_cond    = PTHREAD_COND_INITIALIZER;
92 
93 static pthread_mutex_t from_host_mutex      = PTHREAD_MUTEX_INITIALIZER;
94 static pthread_mutex_t from_radio_mutex     = PTHREAD_MUTEX_INITIALIZER;
95 static pthread_mutex_t kiss_bc_frame_mutex  = PTHREAD_MUTEX_INITIALIZER;
96 static pthread_mutex_t kiss_frame_mutex     = PTHREAD_MUTEX_INITIALIZER;
97 static pthread_mutex_t to_host_arq_mutex    = PTHREAD_MUTEX_INITIALIZER;
98 static pthread_mutex_t to_host_mutex        = PTHREAD_MUTEX_INITIALIZER;
99 static pthread_mutex_t to_radio_mutex       = PTHREAD_MUTEX_INITIALIZER;
100 //static pthread_mutex_t external_mutex       = PTHREAD_MUTEX_INITIALIZER;
101 static pthread_mutex_t restart_mutex        = PTHREAD_MUTEX_INITIALIZER;
102 static pthread_mutex_t kiss_encode_mutex    = PTHREAD_MUTEX_INITIALIZER;
103 static pthread_mutex_t kiss_loop_exit_mutex = PTHREAD_MUTEX_INITIALIZER;
104 
105 bool kiss_enabled = false;
106 bool kiss_exit = false;
107 bool kiss_rx_exit = false;
108 bool allow_kiss_socket_io  = false;
109 bool kiss_loop_running     = false;
110 bool kiss_rx_loop_running  = false;
111 bool kiss_watchdog_exit    = false;
112 bool kiss_watchdog_running = false;
113 bool kiss_tcp_ip_connected = false;
114 bool tcpip_reset_flag      = false;
115 
116 static bool smack_crc_enabled  = false;
117 static int crc_mode            = CRC16_CCITT;
118 static std::string default_kiss_modem = "BPSK250";
119 static std::string kiss_modem = "";
120 static unsigned int transmit_buffer_flush_timeout = 0;
121 
122 unsigned int duplex = KISS_HALF_DUPLEX; // Default half duplex
123 unsigned int kiss_port_no = 0;          // Default is 0
124 
125 /// Any access to shared variables must be protected.
126 static std::string from_host         = "";
127 static std::string from_radio        = "";
128 static std::string from_radio_parsed = "";
129 static std::string kiss_bc_frame     = "";
130 static std::string kiss_frame        = "";
131 static std::string kiss_ip_address   = "";
132 static std::string kiss_ip_io_port   = "";
133 static std::string kiss_ip_out_port  = "";
134 static std::string kiss_one_frame    = "";
135 static std::string to_arq_host       = "";
136 static std::string to_host           = "";
137 static std::string to_radio          = "";
138 static std::string translated_frame  = "";
139 static int pText = 0;
140 
141 bool bcast_tx_buffer_empty_flag = false;
142 bool kiss_bcast_rsid_reception  = false;
143 bool kiss_bcast_trx_toggle      = false;
144 bool kiss_text_available        = false;
145 static bool kiss_reset_flag     = false;
146 static int  retry_count         = KISS_CONNECT_RETRY_COUNT;
147 
148 #define HISTO_COUNT 256
149 #define HISTO_THRESH_HOLD 48
150 // In seconds
151 #define HISTO_RESET_TX_TIME 3
152 
153 static int histogram[HISTO_COUNT];
154 static bool init_hist_flag = true;
155 // static double threshold = 5.0;
156 // time_t inhibit_tx_seconds = 0;
157 
158 time_t temp_disable_tx_inhibit = 0;
159 time_t temp_disable_tx_duration = DISABLE_TX_INHIBIT_DURATION;
160 
161 static int kpsql_pl = 0;
162 static double kpsql_threshold = 0.0;
163 
164 extern int IMAGE_WIDTH;
165 Socket *kiss_socket = 0;
166 int data_io_enabled = DISABLED_IO;
167 int data_io_type    = DATA_IO_UDP;
168 
169 //program_start_time
170 bool program_started_flag = 0;
171 
172 extern const struct mode_info_t mode_info[];
173 extern void abort_tx();
174 
175 // Storage for modem list allowed for KISS use.
176 static std::vector<std::string> availabe_kiss_modems;
177 static int kiss_raw_enabled = KISS_RAW_DISABLED;
178 std::string host_name_string;
179 
180 inline std::string uppercase_string(std::string str);
181 inline void set_tx_timeout(void);
182 size_t hdlc_decode(char *src, size_t src_size, char **dst);
183 size_t hdlc_encode(char *src, size_t src_size, char **dst);
184 size_t kiss_decode(char *src, size_t src_size, char **dst);
185 size_t kiss_encode(char *src, size_t src_size, char **dst);
186 static bool kiss_queue_frame(KISS_QUEUE_FRAME * frame, std::string cmd);
187 static int  calc_ccitt_crc(char *buf, int n);
188 static int  calc_fcs_crc(char *buf, int n);
189 static int  calc_xor_crc(char *buf, int n);
190 static KISS_QUEUE_FRAME * encap_kiss_frame(std::string data, int frame_type, int port);
191 static KISS_QUEUE_FRAME *encap_kiss_frame(char *buffer, size_t buffer_size, int frame_type, int port);
192 static size_t decap_hdlc_frame(char *buffer, size_t data_count);
193 static size_t encap_hdlc_frame(char *buffer, size_t data_count);
194 static void *kiss_loop(void *args);
195 static void *ReadFromHostSocket(void *args);
196 static void *tcpip_watchdog(void *args);
197 static void exec_hardware_command(std::string cmd, std::string arg);
198 static void host_name(char *arg);
199 static void kiss_tcp_disconnect(char *arg);
200 static void parse_hardware_frame(std::string frame);
201 static void parse_kiss_frame(std::string frame_segment);
202 static void ReadFromHostBuffered(void);
203 static void reply_active_modem_bw(char * arg);
204 static void reply_active_modem(char * arg);
205 static void reply_busy_channel_duration(char * arg);
206 static void reply_busy_channel_on_off(char * arg);
207 static void reply_busy_state(char * arg);
208 static void reply_crc_mode(char *arg);
209 static void reply_csma_mode(char *arg);
210 static void reply_fldigi_stat(char *arg);
211 static void reply_kiss_raw_mode(char * arg);
212 static void reply_kpsql_fraction_gain(char *arg);
213 static void reply_kpsql_on_off(char * arg);
214 static void reply_kpsql_pwr_level(char * arg);
215 static void reply_kpsql_squelch_level(char * arg);
216 static void reply_modem_list(char * arg);
217 static void reply_psm_on_off(char * arg);
218 static void reply_psm_pwr_level(char * arg);
219 static void reply_psm_squelch_level(char * arg);
220 static void reply_rsid_bc_mode(char * arg);
221 static void reply_rsid_mode_state(char * arg);
222 static void reply_rsid_rx_state(char * arg);
223 static void reply_rsid_tx_state(char * arg);
224 static void reply_sql_level(char * arg);
225 static void reply_sql_on_off(char * arg);
226 static void reply_sql_pwr_level(char * arg);
227 static void reply_tnc_name(char * arg);
228 static void reply_trx_state(char * arg);
229 static void reply_trxs_bc_mode(char * arg);
230 static void reply_tx_buffer_count(char * arg);
231 static void reply_txbe_bc_mode(char * arg);
232 static void reply_waterfall_bw(char * arg);
233 static void reply_wf_freq_pos(char * arg);
234 static void send_disconnect_msg(void);
235 static void set_busy_channel_duration(char * arg);
236 static void set_busy_channel_inhibit(char *arg);
237 static void set_busy_channel_on_off(char * arg);
238 static void set_button(Fl_Button * button, bool value);
239 static void set_counter(Fl_Counter * counter, int value);
240 static void set_crc_mode(char * arg);
241 static void set_csma_mode(char * arg);
242 static void set_default_kiss_modem(void);
243 static void set_kiss_modem(char * arg);
244 static void set_kiss_raw_mode(char * arg);
245 static void set_kpsql_on_off(char * arg);
246 static void set_kpsql_squelch_level(char * arg);
247 static void set_psm_fraction_gain(char *arg);
248 static void set_psm_on_off(char * arg);
249 static void set_psm_squelch_level(char * arg);
250 static void set_reply_tx_lock(char * arg);
251 static void set_rsid_bc_mode(char * arg);
252 static void set_rsid_mode(char *arg);
253 static void set_rsid_rx(char *arg);
254 static void set_rsid_tx(char * arg);
255 static void set_sql_level(char * arg);
256 static void set_sql_on_off(char * arg);
257 static void set_trxs_bc_mode(char * arg);
258 static void set_txbe_bc_mode(char * arg);
259 static void set_wf_cursor_pos(char * arg);
260 static void WriteToHostARQBuffered(void);
261 static void WriteToHostBuffered(const char *data, size_t size);
262 static void WriteToRadioBuffered(const char *data, size_t size);
263 std::string kiss_decode(std::string frame);
264 std::string kiss_encode(std::string frame);
265 std::string unencap_kiss_frame(char *buffer, size_t buffer_size, int *frame_type, int *kiss_port_no);
266 std::string unencap_kiss_frame(std::string package, int *frame_type, int *kiss_port_no);
267 void kiss_main_thread_close(void *ptr);
268 void kiss_main_thread_retry_open(void *ptr);
269 void kiss_reset_buffers(void);
270 void kiss_reset(void);
271 void ReadFromRadioBuffered(void);
272 void WriteKISS(const char *data, size_t size);
273 void WriteKISS(const char *data);
274 void WriteKISS(const char data);
275 void WriteKISS(std::string data);
276 void WriteToHostBCastFramesBuffered(void);
277 void WriteToHostSocket(void);
278 
279 /**********************************************************************************
280  * Not all modems are created equal. Translate!
281  * There must be at least HDLC_CNT_OFFSET count offset (+/-, but still in range)
282  * between real values and translated values.
283  **********************************************************************************/
284 static int not_allowed[256] = {
285 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, //  16
286 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //  32
287 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //  48
288 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //  64
289 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //  80
290 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //  96
291 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 112
292 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, // 128
293 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144
294 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160
295 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176
296 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192
297 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208
298 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224
299 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240
300 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1  // 256
301 };
302 
303 /**********************************************************************************
304  * KISS hardware frame commands strings and calling functions
305  **********************************************************************************/
306 EXEC_HARDWARE_CMD_MATCH exec_match[] = {
307 	{ (char *) "BCHN",      set_busy_channel_on_off },
308 	{ (char *) "BCHNS",     set_busy_channel_duration },
309 	{ (char *) "BUSY",      reply_busy_state },
310 	{ (char *) "CSMA",      set_csma_mode },
311 	{ (char *) "DISC",      kiss_tcp_disconnect },
312 	{ (char *) "FLSTAT",    reply_fldigi_stat },
313 	{ (char *) "HOST",      host_name },
314 	{ (char *) "IBCHN",     set_busy_channel_inhibit },
315 	{ (char *) "KISSCRCM",  set_crc_mode },
316 	{ (char *) "KISSRAW",   set_kiss_raw_mode },
317 	{ (char *) "KPSATT",    set_psm_fraction_gain },   // Depreciated
318 	{ (char *) "PSMATT",    set_psm_fraction_gain },
319 	{ (char *) "PSM",       set_psm_on_off },
320 	{ (char *) "PSMP",      reply_psm_pwr_level },
321 	{ (char *) "PSMS",      set_psm_squelch_level },
322 	{ (char *) "KPSQL",     set_kpsql_on_off },        // Depreciated
323 	{ (char *) "KPSQLP",    reply_kpsql_pwr_level },   // Depreciated
324 	{ (char *) "KPSQLS",    set_kpsql_squelch_level }, // Depreciated
325 	{ (char *) "MODEM",     set_kiss_modem },
326 	{ (char *) "MODEMBW",   reply_active_modem_bw },
327 	{ (char *) "MODEML",    reply_modem_list },
328 	{ (char *) "RSIDBCAST", set_rsid_bc_mode },
329 	{ (char *) "RSIDM",     set_rsid_mode },
330 	{ (char *) "RSIDRX",    set_rsid_rx },
331 	{ (char *) "RSIDTX",    set_rsid_tx },
332 	{ (char *) "SQL",       set_sql_on_off },
333 	{ (char *) "SQLP",      reply_sql_pwr_level },
334 	{ (char *) "SQLS",      set_sql_level },
335 	{ (char *) "TNC",       reply_tnc_name },
336 	{ (char *) "TRXS",      reply_trx_state },
337 	{ (char *) "TRXSBCAST", set_trxs_bc_mode },
338 	{ (char *) "TXBEBCAST", set_txbe_bc_mode },
339 	{ (char *) "TXBUF",     reply_tx_buffer_count },
340 	{ (char *) "TXLOCK",    set_reply_tx_lock },
341 	{ (char *) "WFBW",      reply_waterfall_bw },
342 	{ (char *) "WFF",       set_wf_cursor_pos },
343 	{ (char *) 0,           0 }
344 };
345 
346 
347 #ifdef USE_NOCTRL
348 
349 static std::string noctrl(string src);
350 
351 static const char *asc[128] = {
352 	"<NUL>", "<SOH>", "<STX>", "<ETX>",
353 	"<EOT>", "<ENQ>", "<ACK>", "<BEL>",
354 	"<BS>",  "<TAB>", "\n",    "<VT>",
355 	"<FF>",  "",      "<SO>",  "<SI>",
356 	"<DLE>", "<DC1>", "<DC2>", "<DC3>",
357 	"<DC4>", "<NAK>", "<SYN>", "<ETB>",
358 	"<CAN>", "<EM>",  "<SUB>", "<ESC>",
359 	"<FS>",  "<GS>",  "<RS>",  "<US>",
360 	" ",     "!",     "\"",    "#",
361 	"$",     "%",     "&",     "\'",
362 	"(",     ")",     "*",     "+",
363 	",",     "-",     ".",     "/",
364 	"0",     "1",     "2",     "3",
365 	"4",     "5",     "6",     "7",
366 	"8",     "9",     ":",     ";",
367 	"<",     "=",     ">",     "?",
368 	"@",     "A",     "B",     "C",
369 	"D",     "E",     "F",     "G",
370 	"H",     "I",     "J",     "K",
371 	"L",     "M",     "N",     "O",
372 	"P",     "Q",     "R",     "S",
373 	"T",     "U",     "V",     "W",
374 	"X",     "Y",     "Z",     "[",
375 	"\\",    "]",     "^",     "_",
376 	"`",     "a",     "b",     "c",
377 	"d",     "e",     "f",     "g",
378 	"h",     "i",     "j",     "k",
379 	"l",     "m",     "n",     "o",
380 	"p",     "q",     "r",     "s",
381 	"t",     "u",     "v",     "w",
382 	"x",     "y",     "z",     "{",
383 	"|",     "}",     "~",     "<DEL>"
384 };
385 
386 /**********************************************************************************
387  *
388  **********************************************************************************/
noctrl(string src)389 static string noctrl(string src)
390 {
391 	static string retstr;
392 	retstr.clear();
393 	char hexstr[10];
394 	int c;
395 	for (size_t i = 0; i < src.length(); i++)  {
396 		c = src[i];
397 		if ( c > 0 && c < 128)
398 			retstr.append(asc[c]);
399 		else {
400 			snprintf(hexstr, sizeof(hexstr), "<%0X>", c & 0xFF);
401 			retstr.append(hexstr);
402 		}
403 	}
404 	return retstr;
405 }
406 #endif // USE_NOCTRL
407 
408 /**********************************************************************************
409  * For SMACK CRC validation
410  **********************************************************************************/
calc_ccitt_crc(char * buf,int n)411 static int  calc_ccitt_crc(char *buf, int n)
412 {
413 	static int  crc_table[] = {
414 		0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
415 		0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
416 		0xcc01, 0xcc0,  0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
417 		0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
418 		0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
419 		0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
420 		0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
421 		0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
422 		0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
423 		0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
424 		0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
425 		0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
426 		0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
427 		0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
428 		0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
429 		0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
430 		0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
431 		0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
432 		0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
433 		0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
434 		0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
435 		0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
436 		0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
437 		0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
438 		0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
439 		0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
440 		0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
441 		0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
442 		0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
443 		0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
444 		0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
445 		0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
446 	};
447 
448 	int crc;
449 	crc = 0;
450 	while (--n >= 0)
451 		crc = ((crc >> 8) & 0xff) ^ crc_table[(crc ^ *buf++) & 0xff];
452 	return crc;
453 }
454 
455 /**********************************************************************************
456  * For SMACK CRC validation (BPQ XOR CRC implimentation).
457  **********************************************************************************/
calc_xor_crc(char * buf,int n)458 static int  calc_xor_crc(char *buf, int n)
459 {
460 	int crc;
461 	crc = 0;
462 	while (--n >= 0)
463 		crc ^= (*buf++ & 0xff);
464 	return crc;
465 }
466 
467 /**********************************************************************************
468  * For FCS CRC.
469  **********************************************************************************/
calc_fcs_crc(char * buf,int n)470 static int  calc_fcs_crc(char *buf, int n)
471 {
472 
473 	static int fcstab[256] = {
474 		0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
475 		0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
476 		0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
477 		0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
478 		0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
479 		0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
480 		0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
481 		0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
482 		0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
483 		0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
484 		0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
485 		0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
486 		0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
487 		0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
488 		0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
489 		0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
490 		0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
491 		0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
492 		0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
493 		0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
494 		0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
495 		0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
496 		0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
497 		0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
498 		0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
499 		0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
500 		0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
501 		0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
502 		0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
503 		0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
504 		0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
505 		0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
506 	};
507 
508 	int crc;
509 	crc = 0xFFFF;
510 	while (--n >= 0)
511 		crc = ((crc >> 8) & 0xff) ^ fcstab[(crc ^ *buf++) & 0xff];
512 	return crc;
513 }
514 
515 /**********************************************************************************
516  *
517  **********************************************************************************/
set_button(Fl_Button * button,bool value)518 static void set_button(Fl_Button * button, bool value)
519 {
520 	button->value(value);
521 	button->do_callback();
522 }
523 
524 
525 /**********************************************************************************
526  *
527  **********************************************************************************/
set_counter(Fl_Counter * counter,int value)528 static void set_counter(Fl_Counter * counter, int value)
529 {
530 	counter->value(value);
531 	counter->do_callback();
532 }
533 
534 /**********************************************************************************
535  *
536  **********************************************************************************/
set_slider2(Fl_Slider2 * sider,int value)537 static void set_slider2(Fl_Slider2 * sider, int value)
538 {
539 	sider->value(value);
540 	sider->do_callback();
541 }
542 
543 /**********************************************************************************
544  *
545  **********************************************************************************/
valid_kiss_modem(std::string _modem)546 bool valid_kiss_modem(std::string _modem)
547 {
548 	if(_modem.empty()) return false;
549 
550 	int index = 0;
551 	int count = availabe_kiss_modems.size();
552 	std::string _tmp_str;
553 
554 	if(count < 1) {
555 		for(index = 0; index < NUM_MODES; index++) {
556 			if(mode_info[index].iface_io & KISS_IO) {
557 				_tmp_str = uppercase_string(mode_info[index].sname);
558 				availabe_kiss_modems.push_back(_tmp_str);
559 			}
560 		}
561 		count = availabe_kiss_modems.size();
562 	}
563 
564 	std::string cmp_str = "";
565 	index = 0;
566 
567 	_modem = uppercase_string(_modem);
568 
569 	while(index < count) {
570 		cmp_str = availabe_kiss_modems[index];
571 		if(cmp_str.empty()) return false;
572 
573 		if(_modem.compare(cmp_str) == 0) {
574 			return true;
575 		}
576 
577 		index++;
578 	}
579 
580 	return false;
581 }
582 
583 /**********************************************************************************
584  *
585  **********************************************************************************/
check_kiss_modem(void)586 void check_kiss_modem(void)
587 {
588 	int mode = active_modem->get_mode();
589 	std::string modem_name;
590 	modem_name.assign(mode_info[mode].sname);
591 	bool valid = valid_kiss_modem(modem_name);
592 
593 	if(!valid)
594 		set_default_kiss_modem();
595 }
596 
597 /**********************************************************************************
598  *
599  **********************************************************************************/
set_default_kiss_modem(void)600 static void set_default_kiss_modem(void)
601 {
602 	set_kiss_modem((char *) default_kiss_modem.c_str());
603 }
604 
605 /**********************************************************************************
606  *
607  **********************************************************************************/
uppercase_string(std::string str)608 inline std::string uppercase_string(std::string str)
609 {
610 	int index = 0;
611 	int count = str.size();
612 	std::string ret_str = "";
613 
614 	if(!count) return ret_str;
615 
616 	ret_str.reserve(count + 1);
617 	ret_str.clear();
618 
619 	for(index = 0; index < count; index++)
620 		ret_str += toupper(str[index]);
621 
622 	return ret_str;
623 }
624 
625 /**********************************************************************************
626  * MODEM:<modem_id_string>
627  **********************************************************************************/
set_kiss_modem(char * arg)628 static void set_kiss_modem(char * arg)
629 {
630 	if(!arg) return;
631 
632 	std::string _modem = "";
633 	std::string _cmp_modem = "";
634 
635 	_modem.assign(arg);
636 
637 	if(_modem.empty()) {
638 		return reply_active_modem(arg);
639 	}
640 
641 	bool valid = valid_kiss_modem(_modem);
642 
643 	_modem = uppercase_string(_modem);
644 
645 	if(valid) {
646 		for (size_t i = 0; i < NUM_MODES; i++) {
647 			_cmp_modem = uppercase_string(mode_info[i].sname);
648 			if (_modem == _cmp_modem) {
649 				REQ_SYNC(init_modem_sync, i, 0);
650 				kiss_modem.assign(_modem);
651 				break;
652 			}
653 		}
654 		return;
655 	}
656 
657 	if(!valid)
658 		LOG_INFO("Modem %s invalid for KISS use. Must support 8bit.", _modem.c_str());
659 
660 	return;
661 }
662 
663 /**********************************************************************************
664  * DISC:  Disconnect TCP/IP connection.
665  **********************************************************************************/
kiss_tcp_disconnect(char * arg)666 static void kiss_tcp_disconnect(char *arg)
667 {
668 	if(kiss_socket && data_io_type == DATA_IO_TCP) {
669 		Fl::awake(kiss_main_thread_close, (void *) 0);
670 	}
671 }
672 
673 /**********************************************************************************
674  * Send a Disconnect message to the HOST called from the main thread only.
675  **********************************************************************************/
send_disconnect_msg(void)676 static void send_disconnect_msg(void)
677 {
678 	if(kiss_socket && data_io_type == DATA_IO_TCP) {
679 		std::string package = "";
680 		std::string cmd = "DISC:";
681 		package.assign(cmd);
682 		kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
683 	}
684 }
685 
686 /**********************************************************************************
687  * FLSTAT:<INIT|OK>,<HH:MM:SS>
688  **********************************************************************************/
reply_fldigi_stat(char * arg)689 static void reply_fldigi_stat(char *arg)
690 {
691 	std::string package = "";
692 	std::string cmd = "FLSTAT:";
693 
694 	unsigned int hours = 0;
695 	unsigned int mins = 0;
696 	unsigned int secs = 0;
697 
698 	time_t current_time = time(0);
699 	time_t diff_time = 0;
700 
701 	char buffer[64];
702 
703 	package.assign(cmd);
704 
705 	if(program_started_flag) {
706 		package.append("OK");
707 	} else {
708 		package.append("INIT");
709 		program_started_flag = true;
710 	}
711 
712 	if(program_start_time == 0)
713 		program_start_time = time(0);
714 
715 	diff_time = current_time - program_start_time;
716 
717 	hours = (unsigned int) (diff_time / 3600);
718 	diff_time -= (time_t) (hours * 3600);
719 
720 	mins = (unsigned int)(diff_time / 60);
721 	diff_time -= (time_t) (mins * 60);
722 
723 	secs = (unsigned int) diff_time;
724 
725 	memset(buffer, 0, sizeof(buffer));
726 	snprintf(buffer, sizeof(buffer)-1, ",%02u:%02u:%02u", hours, mins, secs);
727 	package.append(buffer);
728 
729 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
730 
731 }
732 
733 
734 /**********************************************************************************
735  * CSMA:<ON|OFF>
736  **********************************************************************************/
set_csma_mode(char * arg)737 static void set_csma_mode(char * arg)
738 {
739 	if(!arg)
740 		return;
741 
742 	std::string rsid_tx_state = "";
743 	rsid_tx_state.assign(arg);
744 
745 	if(rsid_tx_state.empty())
746 		return reply_csma_mode(arg);
747 
748 	std::string state = uppercase_string(rsid_tx_state);
749 
750 	if(state.find("ON") != std::string::npos) {
751 		REQ(set_button, btnEnable_csma, 1);
752 		return;
753 	}
754 
755 	if(state.find("OFF") != std::string::npos) {
756 		REQ(set_button, btnEnable_csma, 0);
757 		return;
758 	}
759 }
760 
761 /**********************************************************************************
762  * CSMA:<ON|OFF>
763  **********************************************************************************/
reply_csma_mode(char * arg)764 static void reply_csma_mode(char *arg)
765 {
766 	std::string package = "";
767 	std::string cmd = "CSMA:";
768 
769 	package.assign(cmd);
770 
771 	if(progdefaults.csma_enabled)
772 		package.append("ON");
773 	else
774 		package.append("OFF");
775 
776 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
777 
778 }
779 
780 /**********************************************************************************
781  * IBCHN:I       // Inhibit busy channel temporarily. 'I' (character)
782  * IBCHN:<N>     // Set Inhibit busy channel duration to N seconds
783  * IBCHN:0       // Resets temporary duration to default setting (5).
784  * IBCHN:        // Returns IBCHN:<SECONDS>
785  **********************************************************************************/
set_busy_channel_inhibit(char * arg)786 static void set_busy_channel_inhibit(char *arg)
787 {
788 	std::string argstr = "";
789 	int temp = 0;
790 
791 	if(arg) {
792 		argstr.assign(arg);
793 		if(!argstr.empty()) {
794 			if(argstr[0] == 'I' || argstr[0] == 'i') {
795 				if(progdefaults.enableBusyChannel && inhibit_tx_seconds) {
796 					temp_disable_tx_inhibit = time(0) + temp_disable_tx_duration;
797 				}
798 			} else if(isdigit(argstr[0])) {
799 				sscanf(arg, "%d", &temp);
800 				if(temp == 0)
801 					temp_disable_tx_duration = DISABLE_TX_INHIBIT_DURATION;
802 				else
803 					temp_disable_tx_duration = temp;
804 			}
805 			return;
806 		}
807 	}
808 
809 	std::string cmd = "IBCHN:";
810 	std::string package = "";
811 	char buff[32];
812 
813 	package.assign(cmd);
814 
815 	memset(buff, 0, sizeof(buff));
816 	snprintf(buff, sizeof(buff)-1, "%lu", temp_disable_tx_duration);
817 	package.append(buff);
818 
819 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
820 }
821 
822 /**********************************************************************************
823  * KPSATT:<value>        // Set the fractional ratio gain value (1/value)
824  **********************************************************************************/
set_psm_fraction_gain(char * arg)825 static void set_psm_fraction_gain(char *arg)
826 {
827 	if(!arg) return;
828 	std::string args;
829 
830 	args.assign(arg);
831 
832 	if(args.empty())
833 		return reply_kpsql_fraction_gain(arg);
834 
835 	unsigned int value = 0;
836 
837 	sscanf(args.c_str(), "%u", &value);
838 
839 	update_kpsql_fractional_gain(value);
840 
841 	REQ(set_counter, cntKPSQLAttenuation, progdefaults.kpsql_attenuation);
842 }
843 
844 /**********************************************************************************
845  * KPSQLG:          // Return the fractional ratio gain value (1/value)
846  **********************************************************************************/
reply_kpsql_fraction_gain(char * arg)847 static void reply_kpsql_fraction_gain(char *arg)
848 {
849 	std::string package = "";
850 	std::string cmd = "KPSATT:";
851 	char buffer[128];
852 
853 	package.assign(cmd);
854 	memset(buffer, 0, sizeof(buffer));
855 
856 	snprintf(buffer, sizeof(buffer)-1, "%u", progdefaults.kpsql_attenuation);
857 	package.append(buffer);
858 
859 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
860 
861 }
862 
863 /**********************************************************************************
864  * WFF:<integer value> Move TXRX cursor to Frequency.
865  **********************************************************************************/
set_wf_cursor_pos(char * arg)866 static void set_wf_cursor_pos(char * arg)
867 {
868 	if(!arg) return;
869 
870 	std::string wf_cursor_pos = "";
871 	wf_cursor_pos.assign(arg);
872 
873 	if(wf_cursor_pos.empty())
874 		return reply_wf_freq_pos(arg);
875 
876 	int cursor = 0;
877 	int mode_bw = active_modem->get_bandwidth();
878 
879 	sscanf(wf_cursor_pos.c_str(), "%d", &cursor);
880 
881 	mode_bw >>= 1;
882 
883 	if((cursor - mode_bw) < 0) cursor = mode_bw;
884 	if((cursor + mode_bw) >= IMAGE_WIDTH) cursor = IMAGE_WIDTH - mode_bw;
885 
886 	active_modem->set_freq((double) cursor);
887 
888 }
889 
890 /**********************************************************************************
891  * RSIDTX:<ON|OFF>
892  **********************************************************************************/
set_rsid_tx(char * arg)893 static void set_rsid_tx(char * arg)
894 {
895 	if(!arg)
896 		return;
897 
898 	std::string rsid_tx_state = "";
899 	rsid_tx_state.assign(arg);
900 
901 	if(rsid_tx_state.empty())
902 		return reply_rsid_tx_state(arg);
903 
904 	std::string state = uppercase_string(rsid_tx_state);
905 
906 	if(state.find("ON") != std::string::npos) {
907 		REQ(set_button, btnTxRSID, 1);
908 		return;
909 	}
910 
911 	if(state.find("OFF") != std::string::npos) {
912 		REQ(set_button, btnTxRSID, 0);
913 		return;
914 	}
915 }
916 
917 /**********************************************************************************
918  * RSIDRX:<ON|OFF>
919  **********************************************************************************/
set_rsid_rx(char * arg)920 static void set_rsid_rx(char *arg)
921 {
922 	if(!arg)
923 		return;
924 
925 	std::string rsid_rx_state = "";
926 
927 	rsid_rx_state.assign(arg);
928 
929 	if(rsid_rx_state.empty())
930 		return reply_rsid_rx_state(arg);
931 
932 	std::string state = uppercase_string(rsid_rx_state);
933 
934 	if(state.find("ON") != std::string::npos) {
935 		REQ(set_button, btnRSID, 1);
936 		return;
937 	}
938 
939 	if(state.find("OFF") != std::string::npos) {
940 		REQ(set_button, btnRSID, 0);
941 		return;
942 	}
943 }
944 
945 /**********************************************************************************
946  * RSIDM:<BANDPASS|MODEM> <ACTIVE|NOTIFY>
947  **********************************************************************************/
set_rsid_mode(char * arg)948 static void set_rsid_mode(char *arg)
949 {
950 	if(!arg)
951 		return;
952 
953 	std::string strarg = "";
954 
955 	strarg.assign(arg);
956 
957 	if(strarg.empty())
958 		return reply_rsid_mode_state(arg);
959 
960 	std::string state = uppercase_string(strarg);
961 
962 	if(state.find("BANDPASS") != std::string::npos) {
963 		REQ(set_button, chkRSidWideSearch, 1);
964 	}
965 
966 	if(state.find("MODEM") != std::string::npos) {
967 		REQ(set_button, chkRSidWideSearch, 0);
968 	}
969 
970 	if(state.find("NOTIFY") != std::string::npos) {
971 		REQ(set_button, chkRSidNotifyOnly, 1);
972 	}
973 
974 	if(state.find("ACTIVE") != std::string::npos) {
975 		REQ(set_button, chkRSidNotifyOnly, 0);
976 	}
977 }
978 
979 /**********************************************************************************
980  * RSIDBCAST:<ON|OFF>
981  **********************************************************************************/
set_rsid_bc_mode(char * arg)982 static void set_rsid_bc_mode(char * arg)
983 {
984 	if(!arg)
985 		return;
986 
987 	std::string strarg = "";
988 
989 	strarg.assign(arg);
990 
991 	if(strarg.empty())
992 		return reply_rsid_bc_mode(arg);
993 
994 	std::string state = uppercase_string(strarg);
995 
996 	if(state.find("ON") != std::string::npos) {
997 		kiss_bcast_rsid_reception = true;
998 		return;
999 	}
1000 
1001 	if(state.find("OFF") != std::string::npos) {
1002 		kiss_bcast_rsid_reception = false;
1003 		return;
1004 	}
1005 }
1006 
1007 /**********************************************************************************
1008  * RSIDBCAST:<ON|OFF>
1009  **********************************************************************************/
reply_rsid_bc_mode(char * arg)1010 static void reply_rsid_bc_mode(char * arg)
1011 {
1012 	std::string package = "";
1013 	std::string cmd = "RSIDBCAST:";
1014 
1015 	package.assign(cmd);
1016 
1017 	if(kiss_bcast_rsid_reception)
1018 		package.append("ON");
1019 	else
1020 		package.append("OFF");
1021 
1022 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1023 }
1024 
1025 /**********************************************************************************
1026  * TRXSBCAST:<ON|OFF>
1027  **********************************************************************************/
set_trxs_bc_mode(char * arg)1028 static void set_trxs_bc_mode(char * arg)
1029 {
1030 	if(!arg)
1031 		return;
1032 
1033 	std::string strarg = "";
1034 
1035 	strarg.assign(arg);
1036 
1037 	if(strarg.empty())
1038 		return reply_trxs_bc_mode(arg);
1039 
1040 	std::string state = uppercase_string(strarg);
1041 
1042 	if(state.find("ON") != std::string::npos) {
1043 		kiss_bcast_trx_toggle = true;
1044 		return;
1045 	}
1046 
1047 	if(state.find("OFF") != std::string::npos) {
1048 		kiss_bcast_trx_toggle = false;
1049 		return;
1050 	}
1051 }
1052 
1053 /**********************************************************************************
1054  * TRXSBCAST:<ON|OFF>
1055  **********************************************************************************/
reply_trxs_bc_mode(char * arg)1056 static void reply_trxs_bc_mode(char * arg)
1057 {
1058 	std::string package = "";
1059 	std::string cmd = "TRXSBCAST:";
1060 
1061 	package.assign(cmd);
1062 
1063 	if(kiss_bcast_trx_toggle)
1064 		package.append("ON");
1065 	else
1066 		package.append("OFF");
1067 
1068 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1069 }
1070 
1071 /**********************************************************************************
1072  * SET TXBEBCAST:<ON|OFF>
1073  **********************************************************************************/
set_txbe_bc_mode(char * arg)1074 static void set_txbe_bc_mode(char * arg)
1075 {
1076 	if(!arg)
1077 		return;
1078 
1079 	std::string strarg = "";
1080 
1081 	strarg.assign(arg);
1082 
1083 	if(strarg.empty())
1084 		return reply_txbe_bc_mode(arg);
1085 
1086 	std::string state = uppercase_string(strarg);
1087 
1088 	if(state.find("ON") != std::string::npos) {
1089 		bcast_tx_buffer_empty_flag = true;
1090 		return;
1091 	}
1092 
1093 	if(state.find("OFF") != std::string::npos) {
1094 		bcast_tx_buffer_empty_flag = false;
1095 		return;
1096 	}
1097 }
1098 
1099 /**********************************************************************************
1100  * REPLY TXBEBCAST:<ON|OFF>
1101  **********************************************************************************/
reply_txbe_bc_mode(char * arg)1102 static void reply_txbe_bc_mode(char * arg)
1103 {
1104 	std::string package = "";
1105 	std::string cmd = "TXBEBCAST:";
1106 
1107 	package.assign(cmd);
1108 
1109 	if(bcast_tx_buffer_empty_flag)
1110 		package.append("ON");
1111 	else
1112 		package.append("OFF");
1113 
1114 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1115 }
1116 
1117 /**********************************************************************************
1118  * TNC:      FLDIGI returns TNC:FLDIGI <Version Number>
1119  **********************************************************************************/
reply_tnc_name(char * arg)1120 static void reply_tnc_name(char * arg)
1121 {
1122 	std::string package = "";
1123 	std::string cmd = "TNC:";
1124 
1125 	package.assign(cmd).append("FLDIGI ").append(PACKAGE_VERSION);
1126 
1127 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1128 }
1129 
1130 /**********************************************************************************
1131  *  TRXS:  FLDIGI returns TRXSQ:<TX|RX>
1132  **********************************************************************************/
reply_trx_state(char * arg)1133 static void reply_trx_state(char * arg)
1134 {
1135 	std::string package = "";
1136 	std::string cmd = "TRXS:";
1137 
1138 	package.assign(cmd);
1139 
1140 	if((trx_state == STATE_TX) || (trx_state == STATE_TUNE))
1141 		package.append("TX");
1142 	else
1143 		package.append("RX");
1144 
1145 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1146 }
1147 
1148 /**********************************************************************************
1149  *  RSIDRX:  FLDIGI returns RSIDRXQ:<ON|OFF>
1150  **********************************************************************************/
reply_rsid_rx_state(char * arg)1151 static void reply_rsid_rx_state(char * arg)
1152 {
1153 	std::string package = "";
1154 	std::string cmd = "RSIDRX:";
1155 
1156 	package.assign(cmd);
1157 
1158 	if(progdefaults.rsid)
1159 		package.append("ON");
1160 	else
1161 		package.append("OFF");
1162 
1163 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1164 }
1165 
1166 /**********************************************************************************
1167  *  RSIDTX:  FLDIGI returns RSIDTXQ:<ON|OFF>
1168  **********************************************************************************/
reply_rsid_tx_state(char * arg)1169 static void reply_rsid_tx_state(char * arg)
1170 {
1171 	std::string package = "";
1172 	std::string cmd = "RSIDTX:";
1173 
1174 	package.assign(cmd);
1175 
1176 	if(progdefaults.TransmitRSid)
1177 		package.append("ON");
1178 	else
1179 		package.append("OFF");
1180 
1181 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1182 }
1183 
1184 /**********************************************************************************
1185  *  TXLOCK:  FLDIGI TXLOCK:<ON|OFF> or without arg return lock state.
1186  **********************************************************************************/
set_reply_tx_lock(char * arg)1187 static void set_reply_tx_lock(char * arg)
1188 {
1189 	if(!arg) return;
1190 
1191 	std::string strarg = "";
1192 	std::string package = "";
1193 	std::string cmd = "TXLOCK:";
1194 
1195 	strarg.assign(arg);
1196 
1197 	if(strarg.empty()) {
1198 		package.assign(cmd);
1199 
1200 		if (!active_modem)
1201 			package.append("INOP");
1202 		else if(active_modem->freqlocked())
1203 			package.append("ON");
1204 		else
1205 			package.append("OFF");
1206 
1207 		kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1208 
1209 		return;
1210 	}
1211 
1212 	if (!active_modem) return;
1213 
1214 	if(strarg.find("ON") != std::string::npos) {
1215 		active_modem->set_freqlock(true);
1216 		REQ(set_button, (Fl_Button *) wf->xmtlock, 1);
1217 		return;
1218 	}
1219 
1220 	if(strarg.find("OFF") != std::string::npos) {
1221 		active_modem->set_freqlock(false);
1222 		REQ(set_button, (Fl_Button *) wf->xmtlock, 0);
1223 		return;
1224 	}
1225 }
1226 
1227 /**********************************************************************************
1228  * WFF:     FLDIGI returns WFFQ:<integer value> (0-4000) Current waterfall limit
1229  **********************************************************************************/
reply_wf_freq_pos(char * arg)1230 static void reply_wf_freq_pos(char * arg)
1231 {
1232 	std::string package = "";
1233 	std::string cmd = "WFF:";
1234 	char buff[32];
1235 
1236 	package.assign(cmd);
1237 
1238 	memset(buff, 0, sizeof(buff));
1239 	snprintf(buff, sizeof(buff) - 1, "%d", (int) active_modem->get_txfreq());
1240 
1241 	package.append(buff);
1242 
1243 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1244 }
1245 
1246 /**********************************************************************************
1247  *  RSIDM:   FLDIGI returns RSIDMQ:<BANDPASS|MODEM>,<ACTIVE|NOTIFY>
1248  **********************************************************************************/
reply_rsid_mode_state(char * arg)1249 static void reply_rsid_mode_state(char * arg)
1250 {
1251 	std::string package = "";
1252 	std::string cmd = "RSIDM:";
1253 
1254 	package.assign(cmd);
1255 
1256 	if(progdefaults.rsidWideSearch)
1257 		package.append("BANDPASS,");
1258 	else
1259 		package.append("MODEM,");
1260 
1261 	if(progdefaults.rsid_notify_only)
1262 		package.append("NOTIFY");
1263 	else
1264 		package.append("ACTIVE");
1265 
1266 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1267 }
1268 
1269 /**********************************************************************************
1270  * MODEM:   FLDIGI returns MODEMQ:<Modem ID String>   // Current Modem
1271  **********************************************************************************/
reply_active_modem(char * arg)1272 static void reply_active_modem(char * arg)
1273 {
1274 	std::string package = "";
1275 	std::string cmd = "MODEM:";
1276 	int mode = active_modem->get_mode();
1277 	package.assign(cmd);
1278 	package.append(mode_info[mode].sname);
1279 
1280 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1281 }
1282 
1283 /**********************************************************************************
1284  * HOST: Sent from FLDIGI to instuct the HOST program to return it's name and
1285  * version number.
1286  **********************************************************************************/
host_name(char * arg)1287 static void host_name(char *arg)
1288 {
1289 	if(arg) {
1290 		if(*arg) {
1291 			host_name_string.assign(arg);
1292 			LOG_INFO("%s", host_name_string.c_str());
1293 		}
1294 	}
1295 }
1296 
1297 /**********************************************************************************
1298  * MODEMBW: FLDIGI returns MODEMBWQ:<Bandwidth in Hz> // Current Modem Bandwidth
1299  **********************************************************************************/
reply_active_modem_bw(char * arg)1300 static void reply_active_modem_bw(char * arg)
1301 {
1302 	std::string package = "";
1303 	std::string cmd = "MODEMBW:";
1304 	char buff[32];
1305 
1306 	memset(buff, 0, sizeof(buff));
1307 	snprintf(buff, sizeof(buff) - 1, "%d", (int) active_modem->get_bandwidth());
1308 
1309 	package.assign(cmd).append(buff);
1310 
1311 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1312 }
1313 
1314 /**********************************************************************************
1315  * WFBW:    FLDIGI returns WFBWQ:<LOWER HZ>,<UPPER HZ>
1316  **********************************************************************************/
reply_waterfall_bw(char * arg)1317 static void reply_waterfall_bw(char * arg)
1318 {
1319 	std::string package = "";
1320 	std::string cmd = "WFBW:";
1321 	char buff[32];
1322 
1323 	memset(buff, 0, sizeof(buff));
1324 	snprintf(buff, sizeof(buff) - 1, "%d,%d", (int) progdefaults.LowFreqCutoff,
1325 			 progdefaults.HighFreqCutoff );
1326 
1327 	package.assign(cmd).append(buff);
1328 
1329 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1330 }
1331 
1332 /**********************************************************************************
1333  * MODEML:  FLDIGI returns MODEML:Modem1,Modem2,...
1334  * A List of comma delimited modem ID strings.
1335  **********************************************************************************/
reply_modem_list(char * arg)1336 static void reply_modem_list(char * arg)
1337 {
1338 	int index = 0;
1339 	int count = 0;
1340 	std::string package = "";
1341 	std::string cmd = "MODEML:";
1342 
1343 	package.assign(cmd);
1344 
1345 	count = availabe_kiss_modems.size();
1346 
1347 	for(index = 0; index < count - 1; index++)
1348 		package.append(availabe_kiss_modems[index]).append(",");
1349 	package.append(availabe_kiss_modems[index]);
1350 
1351 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1352 }
1353 
1354 /**********************************************************************************
1355  * TXBUF: FLDIGI returns TXBUFQ:<number_of_bytes_in_the_tx_buffer>
1356  **********************************************************************************/
reply_tx_buffer_count(char * arg)1357 static void reply_tx_buffer_count(char * arg)
1358 {
1359 	char *buffer = (char *)0;
1360 	unsigned int buffer_size = 64;
1361 	unsigned tx_buffer_count = 0;
1362 	std::string package = "";
1363 	std::string cmd = "TXBUF:";
1364 
1365 	buffer = new char[buffer_size];
1366 
1367 	if(!buffer) {
1368 		LOG_DEBUG("%s", "Buffer allocation Error");
1369 		return;
1370 	}
1371 
1372 	{
1373 		guard_lock to_radio_lock(&to_radio_mutex);
1374 		tx_buffer_count = to_radio.size();
1375 	}
1376 
1377 	memset(buffer, 0, buffer_size);
1378 	snprintf(buffer, buffer_size - 1, "%u", tx_buffer_count);
1379 
1380 	package.assign(cmd).append(buffer);
1381 
1382 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1383 
1384 	if(buffer) delete [] buffer;
1385 
1386 }
1387 
1388 /**********************************************************************************
1389  * SQL:<ON|OFF>        // SQL On/Off
1390  **********************************************************************************/
set_sql_on_off(char * arg)1391 static void set_sql_on_off(char * arg)
1392 {
1393 	if(!arg)
1394 		return;
1395 
1396 	std::string strarg = "";
1397 
1398 	strarg.assign(arg);
1399 
1400 	if(strarg.empty())
1401 		return reply_sql_on_off(arg);
1402 
1403 	if(strarg.find("ON") != std::string::npos) {
1404 		REQ(set_button, btnSQL, 1);
1405 		return;
1406 	}
1407 
1408 	if(strarg.find("OFF") != std::string::npos) {
1409 		REQ(set_button, btnSQL, 0);
1410 		return;
1411 	}
1412 }
1413 
1414 /**********************************************************************************
1415  * SQL:      FLDIGI returns SQLQ:<ON|OFF>
1416  **********************************************************************************/
reply_sql_on_off(char * arg)1417 static void reply_sql_on_off(char * arg)
1418 {
1419 	std::string package = "";
1420 	std::string cmd = "SQL:";
1421 
1422 	package.assign(cmd);
1423 
1424 	if(progStatus.sqlonoff)
1425 		package.append("ON");
1426 	else
1427 		package.append("OFF");
1428 
1429 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1430 }
1431 
1432 /**********************************************************************************
1433  * SQLP:<0-100>        // Current Symbol Quality Level
1434  **********************************************************************************/
reply_sql_pwr_level(char * arg)1435 static void reply_sql_pwr_level(char * arg)
1436 {
1437 	std::string package = "";
1438 	std::string cmd = "SQLP:";
1439 	char buffer[64];
1440 
1441 	package.assign(cmd);
1442 
1443 	memset(buffer, 0, sizeof(buffer));
1444 	snprintf(buffer, sizeof(buffer)-1, "%u", (unsigned int) progStatus.squelch_value);
1445 	package.append(buffer);
1446 
1447 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1448 
1449 }
1450 
1451 /**********************************************************************************
1452  * SQLS:<0-100> // Set SQL Level (percent)
1453  **********************************************************************************/
set_sql_level(char * arg)1454 static void set_sql_level(char * arg)
1455 {
1456 	if(!arg)
1457 		return;
1458 	int value = 0;
1459 
1460 	std::string strarg = "";
1461 
1462 	strarg.assign(arg);
1463 
1464 	if(strarg.empty())
1465 		return reply_sql_level(arg);
1466 
1467 	sscanf(strarg.c_str(), "%d", &value);
1468 	if(value < 1) value = 1;
1469 	if(value > 100) value = 100;
1470 
1471 	progStatus.sldrSquelchValue = value;
1472 
1473 	if(!progStatus.kpsql_enabled)
1474 		REQ(set_slider2, sldrSquelch, value);
1475 }
1476 
1477 /**********************************************************************************
1478  * SQLS:     FLDIGI returns SQLSQ:<0-100>  // Set SQL Level Query (percent)
1479  **********************************************************************************/
reply_sql_level(char * arg)1480 static void reply_sql_level(char * arg)
1481 {
1482 	std::string package = "";
1483 	std::string cmd = "SQLS:";
1484 	char buffer[64];
1485 
1486 	package.assign(cmd);
1487 
1488 	memset(buffer, 0, sizeof(buffer));
1489 	snprintf(buffer, sizeof(buffer)-1, "%u", (unsigned int) progStatus.sldrSquelchValue);
1490 	package.append(buffer);
1491 
1492 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1493 }
1494 
1495 /**********************************************************************************
1496  * BCHN:<ON|OFF>       // Busy Channel On/Off
1497  **********************************************************************************/
set_busy_channel_on_off(char * arg)1498 static void set_busy_channel_on_off(char * arg)
1499 {
1500 	if(!arg)
1501 		return;
1502 
1503 	std::string strarg = "";
1504 
1505 	strarg.assign(arg);
1506 
1507 	if(strarg.empty())
1508 		return reply_busy_channel_on_off(arg);
1509 
1510 	if(strarg.find("ON") != std::string::npos) {
1511 		REQ(set_button, btnEnableBusyChannel, 1);
1512 		return;
1513 	}
1514 
1515 	if(strarg.find("OFF") != std::string::npos) {
1516 		REQ(set_button, btnEnableBusyChannel, 0);
1517 		return;
1518 	}
1519 
1520 }
1521 
1522 /**********************************************************************************
1523  * BCHN:     FLDIGI returns BCHNQ:<ON|OFF>  // Busy Channel State On/Off Query
1524  **********************************************************************************/
reply_busy_channel_on_off(char * arg)1525 static void reply_busy_channel_on_off(char * arg)
1526 {
1527 	std::string package = "";
1528 	std::string cmd = "BCHN:";
1529 
1530 	package.assign(cmd);
1531 
1532 	if(progdefaults.enableBusyChannel)
1533 		package.append("ON");
1534 	else
1535 		package.append("OFF");
1536 
1537 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1538 }
1539 
1540 /**********************************************************************************
1541  * BCHNS<0-999>        // Busy Channel Wait Duration (seconds)
1542  **********************************************************************************/
set_busy_channel_duration(char * arg)1543 static void set_busy_channel_duration(char * arg)
1544 {
1545 	if(!arg)
1546 		return;
1547 	int value = 0;
1548 	std::string strarg = "";
1549 
1550 	strarg.assign(arg);
1551 
1552 	if(strarg.empty())
1553 		return reply_busy_channel_duration(arg);
1554 
1555 	sscanf(strarg.c_str(), "%d", &value);
1556 	if(value < 1) value = 1;
1557 
1558 	REQ(set_counter, cntBusyChannelSeconds, value);
1559 }
1560 
1561 /**********************************************************************************
1562  * BCHNS:    FLDIGI returns BCHNSQ:<0-999> // Busy Channel Wait Duration Query (seconds)
1563  **********************************************************************************/
reply_busy_channel_duration(char * arg)1564 static void reply_busy_channel_duration(char * arg)
1565 {
1566 	std::string package = "";
1567 	std::string cmd = "BCHNS:";
1568 	char buffer[64];
1569 
1570 	package.assign(cmd);
1571 
1572 	memset(buffer, 0, sizeof(buffer));
1573 	snprintf(buffer, sizeof(buffer)-1, "%d", progdefaults.busyChannelSeconds);
1574 	package.append(buffer);
1575 
1576 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1577 
1578 }
1579 
1580 /**********************************************************************************
1581  * BUSY:     FLDIGI returns BUSY:<T|F>  // Modem band pass signal presents
1582  **********************************************************************************/
reply_busy_state(char * arg)1583 static void reply_busy_state(char * arg)
1584 {
1585 	std::string package = "";
1586 	std::string cmd = "BUSY:";
1587 
1588 	package.assign(cmd);
1589 
1590 	if((trx_state == STATE_TX) || \
1591 	   (kpsql_pl > kpsql_threshold) || \
1592 	   (inhibit_tx_seconds)) {
1593 		package.append("T");
1594 	} else {
1595 		package.append("F");
1596 	}
1597 
1598 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1599 }
1600 
1601 /**********************************************************************************
1602  * KPSQL:<ON|OFF> Depreciated
1603  **********************************************************************************/
set_kpsql_on_off(char * arg)1604 static void set_kpsql_on_off(char * arg)
1605 {
1606 	if(!arg)
1607 		return;
1608 
1609 	std::string strarg = "";
1610 
1611 	strarg.assign(arg);
1612 
1613 	if(strarg.empty())
1614 		return reply_kpsql_on_off(arg);
1615 
1616 	if(strarg.find("ON") != std::string::npos) {
1617 		REQ(set_button, btnPSQL, 1);
1618 		return;
1619 	}
1620 
1621 	if(strarg.find("OFF") != std::string::npos) {
1622 		REQ(set_button, btnPSQL, 0);
1623 		return;
1624 	}
1625 
1626 }
1627 
1628 /**********************************************************************************
1629  * PSM:<ON|OFF>
1630  **********************************************************************************/
set_psm_on_off(char * arg)1631 static void set_psm_on_off(char * arg)
1632 {
1633 	if(!arg)
1634 		return;
1635 
1636 	std::string strarg = "";
1637 
1638 	strarg.assign(arg);
1639 
1640 	if(strarg.empty())
1641 		return reply_psm_on_off(arg);
1642 
1643 	if(strarg.find("ON") != std::string::npos) {
1644 		REQ(set_button, btnPSQL, 1);
1645 		return;
1646 	}
1647 
1648 	if(strarg.find("OFF") != std::string::npos) {
1649 		REQ(set_button, btnPSQL, 0);
1650 		return;
1651 	}
1652 
1653 }
1654 
1655 /**********************************************************************************
1656  * KPSQL:<ON|OFF> Depreciated
1657  **********************************************************************************/
reply_kpsql_on_off(char * arg)1658 static void reply_kpsql_on_off(char * arg)
1659 {
1660 	std::string package = "";
1661 	std::string cmd = "KPSQL:";
1662 
1663 	package.assign(cmd);
1664 
1665 	if(progStatus.kpsql_enabled)
1666 		package.append("ON");
1667 	else
1668 		package.append("OFF");
1669 
1670 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1671 }
1672 
1673 /**********************************************************************************
1674  * PSM:<ON|OFF>
1675  **********************************************************************************/
reply_psm_on_off(char * arg)1676 static void reply_psm_on_off(char * arg)
1677 {
1678 	std::string package = "";
1679 	std::string cmd = "PSM:";
1680 
1681 	package.assign(cmd);
1682 
1683 	if(progStatus.kpsql_enabled)
1684 		package.append("ON");
1685 	else
1686 		package.append("OFF");
1687 
1688 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1689 }
1690 
1691 /**********************************************************************************
1692  * KPSQLP:<0-100> Depreciated
1693  **********************************************************************************/
reply_kpsql_pwr_level(char * arg)1694 static void reply_kpsql_pwr_level(char * arg)
1695 {
1696 	std::string package = "";
1697 	std::string cmd = "KPSQLP:";
1698 	char buffer[64];
1699 	float plevel = 0;
1700 	float scale = 100.0 / ((float) HISTO_COUNT);
1701 
1702 	package.assign(cmd);
1703 
1704 	if(kpsql_pl > (double) HISTO_COUNT) {
1705 		plevel = HISTO_COUNT;
1706 	} else {
1707 		plevel = kpsql_pl;
1708 	}
1709 
1710 	plevel *= scale;
1711 
1712 	memset(buffer, 0, sizeof(buffer));
1713 	snprintf(buffer, sizeof(buffer)-1, "%u", (unsigned int) plevel);
1714 	package.append(buffer);
1715 
1716 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1717 }
1718 
1719 /**********************************************************************************
1720  * PSMP:<0-100>
1721  **********************************************************************************/
reply_psm_pwr_level(char * arg)1722 static void reply_psm_pwr_level(char * arg)
1723 {
1724 	std::string package = "";
1725 	std::string cmd = "PSMP:";
1726 	char buffer[64];
1727 	float plevel = 0;
1728 	float scale = 100.0 / ((float) HISTO_COUNT);
1729 
1730 	package.assign(cmd);
1731 
1732 	if(kpsql_pl > (double) HISTO_COUNT) {
1733 		plevel = HISTO_COUNT;
1734 	} else {
1735 		plevel = kpsql_pl;
1736 	}
1737 
1738 	plevel *= scale;
1739 
1740 	memset(buffer, 0, sizeof(buffer));
1741 	snprintf(buffer, sizeof(buffer)-1, "%u", (unsigned int) plevel);
1742 	package.append(buffer);
1743 
1744 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1745 }
1746 
1747 /**********************************************************************************
1748  * PSMS:<0-100>
1749  **********************************************************************************/
set_psm_squelch_level(char * arg)1750 static void set_psm_squelch_level(char * arg)
1751 {
1752 	if(!arg)
1753 		return;
1754 
1755 	std::string strarg = "";
1756 
1757 	strarg.assign(arg);
1758 
1759 	if(strarg.empty())
1760 		return reply_psm_squelch_level(arg);
1761 
1762 	int value = 0;
1763 
1764 	sscanf(strarg.c_str(), "%d", &value);
1765 
1766 	if(value < 1) value = 1;
1767 	if(value > 100) value = 100;
1768 
1769 	progStatus.sldrPwrSquelchValue = value;
1770 
1771 	if(progStatus.kpsql_enabled)
1772 		REQ(set_slider2, sldrSquelch, value);
1773 
1774 }
1775 
1776 /**********************************************************************************
1777  * KPSQLS:<0-100> Depreciated
1778  **********************************************************************************/
set_kpsql_squelch_level(char * arg)1779 static void set_kpsql_squelch_level(char * arg)
1780 {
1781 	if(!arg)
1782 		return;
1783 
1784 	std::string strarg = "";
1785 
1786 	strarg.assign(arg);
1787 
1788 	if(strarg.empty())
1789 		return reply_kpsql_squelch_level(arg);
1790 
1791 	int value = 0;
1792 
1793 	sscanf(strarg.c_str(), "%d", &value);
1794 
1795 	if(value < 1) value = 1;
1796 	if(value > 100) value = 100;
1797 
1798 	progStatus.sldrPwrSquelchValue = value;
1799 
1800 	if(progStatus.kpsql_enabled)
1801 		REQ(set_slider2, sldrSquelch, value);
1802 
1803 }
1804 
1805 /**********************************************************************************
1806  * KPSQLS: Depreciated
1807  **********************************************************************************/
reply_kpsql_squelch_level(char * arg)1808 static void reply_kpsql_squelch_level(char * arg)
1809 {
1810 	std::string package = "";
1811 	std::string cmd = "KPSQLS:";
1812 	char buffer[64];
1813 
1814 	package.assign(cmd);
1815 
1816 	memset(buffer, 0, sizeof(buffer));
1817 	snprintf(buffer, sizeof(buffer)-1, "%u", (unsigned int) progStatus.sldrPwrSquelchValue);
1818 	package.append(buffer);
1819 
1820 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1821 }
1822 
1823 /**********************************************************************************
1824  * PSMS:
1825  **********************************************************************************/
reply_psm_squelch_level(char * arg)1826 static void reply_psm_squelch_level(char * arg)
1827 {
1828 	std::string package = "";
1829 	std::string cmd = "PSMS:";
1830 	char buffer[64];
1831 
1832 	package.assign(cmd);
1833 
1834 	memset(buffer, 0, sizeof(buffer));
1835 	snprintf(buffer, sizeof(buffer)-1, "%u", (unsigned int) progStatus.sldrPwrSquelchValue);
1836 	package.append(buffer);
1837 
1838 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1839 }
1840 
1841 /**********************************************************************************
1842  * KISSRAW:<ON|OFF|ONLY>    // Enable RAW unaltered data over KISS
1843  **********************************************************************************/
set_kiss_raw_mode(char * arg)1844 static void set_kiss_raw_mode(char * arg)
1845 {
1846 	if(!arg)
1847 		return;
1848 
1849 	std::string strarg = "";
1850 
1851 	strarg.assign(arg);
1852 
1853 	if(strarg.empty())
1854 		return reply_kiss_raw_mode(arg);
1855 
1856 	// Longer compares first
1857 	if(strarg.find("ONLY") != std::string::npos) {
1858 		kiss_raw_enabled = KISS_RAW_ONLY;
1859 		return;
1860 	}
1861 
1862 	if(strarg.find("ON") != std::string::npos) {
1863 		kiss_raw_enabled = KISS_RAW_ON;
1864 		return;
1865 	}
1866 
1867 	if(strarg.find("OFF") != std::string::npos) {
1868 		kiss_raw_enabled = KISS_RAW_DISABLED;
1869 		return;
1870 	}
1871 
1872 }
1873 
1874 /**********************************************************************************
1875  * KISSRAW:<ON|OFF|ONLY>    // Enable RAW unaltered data over KISS
1876  **********************************************************************************/
reply_kiss_raw_mode(char * arg)1877 static void reply_kiss_raw_mode(char * arg)
1878 {
1879 	std::string package = "";
1880 	std::string cmd = "KISSRAW:";
1881 
1882 	package.assign(cmd);
1883 
1884 	switch(kiss_raw_enabled) {
1885 		case KISS_RAW_ONLY:
1886 			package.append("ONLY");
1887 			break;
1888 
1889 		case KISS_RAW_ON:
1890 			package.append("ON");
1891 			break;
1892 
1893 		case KISS_RAW_DISABLED:
1894 			package.append("OFF");
1895 			break;
1896 
1897 		default:
1898 			return;
1899 	}
1900 
1901 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1902 }
1903 
1904 /**********************************************************************************
1905  * KISSCRCM:<NONE|SMACK|CCITT|XOR|FCS>
1906  **********************************************************************************/
set_crc_mode(char * arg)1907 static void set_crc_mode(char * arg)
1908 {
1909 	if(!arg)
1910 		return;
1911 
1912 	std::string strarg = "";
1913 
1914 	strarg.assign(arg);
1915 
1916 	if(strarg.empty())
1917 		return reply_crc_mode(arg);
1918 
1919 	if(strarg.find("SMACK") != std::string::npos) {
1920 		smack_crc_enabled = true;
1921 		crc_mode = CRC16_CCITT;
1922 		return;
1923 	}
1924 
1925 	if(strarg.find("CCITT") != std::string::npos) {
1926 		smack_crc_enabled = true;
1927 		crc_mode = CRC16_CCITT;
1928 		return;
1929 	}
1930 
1931 	if(strarg.find("FCS") != std::string::npos) {
1932 		smack_crc_enabled = true;
1933 		crc_mode = CRC16_FCS;
1934 		return;
1935 	}
1936 
1937 	if(strarg.find("XOR") != std::string::npos) {
1938 		smack_crc_enabled = true;
1939 		crc_mode = CRC8_XOR;
1940 		return;
1941 	}
1942 
1943 	if(strarg.find("NONE") != std::string::npos) {
1944 		smack_crc_enabled = false;
1945 		return;
1946 	}
1947 
1948 }
1949 
1950 /**********************************************************************************
1951  * KISSCRCM:<NONE|SMACK>,<NONE|CCITT|XOR|FCS>
1952  **********************************************************************************/
reply_crc_mode(char * arg)1953 static void reply_crc_mode(char *arg)
1954 {
1955 	std::string package = "";
1956 	std::string cmd = "KISSCRCM:";
1957 
1958 	package.assign(cmd);
1959 
1960 	if(smack_crc_enabled)
1961 		package.append("SMACK,");
1962 	else
1963 		package.append("NONE,");
1964 
1965 	switch(crc_mode) {
1966 		case CRC16_NONE:
1967 			package.append("NONE");
1968 			break;
1969 
1970 		case CRC16_CCITT:
1971 			package.append("CCITT");
1972 			break;
1973 
1974 		case CRC16_FCS:
1975 			package.append("FCS");
1976 			break;
1977 
1978 		case CRC8_XOR:
1979 			package.append("XOR");
1980 			break;
1981 
1982 		default:
1983 			package.append("UNDEFINED");
1984 
1985 	}
1986 
1987 	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
1988 }
1989 
1990 /**********************************************************************************
1991  * RSIDN:NEW_WF_OFFSET,NEW_MODEM,OLD_WF_OFFSET,OLD_MODEM,<ACTIVE|NOTIFY>
1992  **********************************************************************************/
bcast_rsid_kiss_frame(int new_wf_pos,int new_mode,int old_wf_pos,int old_mode,int notify)1993 bool bcast_rsid_kiss_frame(int new_wf_pos, int new_mode, int old_wf_pos, int old_mode, int notify)
1994 {
1995 	guard_lock kiss_bc_frame_lock(&kiss_bc_frame_mutex);
1996 
1997 	char buffer[256];
1998 	char old_modem_name[64];
1999 	char new_modem_name[64];
2000 	char *notify_str = (char *) "";
2001 	KISS_QUEUE_FRAME *frame = (KISS_QUEUE_FRAME *)0;
2002 	std::string package = "";
2003 
2004 	if(new_mode >= NUM_MODES || old_mode >= NUM_MODES)
2005 		return false;
2006 
2007 	if(new_mode < 0 || old_mode < 0)
2008 		return false;
2009 
2010 	if(!(mode_info[new_mode].iface_io & KISS_IO))
2011 		return false;
2012 
2013 	if(old_mode != new_mode || new_wf_pos != old_wf_pos) {
2014 		psm_reset_histogram();
2015 	}
2016 
2017 	if(!kiss_bcast_rsid_reception) return true;
2018 
2019 	if(new_wf_pos == 0) {
2020 		new_wf_pos = old_wf_pos;
2021 		notify = RSID_KISS_USER;
2022 	}
2023 
2024 	switch(notify) {
2025 		case RSID_KISS_NOTIFY:
2026 			notify_str = (char *) "NOTIFY";
2027 			break;
2028 
2029 		case RSID_KISS_ACTIVE:
2030 			notify_str = (char *) "ACTIVE";
2031 			break;
2032 
2033 		case RSID_KISS_USER:
2034 			notify_str = (char *) "USER";
2035 			break;
2036 
2037 		default:
2038 			LOG_DEBUG("%s", "Unknown KISS frame RSID BC Source");
2039 			return false;
2040 	}
2041 
2042 	// Send all modem names in capital letters
2043 
2044 	memset(old_modem_name, 0, sizeof(old_modem_name));
2045 	strncpy(old_modem_name, mode_info[old_mode].sname, sizeof(old_modem_name) - 1);
2046 
2047 	for(size_t i = 0; i < sizeof(old_modem_name); i++) {
2048 		if(old_modem_name[i])
2049 			old_modem_name[i] = toupper(old_modem_name[i]);
2050 		else
2051 			break;
2052 	}
2053 
2054 	memset(new_modem_name, 0, sizeof(new_modem_name));
2055 	strncpy(new_modem_name, mode_info[new_mode].sname, sizeof(new_modem_name) - 1);
2056 
2057 	for(size_t i = 0; i < sizeof(new_modem_name); i++) {
2058 		if(new_modem_name[i])
2059 			new_modem_name[i] = toupper(new_modem_name[i]);
2060 		else
2061 			break;
2062 	}
2063 
2064 	memset(buffer, 0, sizeof(buffer));
2065 	snprintf(buffer, sizeof(buffer)-1, "RSIDN:%d,%s,%d,%s,%s", new_wf_pos, new_modem_name, \
2066 			 old_wf_pos, old_modem_name, notify_str);
2067 
2068 	package.assign(buffer);
2069 
2070 	frame = encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no);
2071 
2072 	if(!frame) {
2073 		LOG_DEBUG("%s", "Broadcast Hardware Frame Assembly Failure");
2074 		return true;
2075 	}
2076 
2077 	kiss_bc_frame.append((const char *) frame->data, (size_t) frame->size);
2078 
2079 	if(frame->data)	delete [] frame->data;
2080 	if(frame) delete frame;
2081 
2082 	return true;
2083 }
2084 
2085 /**********************************************************************************
2086  *  TRXS:<RX|TX> // Transmit to HOST during a state change between RX/TX or TX/RX.
2087  **********************************************************************************/
bcast_trxs_kiss_frame(int state)2088 void bcast_trxs_kiss_frame(int state)
2089 {
2090 	guard_lock kiss_bc_frame_lock(&kiss_bc_frame_mutex);
2091 
2092 	KISS_QUEUE_FRAME *frame = (KISS_QUEUE_FRAME *)0;
2093 	std::string package;
2094 
2095 	package.assign("TRXS:");
2096 
2097 	switch(state) {
2098 		case STATE_RX:
2099 			package.append("RX") ;
2100 			break;
2101 
2102 		case STATE_TUNE:
2103 		case STATE_TX:
2104 			package.append("TX") ;
2105 			break;
2106 
2107 		default:
2108 			LOG_DEBUG("%s", "Unknown Transmit State");
2109 			return;
2110 
2111 	}
2112 
2113 	frame = encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no);
2114 
2115 	if(!frame) {
2116 		LOG_DEBUG("%s", "Broadcast Hardware Frame Assembly Failure");
2117 		return;
2118 	}
2119 
2120 	kiss_bc_frame.append((const char *) frame->data, (size_t) frame->size);
2121 
2122 	if(frame->data)	delete [] frame->data;
2123 	if(frame) delete frame;
2124 }
2125 
2126 /**********************************************************************************
2127  * TXBE: // Broadcast empty transmit buffer state
2128  **********************************************************************************/
bcast_tx_buffer_empty_kiss_frame(void)2129 void bcast_tx_buffer_empty_kiss_frame(void)
2130 {
2131 	if(!bcast_tx_buffer_empty_flag) return;
2132 
2133 	guard_lock kiss_bc_frame_lock(&kiss_bc_frame_mutex);
2134 
2135 	KISS_QUEUE_FRAME *frame = (KISS_QUEUE_FRAME *)0;
2136 	std::string package;
2137 
2138 	package.assign("TXBE:");
2139 
2140 	frame = encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no);
2141 
2142 	if(!frame) {
2143 		LOG_DEBUG("%s", "Broadcast Hardware Frame Assembly Failure");
2144 		return;
2145 	}
2146 
2147 	kiss_bc_frame.append((const char *) frame->data, (size_t) frame->size);
2148 
2149 	if(frame->data)	delete [] frame->data;
2150 	if(frame) delete frame;
2151 }
2152 
2153 /**********************************************************************************
2154  *
2155  **********************************************************************************/
exec_hardware_command(std::string cmd,std::string arg)2156 static void exec_hardware_command(std::string cmd, std::string arg)
2157 {
2158 	if(cmd.empty()) return;
2159 	if(kiss_reset_flag) return;
2160 	int pos = 0;
2161 	int a = 0;
2162 	int b = 0;
2163 	int comp_size = 0;
2164 	int index = 0;
2165 	int count = sizeof(exec_match) / sizeof(EXEC_HARDWARE_CMD_MATCH);
2166 	string cmp = "";
2167 
2168 	for(index = 0; index < count; index++) {
2169 		if(exec_match[index].cmd == (char *)0) return;
2170 		cmp.assign(exec_match[index].cmd);
2171 		if((pos = cmp.find(cmd)) != (int)(string::npos)) {
2172 			a = cmp.size();
2173 			b = cmd.size();
2174 
2175 			if(a > b)
2176 				comp_size = a;
2177 			else
2178 				comp_size = b;
2179 
2180 			if(cmd.compare(pos, comp_size, cmp) == 0) {
2181 				if(exec_match[index].cmd_func)
2182 					(*exec_match[index].cmd_func)((char *) arg.c_str());
2183 				return;
2184 			}
2185 		}
2186 	}
2187 }
2188 
2189 /**********************************************************************************
2190  *
2191  **********************************************************************************/
kiss_queue_frame(KISS_QUEUE_FRAME * frame,std::string cmd)2192 static bool kiss_queue_frame(KISS_QUEUE_FRAME * frame, std::string cmd)
2193 {
2194 	if(!frame) {
2195 		LOG_DEBUG("Null frame (%s)", cmd.c_str());
2196 		return false;
2197 	}
2198 
2199 	if(frame->size == 0 || frame->data == (char *)0) {
2200 		LOG_DEBUG("Frame null content (%s)", cmd.c_str());
2201 		if(frame->data) delete[] frame->data;
2202 		delete frame;
2203 		return false;
2204 	}
2205 
2206 	WriteToHostBuffered((const char *) frame->data, (size_t) frame->size);
2207 
2208 	delete[] frame->data;
2209 	delete frame;
2210 
2211 	return true;
2212 }
2213 
2214 /**********************************************************************************
2215  *
2216  **********************************************************************************/
kiss_encode(char * src,size_t src_size,char ** dst)2217 size_t kiss_encode(char *src, size_t src_size, char **dst)
2218 {
2219 	if(!src || !dst || src_size < 1) return 0;
2220 
2221 	size_t index = 0;
2222 	int count = 0;
2223 	int buffer_size = 0;
2224 	int byte = 0;
2225 	char *buffer = (char *)0;
2226 
2227 	buffer_size = (src_size * KISS_BUFFER_FACTOR) + BUFFER_PADDING;
2228 	buffer = new char[buffer_size];
2229 
2230 	if(!buffer) {
2231 		LOG_DEBUG("Memory allocation error near line %d", __LINE__);
2232 		*dst = (char *)0;
2233 		return 0;
2234 	}
2235 
2236 	memset(buffer, 0, buffer_size);
2237 	count = 0;
2238 	buffer[count++] = KISS_FEND;
2239 
2240 	for(index = 0; index < src_size; index++) {
2241 		byte = (int) src[index] & 0xFF;
2242 		switch(byte) {
2243 			case KISS_FESC:
2244 				buffer[count++] = KISS_FESC;
2245 				buffer[count++] = KISS_TFESC;
2246 				break;
2247 
2248 			case KISS_FEND:
2249 				buffer[count++] = KISS_FESC;
2250 				buffer[count++] = KISS_TFEND;
2251 				break;
2252 
2253 			default:
2254 				buffer[count++] = byte;
2255 		}
2256 	}
2257 
2258 	buffer[count++] = KISS_FEND;
2259 	*dst = (char *) buffer;
2260 
2261 	return count;
2262 }
2263 
2264 /**********************************************************************************
2265  *
2266  **********************************************************************************/
kiss_decode(char * src,size_t src_size,char ** dst)2267 size_t kiss_decode(char *src, size_t src_size, char **dst)
2268 {
2269 	if(!src || !dst || src_size < 1) return 0;
2270 
2271 	size_t index = 0;
2272 	int count = 0;
2273 	int buffer_size = 0;
2274 	int byte = 0;
2275 	int last_byte = 0;
2276 	char *buffer = (char *)0;
2277 
2278 	buffer_size = src_size + BUFFER_PADDING;
2279 	buffer = new char[buffer_size];
2280 
2281 	if(!buffer) {
2282 		LOG_DEBUG("Memory allocation error near line %d", __LINE__);
2283 		*dst = (char *)0;
2284 		return 0;
2285 	}
2286 
2287 	memset(buffer, 0, buffer_size);
2288 	count = 0;
2289 	last_byte = KISS_INVALID;
2290 
2291 	for(index = 0; index < src_size; index++) {
2292 
2293 		byte = src[index] & 0xFF;
2294 
2295 		switch(byte) {
2296 			case KISS_FEND:
2297 				continue;
2298 
2299 			case KISS_FESC:
2300 				break;
2301 
2302 			case KISS_TFEND:
2303 				if(last_byte == KISS_FESC)
2304 					buffer[count++] = KISS_FEND;
2305 				else
2306 					buffer[count++] = byte;
2307 				break;
2308 
2309 			case KISS_TFESC:
2310 				if(last_byte == KISS_FESC)
2311 					buffer[count++] = KISS_FESC;
2312 				else
2313 					buffer[count++] = byte;
2314 				break;
2315 
2316 			default:
2317 				buffer[count++] = byte;
2318 		}
2319 
2320 		last_byte = byte;
2321 	}
2322 
2323 	*dst = (char *) buffer;
2324 	return count;
2325 }
2326 
2327 #if 0
2328 /**********************************************************************************
2329  *
2330  **********************************************************************************/
2331 std::string kiss_decode(std::string frame)
2332 {
2333 	int count = 0;
2334 	int frame_size = 0;
2335 	char *dst = (char *)0;
2336 
2337 	static std::string ret_str = "";
2338 
2339 	if(frame.empty()) return frame;
2340 
2341 	frame_size = frame.size();
2342 
2343 	ret_str.clear();
2344 	ret_str.reserve(frame_size + BUFFER_PADDING);
2345 
2346 	count = kiss_decode((char *) frame.c_str(), frame.size(), &dst);
2347 
2348 	if(count && dst) {
2349 		ret_str.assign(dst, count);
2350 		dst[0] = 0;
2351 		delete [] dst;
2352 	}
2353 
2354 	return ret_str;
2355 }
2356 #endif // 0
2357 
2358 /**********************************************************************************
2359  *
2360  **********************************************************************************/
kiss_encode(std::string frame)2361 std::string kiss_encode(std::string frame)
2362 {
2363 	int count = 0;
2364 	int frame_size = 0;
2365 	char *dst = (char *)0;
2366 
2367 	static std::string ret_str = "";
2368 
2369 	if(frame.empty()) return frame;
2370 
2371 	frame_size = frame.size();
2372 
2373 	ret_str.clear();
2374 	ret_str.reserve((frame_size * 2) + BUFFER_PADDING);
2375 
2376 	count = kiss_encode((char *) frame.c_str(), frame.size(), &dst);
2377 
2378 	if(count && dst) {
2379 		ret_str.assign(dst, count);
2380 		dst[0] = 0;
2381 		delete [] dst;
2382 	}
2383 
2384 	return ret_str;
2385 }
2386 
2387 
2388 /**********************************************************************************
2389  *
2390  **********************************************************************************/
hdlc_encode(char * src,size_t src_size,char ** dst)2391 size_t hdlc_encode(char *src, size_t src_size, char **dst)
2392 {
2393 	if(!src || !dst || src_size < 1) return 0;
2394 
2395 	size_t index = 0;
2396 	int count = 0;
2397 	int buffer_size = 0;
2398 	int byte = 0;
2399 	char *buffer = (char *)0;
2400 
2401 	buffer_size = (src_size * HDLC_BUFFER_FACTOR) + BUFFER_PADDING;
2402 	buffer = new char[buffer_size];
2403 
2404 	if(!buffer) {
2405 		LOG_DEBUG("Memory allocation error near line %d", __LINE__);
2406 		*dst = (char *)0;
2407 		return 0;
2408 	}
2409 
2410 	memset(buffer, 0, buffer_size);
2411 	count = 0;
2412 	buffer[count++] = ' ';
2413 	buffer[count++] = KISS_FEND;
2414 
2415 	for(index = 0; index < src_size; index++) {
2416 		byte = (int) src[index] & 0xFF;
2417 
2418 		if(not_allowed[byte]) {
2419 			buffer[count++] = HDLC_CNT;
2420 			if((byte + HDLC_CNT_OFFSET) > 255)
2421 				buffer[count++] = ((byte - HDLC_CNT_OFFSET) & 0xFF);
2422 			else
2423 				buffer[count++] = ((byte + HDLC_CNT_OFFSET) & 0xFF);
2424 			continue;
2425 		}
2426 
2427 		switch(byte) {
2428 			case KISS_FESC:
2429 				buffer[count++] = KISS_FESC;
2430 				buffer[count++] = KISS_TFESC;
2431 				break;
2432 
2433 			case KISS_FEND:
2434 				buffer[count++] = KISS_FESC;
2435 				buffer[count++] = KISS_TFEND;
2436 				break;
2437 
2438 			case HDLC_CNT:
2439 				buffer[count++] = KISS_FESC;
2440 				buffer[count++] = HDLC_TCNT;
2441 				break;
2442 
2443 			default:
2444 				buffer[count++] = byte;
2445 		}
2446 	}
2447 
2448 	buffer[count++] = KISS_FEND;
2449 	buffer[count++] = ' ';
2450 
2451 	*dst = (char *) buffer;
2452 
2453 	return count;
2454 }
2455 
2456 /**********************************************************************************
2457  *
2458  **********************************************************************************/
hdlc_decode(char * src,size_t src_size,char ** dst)2459 size_t hdlc_decode(char *src, size_t src_size, char **dst)
2460 {
2461 	if(!src || !dst || src_size < 1) return 0;
2462 
2463 	size_t index = 0;
2464 	int count = 0;
2465 	int buffer_size = 0;
2466 	int byte = 0;
2467 	int last_byte = 0;
2468 	int check_byte = 0;
2469 	char *buffer = (char *)0;
2470 
2471 	buffer_size = src_size + BUFFER_PADDING;
2472 	buffer = new char[buffer_size];
2473 
2474 	if(!buffer) {
2475 		LOG_DEBUG("Memory allocation error near line %d", __LINE__);
2476 		*dst = (char *)0;
2477 		return 0;
2478 	}
2479 
2480 	memset(buffer, 0, buffer_size);
2481 	count = 0;
2482 	last_byte = KISS_INVALID;
2483 
2484 	for(index = 0; index < src_size; index++) {
2485 
2486 		byte = src[index] & 0xFF;
2487 
2488 		if(last_byte == HDLC_CNT) {
2489 			check_byte = byte - HDLC_CNT_OFFSET;
2490 			if((check_byte > -1) && (check_byte < 256) && not_allowed[check_byte]) {
2491 				buffer[count++] = check_byte;
2492 				last_byte = byte;
2493 				continue;
2494 			}
2495 
2496 			check_byte = byte + HDLC_CNT_OFFSET;
2497 			if((check_byte > -1) && (check_byte < 256) && not_allowed[check_byte]) {
2498 				buffer[count++] = check_byte;
2499 			}
2500 
2501 			last_byte = byte;
2502 			continue;
2503 		}
2504 
2505 		switch(byte) {
2506 			case KISS_FEND:
2507 				continue;
2508 
2509 			case KISS_FESC:
2510 			case HDLC_CNT:
2511 				last_byte = byte;
2512 				continue;
2513 
2514 			case KISS_TFEND:
2515 				if(last_byte == KISS_FESC)
2516 					byte = KISS_FEND;
2517 				break;
2518 
2519 			case KISS_TFESC:
2520 				if(last_byte == KISS_FESC)
2521 					byte = KISS_FESC;
2522 				break;
2523 
2524 			case HDLC_TCNT:
2525 				if(last_byte == KISS_FESC)
2526 					byte = HDLC_CNT;
2527 				break;
2528 		}
2529 
2530 		last_byte = buffer[count++] = byte;
2531 	}
2532 
2533 	*dst = (char *) buffer;
2534 	return count;
2535 
2536 }
2537 
2538 /**********************************************************************************
2539  *  Buffer must be at least twice the size of the data provided + BUFFER_PADDING
2540  *  data_count: Number of bytes in the buffer to be converted.
2541  *  Return is the converted byte count. Buffer is overwritten with converted data.
2542  **********************************************************************************/
encap_hdlc_frame(char * buffer,size_t data_count)2543 static size_t encap_hdlc_frame(char *buffer, size_t data_count)
2544 {
2545 	if(!buffer || !data_count) {
2546 		LOG_DEBUG("%s", "Parameter Data Error [NULL]");
2547 		return false;
2548 	}
2549 
2550 	size_t count = 0;
2551 	unsigned int crc_value = 0;
2552 	char *kiss_encap = (char *)0;
2553 
2554 	if(progdefaults.ax25_decode_enabled) {
2555 		ax25_decode((unsigned char *) buffer, data_count, true, true);
2556 	}
2557 
2558 	crc_value = calc_fcs_crc(buffer, (int) data_count);
2559 
2560 	buffer[data_count++] = CRC_LOW(crc_value);
2561 	buffer[data_count++] = CRC_HIGH(crc_value);
2562 
2563 	count = hdlc_encode(buffer, data_count, &kiss_encap);
2564 
2565 	if(kiss_encap && count) {
2566 		memcpy(buffer, kiss_encap, count);
2567 #ifdef EXTENED_DEBUG_INFO
2568 		LOG_HEX(buffer, count);
2569 #endif
2570 		delete [] kiss_encap;
2571 	} else {
2572 		LOG_DEBUG("%s", "Kiss Encode Memory Allocation Error");
2573 		return 0;
2574 	}
2575 
2576 	return count;
2577 }
2578 
2579 /*********************************************************************************
2580  * Buffer is presently larger then what will be returned.
2581  * data_count: Number of bytes in the buffer to process.
2582  * Returns the converted byte count. Buffer is over written with converted data.
2583  *********************************************************************************/
decap_hdlc_frame(char * buffer,size_t data_count)2584 static size_t decap_hdlc_frame(char *buffer, size_t data_count)
2585 {
2586 	if(!buffer || !data_count) {
2587 		LOG_DEBUG("%s", "Parameter Data Error/NULL");
2588 		return false;
2589 	}
2590 
2591 	size_t count = 0;
2592 	//	size_t index = 0;
2593 	unsigned int crc_value = 0;
2594 	unsigned int calc_crc_value = 0;
2595 	char *kiss_decap = (char *)0;
2596 
2597 	count = hdlc_decode(buffer, data_count, &kiss_decap);
2598 
2599 #ifdef EXTENED_DEBUG_INFO
2600 	if(data_count && buffer)
2601 		LOG_HEX(buffer, data_count);
2602 
2603 	if(count && kiss_decap)
2604 		LOG_HEX(kiss_decap, count);
2605 #endif
2606 
2607 	do  {
2608 
2609 		if(count > data_count || !kiss_decap) {
2610 			LOG_DEBUG("%s", "Kiss decode error");
2611 			count = 0;
2612 			break;
2613 		}
2614 
2615 		if(count > 2)
2616 			count -= 2;
2617 
2618 		if(count) {
2619 			calc_crc_value = calc_fcs_crc(kiss_decap, (int) count);
2620 		}
2621 		else {
2622 			LOG_DEBUG("%s", "Kiss decode error");
2623 			count = 0;
2624 			break;
2625 		}
2626 
2627 		crc_value = CRC_LOW_HIGH(kiss_decap[count], kiss_decap[count + 1]);
2628 
2629 		if(crc_value != calc_crc_value) {
2630 			count = 0;
2631 			break;
2632 		}
2633 
2634 		temp_disable_tx_inhibit = time(0) + DISABLE_TX_INHIBIT_DURATION; // valid packet, disable busy channel inhitbit for x duration.
2635 
2636 		kiss_decap[count] = kiss_decap[count + 1] = 0;
2637 		memcpy(buffer, kiss_decap, count);
2638 
2639 		if(progdefaults.ax25_decode_enabled) {
2640 			ax25_decode((unsigned char *) buffer, count, true, false);
2641 		}
2642 
2643 		break;
2644 	} while(1);
2645 
2646 	if(kiss_decap) {
2647 		kiss_decap[0] = 0;
2648 		delete [] kiss_decap;
2649 	}
2650 
2651 	return count;
2652 }
2653 
2654 
2655 /**********************************************************************************
2656  *
2657  **********************************************************************************/
encap_kiss_frame(char * buffer,size_t buffer_size,int frame_type,int port)2658 static KISS_QUEUE_FRAME *encap_kiss_frame(char *buffer, size_t buffer_size, int frame_type, int port)
2659 {
2660 
2661 	guard_lock kfenc(&kiss_encode_mutex);
2662 
2663 	if(!buffer || buffer_size < 1) {
2664 		LOG_DEBUG("%s", "KISS encap argument 'data' contains no data");
2665 		return (KISS_QUEUE_FRAME *)0;
2666 	}
2667 
2668 	if(port > 0xF || port < 0) {
2669 		LOG_DEBUG("Invalid KISS port number (%d)", port);
2670 		return (KISS_QUEUE_FRAME *)0;
2671 	}
2672 
2673 	switch(frame_type) {
2674 		case KISS_DATA:
2675 		case KISS_RAW:
2676 		case KISS_TXDELAY:
2677 		case KISS_PERSIST:
2678 		case KISS_SLOTTIME:
2679 		case KISS_TXTAIL:
2680 		case KISS_DUPLEX:
2681 		case KISS_HARDWARE:
2682 			break;
2683 
2684 		default:
2685 			LOG_DEBUG("Invalid KISS frame type (%d)", frame_type);
2686 			return (KISS_QUEUE_FRAME *)0;
2687 	}
2688 
2689 	int size = 0;
2690 	int index = 0;
2691 	unsigned int crc_value = 0;
2692 	KISS_QUEUE_FRAME *frame = (KISS_QUEUE_FRAME *)0;
2693 
2694 	frame = new KISS_QUEUE_FRAME;
2695 
2696 	if(!frame) {
2697 		LOG_DEBUG("%s", "KISS struct frame memory allocation error");
2698 		return (KISS_QUEUE_FRAME *)0;
2699 	}
2700 
2701 	size = (buffer_size * KISS_BUFFER_FACTOR) + BUFFER_PADDING; // Resulting data space could be 2 fold higher.
2702 	frame->data = (char *) new char[size];
2703 
2704 	if(!frame->data) {
2705 		delete frame;
2706 		LOG_DEBUG("%s", "KISS buffer frame memory allocation error");
2707 		return (KISS_QUEUE_FRAME *)0;
2708 	}
2709 
2710 	memset(frame->data, 0, size);
2711 	size = buffer_size;
2712 
2713 	frame->data[0] = SET_KISS_TYPE_PORT(frame_type, port);
2714 	memcpy(&frame->data[1], buffer, size);
2715 
2716 	size++;
2717 
2718 	if((frame_type == KISS_DATA) || (frame_type == KISS_RAW)) {
2719 
2720 		if(smack_crc_enabled) {
2721 
2722 			frame->data[0] = SMACK_CRC_ASSIGN(frame->data[0]);
2723 
2724 			switch(crc_mode) {
2725 				case CRC16_CCITT:
2726 					crc_value = calc_ccitt_crc((char *) frame->data, size);
2727 					frame->data[size++] = CRC_LOW(crc_value);
2728 					frame->data[size++] = CRC_HIGH(crc_value);
2729 					break;
2730 
2731 				case CRC16_FCS:
2732 					crc_value = calc_fcs_crc((char *) frame->data, size);
2733 					frame->data[size++] = CRC_LOW(crc_value);
2734 					frame->data[size++] = CRC_HIGH(crc_value);
2735 					break;
2736 
2737 				case CRC8_XOR:
2738 					crc_value = calc_xor_crc((char *) frame->data, size);
2739 					frame->data[size++] = CRC_LOW(crc_value);
2740 					break;
2741 
2742 				default:
2743 					break;
2744 			}
2745 		}
2746 	}
2747 
2748 	char *tmp = (char *)0;
2749 
2750 	index = kiss_encode((char *) frame->data, size, &tmp);
2751 
2752 	if(tmp) {
2753 
2754 #ifdef EXTENED_DEBUG_INFO
2755 		LOG_HEX(tmp, index);
2756 #endif
2757 
2758 		frame->data[0] = 0;
2759 		delete [] frame->data;
2760 		frame->data = (char *) tmp;
2761 		frame->size = index;
2762 	} else {
2763 		LOG_DEBUG("KISS encode allocation error near line %d", __LINE__);
2764 		delete [] frame->data;
2765 		delete frame;
2766 		frame = (KISS_QUEUE_FRAME *)0;
2767 	}
2768 
2769 	return frame;
2770 }
2771 
2772 /**********************************************************************************
2773  *
2774  **********************************************************************************/
encap_kiss_frame(std::string data,int frame_type,int port)2775 static KISS_QUEUE_FRAME * encap_kiss_frame(std::string data, int frame_type, int port)
2776 {
2777 	if(data.empty()) return (KISS_QUEUE_FRAME *)0;
2778 	return encap_kiss_frame((char *) data.c_str(), (size_t) data.size(), frame_type, port);
2779 }
2780 
2781 /**********************************************************************************
2782  *
2783  **********************************************************************************/
unencap_kiss_frame(char * buffer,size_t buffer_size,int * frame_type,int * kiss_port_no)2784 std::string unencap_kiss_frame(char *buffer, size_t buffer_size, int *frame_type, int *kiss_port_no)
2785 {
2786 	if(!buffer || buffer_size < 1 || !frame_type || !kiss_port_no)
2787 		return std::string("");
2788 
2789 	char *decoded_buffer = (char *)0;
2790 	size_t count = 0;
2791 	unsigned int crc_extracted = 0;
2792 	unsigned int crc_calc = 0;
2793 	unsigned int port = 0;
2794 	unsigned int ftype = 0;
2795 
2796 	static std::string ret_str = "";
2797 
2798 	ret_str.clear();
2799 
2800 #ifdef EXTENED_DEBUG_INFO
2801 	LOG_HEX(buffer, buffer_size);
2802 #endif
2803 
2804 	count = kiss_decode(buffer, buffer_size, &decoded_buffer);
2805 
2806 	if(!count || !decoded_buffer) {
2807 		LOG_DEBUG("Kiss decoder memory allocation error near line %d", __LINE__);
2808 		return ret_str;
2809 	}
2810 
2811 	ftype = KISS_CMD(decoded_buffer[0]);
2812 	port = KISS_PORT(decoded_buffer[0]);
2813 
2814 	if((ftype == KISS_DATA) || (ftype == KISS_RAW)) {
2815 		smack_crc_enabled = SMACK_CRC(port);
2816 		port = SMACK_CRC_MASK(port);
2817 
2818 		if(smack_crc_enabled) {
2819 			switch(crc_mode) {
2820 				case CRC16_CCITT:
2821 					count -= 2;
2822 					if(count > 2) {
2823 						crc_calc = calc_ccitt_crc(decoded_buffer, count);
2824 						crc_extracted = CRC_LOW_HIGH(decoded_buffer[count], decoded_buffer[count + 1]);
2825 					} else {
2826 						crc_calc = crc_extracted + 1; // Force a fail
2827 					}
2828 					break;
2829 
2830 				case CRC16_FCS:
2831 					count -= 2;
2832 					if(count > 2) {
2833 						crc_calc = calc_fcs_crc(decoded_buffer, count);
2834 						crc_extracted = CRC_LOW_HIGH(decoded_buffer[count], decoded_buffer[count + 1]);
2835 					} else {
2836 						crc_calc = crc_extracted + 1;
2837 					}
2838 					break;
2839 
2840 				case CRC8_XOR:
2841 					count -= 1;
2842 					if(count > 1) {
2843 						crc_calc = CRC_LOW(calc_fcs_crc(decoded_buffer, count));
2844 						crc_extracted = CRC_LOW(decoded_buffer[count]);
2845 					} else {
2846 						crc_calc = crc_extracted + 1;
2847 					}
2848 					break;
2849 
2850 				default:
2851 					LOG_DEBUG("CRC type not found %d", crc_mode);
2852 			}
2853 
2854 			if(crc_calc != crc_extracted) {
2855 
2856 				if(frame_type) *frame_type = ftype;
2857 				if(kiss_port_no) *kiss_port_no = port;
2858 				if(decoded_buffer) delete [] decoded_buffer;
2859 
2860 				ret_str.clear();
2861 				return ret_str;
2862 			}
2863 		}
2864 	}
2865 
2866 	if(count > 0)
2867 		count--;
2868 
2869 #ifdef EXTENED_DEBUG_INFO
2870 	LOG_HEX(&decoded_buffer[1], count);
2871 #endif
2872 
2873 	ret_str.assign(&decoded_buffer[1], count);
2874 
2875 	if(frame_type) *frame_type = ftype;
2876 	if(kiss_port_no) *kiss_port_no = port;
2877 	if(decoded_buffer) delete [] decoded_buffer;
2878 
2879 	return ret_str;
2880 }
2881 
2882 /**********************************************************************************
2883  *
2884  **********************************************************************************/
unencap_kiss_frame(std::string package,int * frame_type,int * kiss_port_no)2885 std::string unencap_kiss_frame(std::string package, int *frame_type, int *kiss_port_no)
2886 {
2887 	if(package.empty() || !frame_type || !kiss_port_no)
2888 		return std::string("");
2889 
2890 	return unencap_kiss_frame((char *) package.c_str(), (size_t) package.size(), frame_type, kiss_port_no);
2891 }
2892 
2893 /**********************************************************************************
2894  *
2895  **********************************************************************************/
parse_hardware_frame(std::string frame)2896 static void parse_hardware_frame(std::string frame)
2897 {
2898 	if(frame.empty()) return;
2899 
2900 	string cmd = "";
2901 	string arg = "";
2902 	static char buffer[512];
2903 	string parse_frame = "";
2904 	char bofmsg[] = "Temp Buffer overflow";
2905 	size_t count = frame.size();
2906 	size_t index = 0;
2907 	size_t pos = 0;
2908 	size_t j = 0;
2909 
2910 	parse_frame.assign(frame);
2911 
2912 #ifdef EXTENED_DEBUG_INFO
2913 	LOG_HEX(frame.c_str(), frame.size());
2914 #endif
2915 
2916 	do {
2917 		if(kiss_reset_flag) return;
2918 
2919 		pos = parse_frame.find(":");
2920 
2921 		if(pos == string::npos) return;
2922 
2923 		j = 0;
2924 		memset(buffer, 0, sizeof(buffer));
2925 		for(index = 0; index < pos; index++) {
2926 			if(parse_frame[index] <= ' ') continue;
2927 			buffer[j++] = toupper(parse_frame[index]);
2928 			if(j >= sizeof(buffer)) {
2929 				LOG_DEBUG("%s", bofmsg);
2930 				return;
2931 			}
2932 		}
2933 		cmd.assign(buffer);
2934 
2935 		j = 0;
2936 		memset(buffer, 0, sizeof(buffer));
2937 		for(index = pos + 1; index < count; index++) {
2938 			if(parse_frame[index] <= ' ') break;
2939 			buffer[j++] = parse_frame[index];
2940 			if(j >= sizeof(buffer)) {
2941 				LOG_DEBUG("%s", bofmsg);
2942 				return;
2943 			}
2944 		}
2945 		arg.assign(buffer);
2946 
2947 		if(cmd.empty()) return;
2948 
2949 		exec_hardware_command(cmd, arg);
2950 
2951 		if(index > count)
2952 			index = count;
2953 
2954 		parse_frame.erase(0, index);
2955 		count = parse_frame.size();
2956 
2957 	} while(count > 0);
2958 
2959 }
2960 
2961 /**********************************************************************************
2962  *
2963  **********************************************************************************/
parse_kiss_frame(std::string frame_segment)2964 static void parse_kiss_frame(std::string frame_segment)
2965 {
2966 	guard_lock kiss_rx_lock(&kiss_frame_mutex);
2967 
2968 	unsigned int cur_byte    = KISS_INVALID;
2969 	unsigned int frame_size  = 0;
2970 	unsigned int index       = 0;
2971 	unsigned int fend_count  = 0;
2972 	unsigned int cmsa_data   = 0;
2973 	int buffer_size = 0;
2974 	int port_no     = KISS_INVALID;
2975 	int frame_type  = KISS_INVALID;
2976 	int data_count = 0;
2977 
2978 	bool process_one_frame = false;
2979 	char *buffer = (char *)0;
2980 
2981 	kiss_frame.append(frame_segment);
2982 
2983 	while(1) {
2984 
2985 		if(kiss_frame.empty()) return;
2986 
2987 		frame_size = kiss_frame.size();
2988 		process_one_frame = false;
2989 		fend_count = 0;
2990 		kiss_one_frame.clear();
2991 
2992 		for(index = 0; index < frame_size; index++) {
2993 			cur_byte = kiss_frame[index] & 0xFF;
2994 
2995 			if(cur_byte == KISS_FEND) {
2996 				fend_count++;
2997 			}
2998 
2999 			if(fend_count) {
3000 				kiss_one_frame += cur_byte;
3001 			}
3002 
3003 			if(fend_count == 2) {
3004 				kiss_frame.erase(0, index);
3005 				process_one_frame = true;
3006 				break;
3007 			}
3008 		}
3009 
3010 		if(!process_one_frame)
3011 			return;
3012 
3013 		frame_size = kiss_one_frame.size();
3014 
3015 		if(frame_size < 3) {
3016 			continue; // Invalid Frame size
3017 		}
3018 
3019 		kiss_one_frame = unencap_kiss_frame(kiss_one_frame, &frame_type, &port_no);
3020 
3021 		if(kiss_one_frame.empty())
3022 			continue;
3023 
3024 		if(port_no != (int)kiss_port_no) {
3025 			continue;
3026 		}
3027 
3028 		switch(frame_type) {
3029 			case KISS_TXDELAY:
3030 			case KISS_PERSIST:
3031 			case KISS_SLOTTIME:
3032 			case KISS_TXTAIL:
3033 			case KISS_DUPLEX:
3034 				cmsa_data = kiss_one_frame[0] & 0xFF;
3035 				break;
3036 
3037 			case KISS_DATA:
3038 				if(kiss_raw_enabled == KISS_RAW_ONLY)
3039 					continue;
3040 				break;
3041 
3042 			case KISS_RAW:
3043 				if(kiss_raw_enabled == KISS_RAW_DISABLED)
3044 					continue;
3045 				break;
3046 
3047 			case KISS_HARDWARE:
3048 				break;
3049 
3050 			default:
3051 				continue; // Unreconized frame_type.
3052 
3053 		}
3054 
3055 		switch(frame_type) {
3056 			case KISS_DATA:
3057 				buffer_size = (frame_size * HDLC_BUFFER_FACTOR) + BUFFER_PADDING;
3058 				buffer = new char[buffer_size];
3059 
3060 				if(!buffer) {
3061 					LOG_DEBUG("%s", "Buffer Allocation Error");
3062 					return;
3063 				}
3064 				data_count = kiss_one_frame.size();
3065 				memset(buffer, 0, buffer_size);
3066 				memcpy(buffer, kiss_one_frame.c_str(), data_count);
3067 
3068 				data_count = encap_hdlc_frame(buffer, data_count);
3069 
3070 				WriteToRadioBuffered((const char *) buffer, (size_t) data_count);
3071 
3072 				buffer[0] = 0;
3073 				delete [] buffer;
3074 				buffer = 0;
3075 
3076 				break;
3077 
3078 			case KISS_RAW:
3079 				WriteToRadioBuffered((const char *) kiss_one_frame.c_str(), (size_t) kiss_one_frame.size());
3080 				break;
3081 
3082 			case KISS_TXDELAY:
3083 				progStatus.csma_transmit_delay   = cmsa_data;
3084 				progdefaults.csma_transmit_delay = cmsa_data;
3085 				REQ(update_csma_io_config, (int) CSMA_TX_DELAY);
3086 				break;
3087 
3088 			case KISS_PERSIST:
3089 				progStatus.csma_persistance   = cmsa_data;
3090 				progdefaults.csma_persistance = cmsa_data;
3091 				REQ(update_csma_io_config, (int) CSMA_PERSISTANCE);
3092 				break;
3093 
3094 			case KISS_SLOTTIME:
3095 				progStatus.csma_slot_time   = cmsa_data;
3096 				progdefaults.csma_slot_time = cmsa_data;
3097 				REQ(update_csma_io_config, (int) CSMA_SLOT_TIME);
3098 				break;
3099 
3100 			case KISS_TXTAIL:
3101 				break;
3102 
3103 			case KISS_DUPLEX:
3104 				if(cmsa_data)
3105 					duplex = KISS_FULL_DUPLEX;
3106 				else
3107 					duplex = KISS_HALF_DUPLEX;
3108 				break;
3109 
3110 			case KISS_HARDWARE:
3111 				parse_hardware_frame(kiss_one_frame);
3112 				break;
3113 		}
3114 	} // while(1)
3115 }
3116 
3117 /**********************************************************************************
3118  *
3119  **********************************************************************************/
WriteToHostBuffered(const char * data,size_t size)3120 static void WriteToHostBuffered(const char *data, size_t size)
3121 {
3122 	guard_lock to_host_lock(&to_host_mutex);
3123 	to_host.append(data, size);
3124 }
3125 
3126 /**********************************************************************************
3127  *
3128  **********************************************************************************/
WriteToRadioBuffered(const char * data,size_t size)3129 static void WriteToRadioBuffered(const char *data, size_t size)
3130 {
3131 	guard_lock to_radio_lock(&to_radio_mutex);
3132 	if(!data || size < 1) return;
3133 	set_tx_timeout();
3134 	to_radio.append(data, size);
3135 }
3136 
3137 /**********************************************************************************
3138  * Must be call in WriteToRadioBuffered() and no other.
3139  **********************************************************************************/
set_tx_timeout(void)3140 inline void set_tx_timeout(void)
3141 {
3142 	if(to_radio.empty()) {
3143 		transmit_buffer_flush_timeout = time(0) + TX_BUFFER_TIMEOUT;
3144 	}
3145 }
3146 
3147 /**********************************************************************************
3148  *
3149  **********************************************************************************/
flush_kiss_tx_buffer(void)3150 void flush_kiss_tx_buffer(void)
3151 {
3152 	int data_count = 0;
3153 
3154 	{
3155 		guard_lock to_host_lock(&to_radio_mutex);
3156 		kiss_text_available = false;
3157 		pText = 0;
3158 		data_count = to_radio.size();
3159 
3160 		if(data_count)
3161 			to_radio.clear();
3162 	}
3163 
3164 	if(data_count)
3165 		bcast_tx_buffer_empty_kiss_frame();
3166 }
3167 
3168 /**********************************************************************************
3169  *
3170  **********************************************************************************/
WriteToHostARQBuffered(void)3171 static void WriteToHostARQBuffered(void)
3172 {
3173 	std::string arq_data = "";
3174 
3175 	{
3176 		guard_lock to_host_arq_lock(&to_host_arq_mutex);
3177 		int data_available = to_arq_host.size();
3178 
3179 		if(kiss_raw_enabled == KISS_RAW_DISABLED) {
3180 			if(data_available) {
3181 				to_arq_host.clear();
3182 			}
3183 			return;
3184 		}
3185 
3186 		if(data_available < 1) return;
3187 
3188 #ifdef EXTENED_DEBUG_INFO
3189 		LOG_HEX(to_arq_host.c_str(), to_arq_host.size());
3190 #endif
3191 
3192 		arq_data.assign(to_arq_host);
3193 		to_arq_host.clear();
3194 	}
3195 
3196 	kiss_queue_frame(encap_kiss_frame(arq_data, KISS_RAW, kiss_port_no), string("ARQ"));
3197 
3198 }
3199 
3200 /**********************************************************************************
3201  *
3202  **********************************************************************************/
ReadFromHostSocket(void * args)3203 static void *ReadFromHostSocket(void *args)
3204 {
3205 	if(!kiss_socket) return (void *)0;
3206 
3207 	static char buffer[2048];
3208 	string str_buffer;
3209 	size_t count = 0;
3210 	Socket *tmp_socket = (Socket *)0;
3211 	memset(buffer, 0, sizeof(buffer));
3212 	str_buffer.reserve(sizeof(buffer));
3213 
3214 	if(progStatus.kiss_tcp_io && progStatus.kiss_tcp_listen) {
3215 		tmp_socket = kiss_socket->accept2();
3216 		kiss_socket->shut_down();
3217 		kiss_socket->close();
3218 
3219 		if(tmp_socket)
3220 			kiss_socket = tmp_socket;
3221 		tmp_socket = 0;
3222 	}
3223 
3224 	LOG_INFO("%s", "Kiss RX loop started. ");
3225 	kiss_rx_exit = false;
3226 	kiss_rx_loop_running = true;
3227 
3228 	while(!kiss_rx_exit) {
3229 
3230 		memset(buffer, 0, sizeof(buffer));
3231 
3232 		try {
3233 			if(progStatus.kiss_tcp_io)
3234 				count = kiss_socket->recv((void *) buffer, sizeof(buffer) - 1);
3235 			else
3236 				count = kiss_socket->recvFrom((void *) buffer, sizeof(buffer) - 1);
3237 		} catch (...) {
3238 			if (errno)
3239 				LOG_INFO("recv/recvFrom Socket Error %d", errno);
3240 			count = 0;
3241 
3242 			if(!tcpip_reset_flag) {
3243 				kiss_tcp_disconnect((char *)"");
3244 			}
3245 			break;
3246 		}
3247 
3248 		if(count && (data_io_enabled == KISS_IO)) {
3249 #ifdef EXTENED_DEBUG_INFO
3250 			LOG_HEX(buffer, count);
3251 #endif
3252 			guard_lock from_host_lock(&from_host_mutex);
3253 			from_host.append(buffer, count);
3254 		}
3255 	}
3256 
3257 	LOG_INFO("%s", "Kiss RX loop exit. ");
3258 
3259 	kiss_rx_loop_running = false;
3260 	return (void *)0;
3261 }
3262 
3263 extern Fl_Slider2 *sldrSquelch;
3264 extern Progress	*pgrsSquelch;
3265 
3266 /**********************************************************************************
3267  *
3268  **********************************************************************************/
kiss_loop(void * args)3269 static void *kiss_loop(void *args)
3270 {
3271 	SET_THREAD_ID(KISS_TID);
3272 
3273 	int old_trx_state = STATE_TX;
3274 
3275 	LOG_INFO("%s", "Kiss loop started. ");
3276 
3277 	kiss_loop_running = true;
3278 
3279 	while(!kiss_exit){
3280 		MilliSleep(100);
3281 
3282 		if(data_io_enabled != KISS_IO) {
3283 			kiss_text_available = false;
3284 			kiss_reset_buffers();
3285 			continue;
3286 		}
3287 
3288 		if(old_trx_state != trx_state) {
3289 			if(kiss_bcast_trx_toggle) {
3290 				switch(trx_state) {
3291 					case STATE_TX:
3292 					case STATE_RX:
3293 					case STATE_TUNE:
3294 						bcast_trxs_kiss_frame(trx_state);
3295 					default :
3296 						break;
3297 				}
3298 			}
3299 
3300 			old_trx_state = trx_state;
3301 		}
3302 
3303 		ReadFromHostBuffered();
3304 		ReadFromRadioBuffered();
3305 		WriteToHostBCastFramesBuffered();
3306 		WriteToHostARQBuffered();
3307 		WriteToHostSocket();
3308 
3309 		if(!to_radio.empty()) {
3310 			kiss_text_available = true;
3311 			active_modem->set_stopflag(false);
3312 			trx_transmit();
3313 		}
3314 	}
3315 
3316 	kiss_loop_running = false;
3317 
3318 	// exit the kiss thread
3319 	return NULL;
3320 }
3321 
3322 
3323 /**********************************************************************************
3324  *
3325  **********************************************************************************/
WriteKISS(const char data)3326 void WriteKISS(const char data)
3327 {
3328 	if (active_modem->get_mode() == MODE_FSQ) return;
3329 
3330 	if(kiss_reset_flag) return;
3331 
3332 	{
3333 		guard_lock from_radio_lock(&from_radio_mutex);
3334 		from_radio += data;
3335 	}
3336 
3337 	if(kiss_raw_enabled != KISS_RAW_DISABLED) {
3338 		guard_lock to_host_arq_lock(&to_host_arq_mutex);
3339 		to_arq_host += data;
3340 	}
3341 }
3342 
3343 /**********************************************************************************
3344  *
3345  **********************************************************************************/
WriteKISS(const char * data)3346 void WriteKISS(const char *data)
3347 {
3348 	if (active_modem->get_mode() == MODE_FSQ) return;
3349 
3350 	if(kiss_reset_flag) return;
3351 
3352 	{
3353 		guard_lock from_radio_lock(&from_radio_mutex);
3354 		if(data)
3355 			from_radio.append(data);
3356 	}
3357 
3358 	{
3359 		guard_lock to_host_arq_lock(&to_host_arq_mutex);
3360 		if(data && (kiss_raw_enabled != KISS_RAW_DISABLED))
3361 			to_arq_host.append(data);
3362 	}
3363 }
3364 
3365 /**********************************************************************************
3366  *
3367  **********************************************************************************/
WriteKISS(const char * data,size_t size)3368 void WriteKISS(const char *data, size_t size)
3369 {
3370 	if (active_modem->get_mode() == MODE_FSQ) return;
3371 
3372 	if(kiss_reset_flag) return;
3373 
3374 	{
3375 		guard_lock from_radio_lock(&from_radio_mutex);
3376 		if(data && size) {
3377 			from_radio.append(data, size);
3378 		}
3379 	}
3380 
3381 	{
3382 		guard_lock to_host_arq_lock(&to_host_arq_mutex);
3383 		if(data && size && (kiss_raw_enabled != KISS_RAW_DISABLED)) {
3384 			to_arq_host.append(data, size);
3385 		}
3386 	}
3387 }
3388 
3389 /**********************************************************************************
3390  *
3391  **********************************************************************************/
WriteKISS(std::string data)3392 void WriteKISS(std::string data)
3393 {
3394 	if (active_modem->get_mode() == MODE_FSQ) return;
3395 
3396 	if(kiss_reset_flag) return;
3397 
3398 	{
3399 		guard_lock from_radio_lock(&from_radio_mutex);
3400 		if(!data.empty()) {
3401 			from_radio.append(data);
3402 		}
3403 	}
3404 
3405 	{
3406 		guard_lock to_host_arq_lock(&to_host_arq_mutex);
3407 		if(!data.empty() && (kiss_raw_enabled != KISS_RAW_DISABLED)) {
3408 			to_arq_host.append(data);
3409 		}
3410 	}
3411 }
3412 
3413 /**********************************************************************************
3414  *
3415  **********************************************************************************/
WriteToHostSocket(void)3416 void WriteToHostSocket(void)
3417 {
3418 	guard_lock to_host_lock(&to_host_mutex);
3419 	size_t count = 0;
3420 
3421 	if(to_host.empty()) return;
3422 
3423 	if(kiss_socket && data_io_enabled == KISS_IO) {
3424 		try {
3425 			if(progStatus.kiss_tcp_io)
3426 				count = kiss_socket->send(to_host.c_str(), to_host.size());
3427 			else
3428 				count = kiss_socket->sendTo(to_host.c_str(), to_host.size());
3429 #ifdef EXTENED_DEBUG_INFO
3430 			LOG_HEX(to_host.c_str(), to_host.size());
3431 #endif
3432 		} catch (...) {
3433 			if(kiss_reset_flag == false) {
3434 				kiss_tcp_disconnect((char *)"");
3435 			}
3436 			LOG_INFO("Write error error to KISS socket: %d", static_cast<int>(count));
3437 		}
3438 	}
3439 
3440 	to_host.clear();
3441 }
3442 
3443 /**********************************************************************************
3444  *
3445  **********************************************************************************/
ReadFromHostBuffered(void)3446 static void ReadFromHostBuffered(void)
3447 {
3448 	if(!kiss_socket) return;
3449 
3450 	guard_lock from_host_lock(&from_host_mutex);
3451 	if(from_host.empty()) return;
3452 #ifdef EXTENED_DEBUG_INFO
3453 	LOG_HEX(from_host.c_str(), from_host.size());
3454 #endif
3455 	parse_kiss_frame(from_host);
3456 	from_host.clear();
3457 }
3458 
3459 /**********************************************************************************
3460  *
3461  **********************************************************************************/
ReadFromRadioBuffered(void)3462 void ReadFromRadioBuffered(void)
3463 {
3464 	if(kiss_reset_flag) return;
3465 
3466 	guard_lock from_radio_lock(&from_radio_mutex);
3467 	if(from_radio.empty()) return;
3468 
3469 	int pos = 0;
3470 	int pos2 = 0;
3471 	//	unsigned int crc = 0;
3472 	KISS_QUEUE_FRAME *frame = (KISS_QUEUE_FRAME *)0;
3473 	static char frame_marker[2] = { (char)(KISS_FEND), 0 };
3474 	std::string one_frame = "";
3475 
3476 	pos = from_radio.find(frame_marker);
3477 
3478 	if(pos == (int)(std::string::npos)) {
3479 		from_radio.clear();
3480 		return;
3481 	}
3482 
3483 	if(pos != 0) {
3484 		from_radio.erase(0, pos);
3485 		pos = 0;
3486 	}
3487 
3488 	pos2 = from_radio.find(frame_marker, pos + 1);
3489 	if(pos2 != (int)(std::string::npos)) {
3490 		one_frame.assign(from_radio, pos, pos2 - pos + 1);
3491 	} else {
3492 		if(from_radio.size() > MAX_TEMP_BUFFER_SIZE)
3493 			from_radio.clear();
3494 		return;
3495 	}
3496 
3497 	char *buffer = (char *)0;
3498 	size_t buffer_size = one_frame.size() + BUFFER_PADDING;
3499 
3500 	buffer = new char [buffer_size];
3501 
3502 	if(!buffer) {
3503 		LOG_DEBUG("Memory Allocation Error Near Line No. %d", __LINE__);
3504 		goto EXIT;
3505 	}
3506 
3507 	memset(buffer, 0, buffer_size);
3508 
3509 	buffer_size = one_frame.size();
3510 	memcpy(buffer, one_frame.c_str(), buffer_size);
3511 
3512 #ifdef EXTENED_DEBUG_INFO
3513 	LOG_HEX(buffer, buffer_size);
3514 #endif
3515 
3516 	buffer_size = decap_hdlc_frame(buffer, buffer_size);
3517 
3518 	if(buffer_size) {
3519 		from_radio.erase(pos, pos2 - pos + 1);
3520 
3521 		if(kiss_raw_enabled != KISS_RAW_ONLY) {
3522 			frame = encap_kiss_frame(buffer, buffer_size, KISS_DATA, kiss_port_no);
3523 
3524 			if(!frame || !frame->data) {
3525 				LOG_DEBUG("Frame Allocation Error Near Line %d", __LINE__);
3526 				goto EXIT;
3527 			}
3528 
3529 			WriteToHostBuffered((const char *) frame->data, (size_t) frame->size);
3530 		}
3531 	} else {
3532 		from_radio.erase(pos, pos + 1);
3533 	}
3534 
3535 EXIT:;
3536 
3537 	if(frame) {
3538 		if(frame->data) {
3539 			frame->data[0] = 0;
3540 			delete [] frame->data;
3541 		}
3542 		delete frame;
3543 	}
3544 
3545 	if(buffer) {
3546 		buffer[0] = 0;
3547 		delete [] buffer;
3548 	}
3549 }
3550 
3551 /**********************************************************************************
3552  *
3553  **********************************************************************************/
WriteToHostBCastFramesBuffered(void)3554 void WriteToHostBCastFramesBuffered(void)
3555 {
3556 	guard_lock kiss_bc_frame_lock(&kiss_bc_frame_mutex);
3557 	if(kiss_bc_frame.empty()) return;
3558 	WriteToHostBuffered((const char *) kiss_bc_frame.c_str(), (size_t) kiss_bc_frame.size());
3559 
3560 #ifdef EXTENED_DEBUG_INFO
3561 	LOG_HEX(kiss_bc_frame.c_str(), (size_t) kiss_bc_frame.size());
3562 #endif
3563 
3564 	kiss_bc_frame.clear();
3565 }
3566 
3567 /**********************************************************************************
3568  *
3569  **********************************************************************************/
tcp_init(bool connect_flag)3570 bool tcp_init(bool connect_flag)
3571 {
3572 	if(progdefaults.kiss_address.empty() || progdefaults.kiss_io_port.empty()) {
3573 		LOG_DEBUG("%s", "KISS IP Address or Port null");
3574 		return false;
3575 	}
3576 
3577 	kiss_ip_address.assign(progdefaults.kiss_address);
3578 	kiss_ip_io_port.assign(progdefaults.kiss_io_port);
3579 	kiss_ip_out_port.assign(progdefaults.kiss_out_port);
3580 
3581 	try {
3582 		kiss_socket = new Socket(Address(kiss_ip_address.c_str(), kiss_ip_io_port.c_str(), "tcp"));
3583 		kiss_socket->set_autoclose(true);
3584 		kiss_socket->set_nonblocking(false);
3585 
3586 		if(progdefaults.kiss_tcp_listen)
3587 			kiss_socket->bind();
3588 	}
3589 	catch (const SocketException& e) {
3590 		LOG_ERROR("Could not resolve %s: %s", kiss_ip_address.c_str(), e.what());
3591 		if(kiss_socket) {
3592 			kiss_socket->shut_down();
3593 			kiss_socket->close();
3594 			delete kiss_socket;
3595 			kiss_socket = 0;
3596 			kiss_enabled = 0;
3597 		}
3598 		return false;
3599 	}
3600 
3601 	if(connect_flag) {
3602 		if(kiss_socket->connect1() == false) {
3603 			LOG_INFO("Connection Failed: Host program present?");
3604 			kiss_socket->shut_down();
3605 			kiss_socket->close();
3606 			delete kiss_socket;
3607 			kiss_socket = 0;
3608 			kiss_enabled = 0;
3609 			return false;
3610 		}
3611 	}
3612 
3613 	return true;
3614 }
3615 
3616 /**********************************************************************************
3617  *
3618  **********************************************************************************/
udp_init(void)3619 bool udp_init(void)
3620 {
3621 	if(progdefaults.kiss_address.empty() || progdefaults.kiss_io_port.empty()) {
3622 		LOG_DEBUG("%s", "KISS IP Address or Port null");
3623 		return false;
3624 	}
3625 
3626 	kiss_ip_address.assign(progdefaults.kiss_address);
3627 	kiss_ip_io_port.assign(progdefaults.kiss_io_port);
3628 	kiss_ip_out_port.assign(progdefaults.kiss_out_port);
3629 
3630 	try {
3631 		kiss_socket = new Socket(Address(kiss_ip_address.c_str(), kiss_ip_io_port.c_str(), "udp"));
3632 		kiss_socket->dual_port(&progdefaults.kiss_dual_port_enabled);
3633 		kiss_socket->set_dual_port_number(kiss_ip_out_port);
3634 		kiss_socket->set_autoclose(true);
3635 		kiss_socket->set_nonblocking(false);
3636 
3637 		if(progdefaults.kiss_tcp_listen) // Listen flag indcates server mode.
3638 			kiss_socket->bindUDP();
3639 
3640 	} catch (const SocketException& e) {
3641 		LOG_ERROR("Could not resolve %s: %s", kiss_ip_address.c_str(), e.what());
3642 		if(kiss_socket) {
3643 			kiss_socket->shut_down();
3644 			kiss_socket->close();
3645 			delete kiss_socket;
3646 			kiss_socket = 0;
3647 			kiss_enabled = 0;
3648 		}
3649 		return false;
3650 	}
3651 
3652 	return true;
3653 }
3654 
3655 /**********************************************************************************
3656  *
3657  **********************************************************************************/
kiss_reset_buffers(void)3658 void kiss_reset_buffers(void)
3659 {
3660 	{
3661 		guard_lock to_host_lock(&to_host_mutex);
3662 		if(!to_host.empty())
3663 			to_host.clear();
3664 	}
3665 
3666 	{
3667 		guard_lock to_host_lock(&from_radio_mutex);
3668 		if(!from_radio.empty())
3669 			from_radio.clear();
3670 	}
3671 
3672 	{
3673 		guard_lock to_host_lock(&to_radio_mutex);
3674 		pText = 0;
3675 		kiss_text_available = false;
3676 		if(!to_radio.empty())
3677 			to_radio.clear();
3678 	}
3679 
3680 	{
3681 		guard_lock kiss_bc_frame_lock(&kiss_bc_frame_mutex);
3682 		if(!kiss_bc_frame.empty())
3683 			kiss_bc_frame.clear();
3684 	}
3685 }
3686 
3687 /**********************************************************************************
3688  *
3689  **********************************************************************************/
kiss_reset(void)3690 void kiss_reset(void)
3691 {
3692 	kiss_reset_flag     = true;
3693 	kiss_text_available = false;
3694 	duplex              = KISS_HALF_DUPLEX;
3695 	crc_mode            = CRC16_NONE;
3696 	smack_crc_enabled   = false;
3697 	pText = 0;
3698 
3699 	if(data_io_enabled == KISS_IO)
3700 		data_io_enabled = DISABLED_IO;
3701 
3702 	MilliSleep(1000);
3703 
3704 	kiss_reset_buffers();
3705 
3706 	if (trx_state == STATE_TX || trx_state == STATE_TUNE) {
3707 		REQ(abort_tx);
3708 	}
3709 
3710 	kiss_reset_flag = false;
3711 
3712 	if(data_io_enabled == DISABLED_IO)
3713 		data_io_enabled = KISS_IO;
3714 }
3715 
3716 /**********************************************************************************
3717  *
3718  **********************************************************************************/
kiss_init(bool connect_flag)3719 void kiss_init(bool connect_flag)
3720 {
3721 	kiss_enabled     = false;
3722 	kiss_exit        = false;
3723 	tcpip_reset_flag = false;
3724 
3725 	// progStatus.data_io_enabled (widget state), data_io_enabled (program state)
3726 
3727 	if(progStatus.data_io_enabled == KISS_IO) {
3728 		if(!(active_modem->iface_io() & KISS_IO)) {
3729 			set_default_kiss_modem();
3730 		}
3731 	}
3732 
3733 	if(init_hist_flag) {
3734 		memset(histogram, 0, sizeof(histogram));
3735 		init_hist_flag = false;
3736 	}
3737 
3738 	srand(time(0)); // For CSMA persistance
3739 	update_kpsql_fractional_gain(progdefaults.kpsql_attenuation);
3740 
3741 	data_io_type = DATA_IO_NA;
3742 
3743 	if(progStatus.kiss_tcp_io) {
3744 
3745 		if(retry_count > KISS_CONNECT_RETRY_COUNT)
3746 			retry_count = KISS_CONNECT_RETRY_COUNT;
3747 
3748 		if(progStatus.kiss_tcp_listen)
3749 			connect_flag = false;
3750 
3751 		do {
3752 			if(tcp_init(connect_flag)) break;
3753 
3754 			if(progStatus.kiss_tcp_listen) return;
3755 
3756 			MilliSleep(KISS_RETRY_WAIT_TIME);
3757 
3758 			if(retry_count-- > 0) continue;
3759 			else return;
3760 
3761 		} while(1);
3762 
3763 		LOG_INFO("%s", "TCP Init - OK");
3764 	} else {
3765 		if(!udp_init()) return;
3766 		LOG_INFO("%s", "UDP Init - OK");
3767 	}
3768 
3769 	Fl::awake(kiss_io_set_button_state, (void *) IO_START_STR);
3770 
3771 	kiss_loop_running = false;
3772 	if (pthread_create(&kiss_thread, NULL, kiss_loop, NULL) < 0) {
3773 		LOG_ERROR("KISS kiss_thread: pthread_create failed");
3774 		return;
3775 	}
3776 
3777 	kiss_rx_loop_running = false;
3778 	if (pthread_create(&kiss_rx_socket_thread, NULL, ReadFromHostSocket, NULL) < 0) {
3779 		LOG_ERROR("KISS kiss_rx_socket_thread: pthread_create failed");
3780 		kiss_exit = true;
3781 		pthread_join(kiss_thread, NULL);
3782 		return;
3783 	}
3784 
3785 	if(progStatus.kiss_tcp_io) {
3786 		data_io_type = DATA_IO_TCP;
3787 		kiss_watchdog_running = false;
3788 		if (pthread_create(&kiss_watchdog_thread, NULL, tcpip_watchdog, NULL) < 0) {
3789 			LOG_ERROR("KISS kiss_watchdog_thread: pthread_create failed");
3790 		}
3791 	} else {
3792 		data_io_type = DATA_IO_UDP;
3793 	}
3794 
3795 	Fl::awake(kiss_io_set_button_state, (void *) IO_STOP_STR);
3796 
3797 	if(progdefaults.data_io_enabled == KISS_IO)
3798 		data_io_enabled = KISS_IO;
3799 
3800 	kiss_enabled = true;
3801 	allow_kiss_socket_io = true;
3802 }
3803 
3804 /**********************************************************************************
3805  *
3806  **********************************************************************************/
tcpip_watchdog(void * args)3807 static void *tcpip_watchdog(void *args)
3808 {
3809 	kiss_watchdog_running = true;
3810 	kiss_watchdog_exit = false;
3811 	struct timespec timeout;
3812 	struct timeval    tp;
3813 	std::string package = "";
3814 	std::string cmd = "HOST:";
3815 
3816 	package.assign(cmd);
3817 
3818 	memset(&timeout, 0, sizeof(timeout));
3819 	LOG_INFO("%s", "TCP/IP watch dog started");
3820 
3821 	kiss_watchdog_running = true;
3822 
3823 	while(!kiss_watchdog_exit) {
3824 		gettimeofday(&tp, NULL);
3825 
3826 		timeout.tv_sec  = tp.tv_sec + TEST_INTERVAL_SECONDS;
3827 		timeout.tv_nsec = tp.tv_usec * 1000;
3828 
3829 		pthread_mutex_lock(&kiss_loop_exit_mutex);
3830 		pthread_cond_timedwait(&kiss_watchdog_cond, &kiss_loop_exit_mutex, &timeout);
3831 		pthread_mutex_unlock(&kiss_loop_exit_mutex);
3832 
3833 		// Send somthing every once in awhile to check if other side is still connected.
3834 		// Data transfer fail handled by the data transfer routines.
3835 		if(kiss_socket && !tcpip_reset_flag)
3836 			if(kiss_socket->is_connected())
3837 				kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
3838 	}
3839 
3840 	kiss_watchdog_running = false;
3841 	LOG_INFO("%s", "TCP/IP watch dog stopped");
3842 	return (void *)0;
3843 }
3844 
3845 /**********************************************************************************
3846  *
3847  **********************************************************************************/
kiss_main_thread_close(void * ptr)3848 void kiss_main_thread_close(void *ptr)
3849 {
3850 	kiss_close(true);
3851 }
3852 
3853 /**********************************************************************************
3854  * Only called from the main thread.
3855  **********************************************************************************/
kiss_close(bool override_flag)3856 void kiss_close(bool override_flag)
3857 {
3858 	int max_loops = 100;
3859 	int loop_delay_ms = 10;
3860 
3861 	if(tcpip_reset_flag && !override_flag) return;
3862 
3863 	if(kiss_socket) {
3864 		if(kiss_socket->is_connected()) {
3865 			kiss_reset_buffers();
3866 			send_disconnect_msg();
3867 			MilliSleep(500); // Wait a short period for outstanding
3868 							 // messages to be sent.
3869 		}
3870 	} else {
3871 		return;
3872 	}
3873 
3874 	tcpip_reset_flag = true;
3875 	kiss_text_available = false;
3876 	allow_kiss_socket_io = false;
3877 
3878 	if(data_io_type == DATA_IO_TCP && kiss_watchdog_running) {
3879 		kiss_watchdog_exit = true;
3880 		pthread_cond_signal(&kiss_watchdog_cond);
3881 
3882 		for(int i = 0; i < max_loops; i++) {
3883 			if(kiss_watchdog_running == false) break;
3884 			MilliSleep(loop_delay_ms);
3885 		}
3886 
3887 		if(!kiss_watchdog_running) {
3888 			pthread_join(kiss_watchdog_thread, NULL);
3889 			LOG_INFO("%s", "kiss_watchdog_running - join");
3890 		} else {
3891 			CANCEL_THREAD(kiss_watchdog_thread);
3892 			LOG_INFO("%s", "kiss_watchdog_running - cancel");
3893 		}
3894 	}
3895 
3896 	if(data_io_enabled == KISS_IO) {
3897 		data_io_enabled = DISABLED_IO;
3898 		data_io_type = DATA_IO_NA;
3899 	}
3900 
3901 	kiss_rx_exit = true;
3902 
3903 	if(kiss_socket) {
3904 		kiss_socket->shut_down();
3905 		kiss_socket->close();
3906 	}
3907 
3908 	for(int i = 0; i < max_loops; i++) {
3909 		if(kiss_rx_loop_running == false) break;
3910 		MilliSleep(loop_delay_ms);
3911 	}
3912 
3913 	if(!kiss_rx_loop_running) {
3914 		pthread_join(kiss_rx_socket_thread, NULL);
3915 		LOG_INFO("%s", "kiss_rx_loop_running - join");
3916 	} else {
3917 		CANCEL_THREAD(kiss_rx_socket_thread);
3918 		LOG_INFO("%s", "kiss_rx_loop_running - cancel");
3919 	}
3920 
3921 	kiss_exit = 1;
3922 
3923 	for(int i = 0; i < max_loops; i++) {
3924 		if(kiss_loop_running == false) break;
3925 		MilliSleep(loop_delay_ms);
3926 	}
3927 
3928 	if(!kiss_loop_running) {
3929 		pthread_join(kiss_thread, NULL);
3930 		LOG_INFO("%s", "kiss_loop_running - join");
3931 	} else {
3932 		CANCEL_THREAD(kiss_thread);
3933 		LOG_INFO("%s", "kiss_loop_running - cancel");
3934 	}
3935 
3936 	LOG_INFO("%s", "Kiss loop terminated. ");
3937 
3938 	kiss_socket = 0;
3939 	kiss_enabled = false;
3940 	kiss_loop_running = false;
3941 	kiss_rx_loop_running = false;
3942 	kiss_watchdog_running = false;
3943 
3944 	Fl::awake(kiss_io_set_button_state, (void *) IO_START_STR);
3945 
3946 	tcpip_reset_flag = false;
3947 
3948 	if((retry_count > 0) && progStatus.kiss_tcp_io)
3949 		Fl::awake(kiss_main_thread_retry_open, (void *) 0);
3950 }
3951 
3952 /**********************************************************************************
3953  *
3954  **********************************************************************************/
kiss_main_thread_retry_open(void * ptr)3955 void kiss_main_thread_retry_open(void *ptr)
3956 {
3957 	if(!progStatus.kiss_tcp_listen)
3958 		MilliSleep(KISS_RETRY_WAIT_TIME);
3959 	connect_to_kiss_io(false);
3960 }
3961 
3962 /**********************************************************************************
3963  *
3964  **********************************************************************************/
connect_to_kiss_io(bool user_requested)3965 void connect_to_kiss_io(bool user_requested)
3966 {
3967 	guard_lock external_lock(&restart_mutex);
3968 
3969 	if(kiss_socket) {
3970 		if(user_requested)
3971 			retry_count = 0;
3972 
3973 		kiss_close(true);
3974 
3975 		if(user_requested)
3976 			return;
3977 	}
3978 
3979 	if(user_requested || progStatus.kiss_tcp_listen)
3980 		retry_count = KISS_CONNECT_RETRY_COUNT;
3981 
3982 	if(retry_count > 0) {
3983 		retry_count--;
3984 		kiss_init(progdefaults.kiss_tcp_listen ? false : true);
3985 	}
3986 }
3987 
3988 /**********************************************************************************
3989  *
3990  **********************************************************************************/
kiss_thread_running(void)3991 bool kiss_thread_running(void)
3992 {
3993 	return (bool) kiss_enabled;
3994 }
3995 
3996 /**********************************************************************************
3997  *
3998  **********************************************************************************/
kiss_get_char(void)3999 int kiss_get_char(void)
4000 {
4001 	/// Mutex is unlocked when returning from function
4002 	guard_lock to_radio_lock(&to_radio_mutex);
4003 	int c = 0;
4004 	static bool toggle_flag = 0;
4005 
4006 	if (kiss_text_available) {
4007 		if (pText != (int)to_radio.length()) {
4008 			c = to_radio[pText++] & 0xFF;
4009 			toggle_flag = true;
4010 		} else {
4011 			kiss_text_available = false;
4012 			to_radio.clear();
4013 			pText = 0;
4014 			c = GET_TX_CHAR_ETX;
4015 
4016 			if(toggle_flag) {
4017 				bcast_tx_buffer_empty_kiss_frame();
4018 				toggle_flag = 0;
4019 			}
4020 		}
4021 	}
4022 
4023 	return c;
4024 }
4025