// ------------------------------------------------------------------------------------------------ // Run the KISS virtual TNC void kiss_run(serial_t *serial_parms, spi_parms_t *spi_parms, arguments_t *arguments) // ------------------------------------------------------------------------------------------------ { static const size_t bufsize = RADIO_BUFSIZE; uint32_t timeout_value; uint8_t rx_buffer[bufsize], tx_buffer[bufsize]; uint8_t rtx_toggle; // 1:Tx, 0:Rx uint8_t rx_trigger; uint8_t tx_trigger; uint8_t force_mode; int rx_count, tx_count, byte_count, ret; uint64_t timestamp; struct timeval tp; set_serial_parameters(serial_parms, arguments); init_radio_int(spi_parms, arguments); memset(rx_buffer, 0, bufsize); memset(tx_buffer, 0, bufsize); radio_flush_fifos(spi_parms); verbprintf(1, "Starting...\n"); force_mode = 1; rtx_toggle = 0; rx_trigger = 0; tx_trigger = 0; rx_count = 0; tx_count = 0; radio_init_rx(spi_parms, arguments); // init for new packet to receive Rx radio_turn_rx(spi_parms); // Turn Rx on while(1) { byte_count = radio_receive_packet(spi_parms, arguments, &rx_buffer[rx_count]); // check if anything was received on radio link if (byte_count > 0) { rx_count += byte_count; // Accumulate Rx gettimeofday(&tp, NULL); timestamp = tp.tv_sec * 1000000ULL + tp.tv_usec; timeout_value = arguments->tnc_radio_window; force_mode = (timeout_value == 0); if (rtx_toggle) // Tx to Rx transition { tx_trigger = 1; // Push Tx } else { tx_trigger = 0; } radio_init_rx(spi_parms, arguments); // Init for new packet to receive rtx_toggle = 0; } byte_count = read_serial(serial_parms, &tx_buffer[tx_count], bufsize - tx_count); if (byte_count > 0) { tx_count += byte_count; // Accumulate Tx gettimeofday(&tp, NULL); timestamp = tp.tv_sec * 1000000ULL + tp.tv_usec; timeout_value = arguments->tnc_serial_window; force_mode = (timeout_value == 0); if (!rtx_toggle) // Rx to Tx transition { rx_trigger = 1; } else { rx_trigger = 0; } rtx_toggle = 1; } if ((rx_count > 0) && ((rx_trigger) || (force_mode))) // Send bytes received on air to serial { radio_wait_free(); // Make sure no radio operation is in progress radio_turn_idle(spi_parms); // Inhibit radio operations verbprintf(2, "Received %d bytes\n", rx_count); ret = write_serial(serial_parms, rx_buffer, rx_count); verbprintf(2, "Sent %d bytes on serial\n", ret); radio_init_rx(spi_parms, arguments); // Init for new packet to receive Rx radio_turn_rx(spi_parms); // Put back into Rx rx_count = 0; rx_trigger = 0; } if ((tx_count > 0) && ((tx_trigger) || (force_mode))) // Send bytes received on serial to air { if (!kiss_command(tx_buffer)) { radio_wait_free(); // Make sure no radio operation is in progress radio_turn_idle(spi_parms); // Inhibit radio operations (should be superfluous since both Tx and Rx turn to IDLE after a packet has been processed) radio_flush_fifos(spi_parms); // Flush result of any Rx activity verbprintf(2, "%d bytes to send\n", tx_count); if (tnc_tx_keyup_delay) { usleep(tnc_tx_keyup_delay); } radio_send_packet(spi_parms, arguments, tx_buffer, tx_count); radio_init_rx(spi_parms, arguments); // init for new packet to receive Rx radio_turn_rx(spi_parms); // put back into Rx } tx_count = 0; tx_trigger = 0; } if (!force_mode) { gettimeofday(&tp, NULL); if ((tp.tv_sec * 1000000ULL + tp.tv_usec) > timestamp + timeout_value) { force_mode = 1; } } radio_wait_a_bit(4); } }
// ------------------------------------------------------------------------------------------------ int main (int argc, char **argv) // ------------------------------------------------------------------------------------------------ { int i, nbytes; // unsolicited termination handling struct sigaction sa; // Catch all signals possible on process exit! for (i = 1; i < 64; i++) { // skip SIGUSR2 for Wiring Pi if (i == 17) continue; // These are uncatchable or harmless or we want a core dump (SEGV) if (i != SIGKILL && i != SIGSEGV && i != SIGSTOP && i != SIGVTALRM && i != SIGWINCH && i != SIGPROF) { memset(&sa, 0, sizeof(sa)); sa.sa_handler = terminate; sigaction(i, &sa, NULL); } } // Set argument defaults init_args(&arguments); // Parse arguments argp_parse (&argp, argc, argv, 0, 0, &arguments); if (arguments.print_long_help) { print_long_help(); return 0; } if (!arguments.usbacm_device) { arguments.usbacm_device = strdup("/dev/ttyACM2"); } if (!arguments.serial_device) { arguments.serial_device = strdup("/var/ax25/axp2"); } if (!arguments.bulk_filename) { arguments.bulk_filename = strdup("-"); } set_serial_parameters(&serial_parms_ax25, arguments.serial_device, get_serial_speed(arguments.serial_speed, &arguments.serial_speed_n)); set_serial_parameters(&serial_parms_usb, arguments.usbacm_device, get_serial_speed(115200, &arguments.usb_speed_n)); init_radio_parms(&radio_parms, &arguments); if (arguments.verbose_level > 0) { print_args(&arguments); print_radio_parms(&radio_parms); fprintf(stderr, "\n"); } if (arguments.tnc_mode == TNC_KISS) { kiss_init(&arguments); kiss_run(&serial_parms_ax25, &serial_parms_usb, &radio_parms, &arguments); } else if (arguments.tnc_mode == TNC_SLIP) { arguments.slip = 1; kiss_init(&arguments); kiss_run(&serial_parms_ax25, &serial_parms_usb, &radio_parms, &arguments); } else if (arguments.tnc_mode == TNC_TEST_USB_ECHO) // This one does not need any access to the radio { usb_test_echo(&serial_parms_usb, &arguments); } else if (arguments.tnc_mode == TNC_RADIO_STATUS) { print_radio_status(&serial_parms_usb, &arguments); } else if (arguments.tnc_mode == TNC_RADIO_INIT) { init_radio(&serial_parms_usb, &radio_parms, &arguments); if (nbytes < 0) { fprintf(stderr, "Error\n"); } } else if (arguments.tnc_mode == TNC_TEST_TX) { radio_transmit_test(&serial_parms_usb, &radio_parms, &arguments); } else if (arguments.tnc_mode == TNC_TEST_RX) { radio_receive_test(&serial_parms_usb, &radio_parms, &arguments); } else if (arguments.tnc_mode == TNC_TEST_ECHO_TX) { radio_echo_test(&serial_parms_usb, &radio_parms, &arguments, 1); } else if (arguments.tnc_mode == TNC_TEST_ECHO_RX) { radio_echo_test(&serial_parms_usb, &radio_parms, &arguments, 0); } else if (arguments.tnc_mode == TNC_TEST_TX_PACKET) { radio_packet_transmit_test(&serial_parms_usb, &radio_parms, &arguments); } else if (arguments.tnc_mode == TNC_TEST_RX_PACKET) { radio_packet_receive_test(&serial_parms_usb, &radio_parms, &arguments); } else if (arguments.tnc_mode == TNC_TEST_RX_PACKET_NON_BLOCKING) { radio_packet_receive_nb_test(&serial_parms_usb, &radio_parms, &arguments); } else if (arguments.tnc_mode == TNC_BULK_TX) { file_bulk_transmit(&serial_parms_usb, &radio_parms, &arguments); } else if (arguments.tnc_mode == TNC_BULK_RX) { file_bulk_receive(&serial_parms_usb, &radio_parms, &arguments); } close_serial(&serial_parms_usb); close_serial(&serial_parms_ax25); delete_args(&arguments); return 0; }
int main(int argc, char *argv[]) { unsigned char bytes[BLOCK_SIZE]; int read_fd = -1; int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; char *device = NULL; char *serial = NULL; char *bytes_file = NULL; bool show_bps = false; std::string username, password; std::vector<std::string> hosts; int log_level = LOG_INFO; fprintf(stderr, "%s, (C) 2009-2015 by [email protected]\n", server_type); while((c = getopt(argc, argv, "hSX:P:o:p:I:d:L:l:sn")) != -1) { switch(c) { case 'S': show_bps = true; break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'o': bytes_file = optarg; break; case 'p': serial = optarg; break; case 'I': hosts.push_back(optarg); break; case 'd': device = optarg; break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; case 'h': help(); return 0; default: help(); return 1; } } if (!hosts.empty() && (username.length() == 0 || password.length() == 0)) error_exit("please select a file with authentication parameters (username + password) using the -X switch"); if (hosts.empty() && !bytes_file) error_exit("no host to connect to or file to write to given"); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); if (device) read_fd = open(device, O_RDONLY); if (read_fd == -1) error_exit("error opening %s", device); if (serial) set_serial_parameters(read_fd, serial); (void)umask(0177); no_core(); lock_mem(bytes, sizeof bytes); if (!do_not_fork) { if (daemon(0, 0) == -1) error_exit("fork failed"); } protocol *p = NULL; if (!hosts.empty()) p = new protocol(&hosts, username, password, true, server_type, DEFAULT_COMM_TO); write_pid(pid_file); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); init_showbps(); set_showbps_start_ts(); for(;!do_exit;) { if (READ(read_fd, bytes, BLOCK_SIZE, &do_exit) != BLOCK_SIZE) error_exit("error reading from input"); if (show_bps) update_showbps(BLOCK_SIZE); if (bytes_file) emit_buffer_to_file(bytes_file, bytes, BLOCK_SIZE); if (p && p -> message_transmit_entropy_data(bytes, BLOCK_SIZE, &do_exit) == -1) { dolog(LOG_INFO, "connection closed"); p -> drop(); } set_showbps_start_ts(); } memset(bytes, 0x00, sizeof bytes); unlink(pid_file); delete p; return 0; }