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