mirror of https://github.com/wb2osz/direwolf.git
KISS TNC enhancements: Multiple TCP clients, serial port for Linux, polling for Bluetooth device.
This commit is contained in:
parent
15b0f59e3a
commit
bef8a97323
18
CHANGES.md
18
CHANGES.md
|
@ -2,6 +2,24 @@
|
||||||
# Revision History #
|
# Revision History #
|
||||||
|
|
||||||
|
|
||||||
|
## Version 1.5 -- Development snapshot A -- May 2017 ##
|
||||||
|
|
||||||
|
This is a snapshot of ongoing development towards version of 1.5. Some features might be incomplete or broken or not documented properly.
|
||||||
|
|
||||||
|
### New Features: ###
|
||||||
|
|
||||||
|
- TCP KISS can now handle multiple concurrent applications.
|
||||||
|
|
||||||
|
- Linux can use serial port for KISS in addition to a pseudo terminal.
|
||||||
|
|
||||||
|
- New document ***Bluetooth-KISS-TNC.pdf*** explaining how to use KISS over Bluetooth.
|
||||||
|
|
||||||
|
### Bugs Fixed: ###
|
||||||
|
|
||||||
|
- Little spelling errors in messages ????
|
||||||
|
|
||||||
|
----------
|
||||||
|
|
||||||
## Version 1.4 -- April 2017 ##
|
## Version 1.4 -- April 2017 ##
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -292,7 +292,7 @@ z := $(notdir ${CURDIR})
|
||||||
direwolf : direwolf.o config.o recv.o demod.o dsp.o demod_afsk.o demod_psk.o demod_9600.o hdlc_rec.o \
|
direwolf : direwolf.o config.o recv.o demod.o dsp.o demod_afsk.o demod_psk.o demod_9600.o hdlc_rec.o \
|
||||||
hdlc_rec2.o multi_modem.o rdq.o rrbb.o dlq.o \
|
hdlc_rec2.o multi_modem.o rdq.o rrbb.o dlq.o \
|
||||||
fcs_calc.o ax25_pad.o ax25_pad2.o xid.o \
|
fcs_calc.o ax25_pad.o ax25_pad2.o xid.o \
|
||||||
decode_aprs.o symbols.o server.o kiss.o kissnet.o kiss_frame.o hdlc_send.o fcs_calc.o \
|
decode_aprs.o symbols.o server.o kiss.o kissserial.o kissnet.o kiss_frame.o hdlc_send.o fcs_calc.o \
|
||||||
gen_tone.o audio.o audio_stats.o digipeater.o cdigipeater.o pfilter.o dedupe.o tq.o xmit.o morse.o \
|
gen_tone.o audio.o audio_stats.o digipeater.o cdigipeater.o pfilter.o dedupe.o tq.o xmit.o morse.o \
|
||||||
ptt.o beacon.o encode_aprs.o latlong.o encode_aprs.o latlong.o textcolor.o \
|
ptt.o beacon.o encode_aprs.o latlong.o encode_aprs.o latlong.o textcolor.o \
|
||||||
dtmf.o aprs_tt.o tt_user.o tt_text.o igate.o waypoint.o serial_port.o log.o telemetry.o \
|
dtmf.o aprs_tt.o tt_user.o tt_text.o igate.o waypoint.o serial_port.o log.o telemetry.o \
|
||||||
|
@ -570,15 +570,22 @@ install : $(APPS) direwolf.conf tocalls.txt symbols-new.txt symbolsX.txt dw-icon
|
||||||
# doc/README.md contains an overview of the PDF file contents and is more useful here.
|
# doc/README.md contains an overview of the PDF file contents and is more useful here.
|
||||||
#
|
#
|
||||||
$(INSTALL) -D --mode=644 doc/README.md $(INSTALLDIR)/share/doc/direwolf/README.md
|
$(INSTALL) -D --mode=644 doc/README.md $(INSTALLDIR)/share/doc/direwolf/README.md
|
||||||
$(INSTALL) -D --mode=644 doc/User-Guide.pdf $(INSTALLDIR)/share/doc/direwolf/User-Guide.pdf
|
$(INSTALL) -D --mode=644 doc/2400-4800-PSK-for-APRS-Packet-Radio.pdf $(INSTALLDIR)/share/doc/direwolf/2400-4800-PSK-for-APRS-Packet-Radio.pdf
|
||||||
|
$(INSTALL) -D --mode=644 doc/A-Better-APRS-Packet-Demodulator-Part-1-1200-baud.pdf $(INSTALLDIR)/share/doc/direwolf/A-Better-APRS-Packet-Demodulator-Part-1-1200-baud.pdf
|
||||||
|
$(INSTALL) -D --mode=644 doc/A-Better-APRS-Packet-Demodulator-Part-2-9600-baud.pdf $(INSTALLDIR)/share/doc/direwolf/A-Better-APRS-Packet-Demodulator-Part-2-9600-baud.pdf
|
||||||
|
$(INSTALL) -D --mode=644 doc/A-Closer-Look-at-the-WA8LMF-TNC-Test-CD.pdf $(INSTALLDIR)/share/doc/direwolf/A-Closer-Look-at-the-WA8LMF-TNC-Test-CD.pdf
|
||||||
|
$(INSTALL) -D --mode=644 doc/APRS-Telemetry-Toolkit.pdf $(INSTALLDIR)/share/doc/direwolf/APRS-Telemetry-Toolkit.pdf
|
||||||
|
$(INSTALL) -D --mode=644 doc/APRStt-Implementation-Notes.pdf $(INSTALLDIR)/share/doc/direwolf/APRStt-Implementation-Notes.pdf
|
||||||
|
$(INSTALL) -D --mode=644 doc/APRStt-interface-for-SARTrack.pdf $(INSTALLDIR)/share/doc/direwolf/APRStt-interface-for-SARTrack.pdf
|
||||||
|
$(INSTALL) -D --mode=644 doc/APRStt-Listening-Example.pdf $(INSTALLDIR)/share/doc/direwolf/APRStt-Listening-Example.pdf
|
||||||
|
$(INSTALL) -D --mode=644 doc/Bluetooth-KISS-TNC.pdf $(INSTALLDIR)/share/doc/direwolf/Bluetooth-KISS-TNC.pdf
|
||||||
|
$(INSTALL) -D --mode=644 doc/Going-beyond-9600-baud.pdf $(INSTALLDIR)/share/doc/direwolf/Going-beyond-9600-baud.pdf
|
||||||
$(INSTALL) -D --mode=644 doc/Raspberry-Pi-APRS.pdf $(INSTALLDIR)/share/doc/direwolf/Raspberry-Pi-APRS.pdf
|
$(INSTALL) -D --mode=644 doc/Raspberry-Pi-APRS.pdf $(INSTALLDIR)/share/doc/direwolf/Raspberry-Pi-APRS.pdf
|
||||||
$(INSTALL) -D --mode=644 doc/Raspberry-Pi-APRS-Tracker.pdf $(INSTALLDIR)/share/doc/direwolf/Raspberry-Pi-APRS-Tracker.pdf
|
$(INSTALL) -D --mode=644 doc/Raspberry-Pi-APRS-Tracker.pdf $(INSTALLDIR)/share/doc/direwolf/Raspberry-Pi-APRS-Tracker.pdf
|
||||||
$(INSTALL) -D --mode=644 doc/Raspberry-Pi-SDR-IGate.pdf $(INSTALLDIR)/share/doc/direwolf/Raspberry-Pi-SDR-IGate.pdf
|
$(INSTALL) -D --mode=644 doc/Raspberry-Pi-SDR-IGate.pdf $(INSTALLDIR)/share/doc/direwolf/Raspberry-Pi-SDR-IGate.pdf
|
||||||
$(INSTALL) -D --mode=644 doc/APRStt-Implementation-Notes.pdf $(INSTALLDIR)/share/doc/direwolf/APRStt-Implementation-Notes.pdf
|
$(INSTALL) -D --mode=644 doc/Successful-APRS-IGate-Operation.pdf $(INSTALLDIR)/share/doc/direwolf/Successful-APRS-IGate-Operation.pdf
|
||||||
$(INSTALL) -D --mode=644 doc/APRStt-interface-for-SARTrack.pdf $(INSTALLDIR)/share/doc/direwolf/APRStt-interface-for-SARTrack.pdf
|
$(INSTALL) -D --mode=644 doc/User-Guide.pdf $(INSTALLDIR)/share/doc/direwolf/User-Guide.pdf
|
||||||
$(INSTALL) -D --mode=644 doc/APRS-Telemetry-Toolkit.pdf $(INSTALLDIR)/share/doc/direwolf/APRS-Telemetry-Toolkit.pdf
|
$(INSTALL) -D --mode=644 doc/WA8LMF-TNC-Test-CD-Results.pdf $(INSTALLDIR)/share/doc/direwolf/WA8LMF-TNC-Test-CD-Results.pdf
|
||||||
$(INSTALL) -D --mode=644 doc/A-Better-APRS-Packet-Demodulator-Part-1-1200-baud.pdf $(INSTALLDIR)/share/doc/direwolf/A-Better-APRS-Packet-Demodulator-Part-1-1200-baud.pdf
|
|
||||||
$(INSTALL) -D --mode=644 doc/A-Better-APRS-Packet-Demodulator-Part-2-9600-baud.pdf $(INSTALLDIR)/share/doc/direwolf/A-Better-APRS-Packet-Demodulator-Part-2-9600-baud.pdf
|
|
||||||
#
|
#
|
||||||
# Various sample config and other files go into examples under the doc directory.
|
# Various sample config and other files go into examples under the doc directory.
|
||||||
# When building from source, these can be put in home directory with "make install-conf".
|
# When building from source, these can be put in home directory with "make install-conf".
|
||||||
|
|
|
@ -237,7 +237,7 @@ direwolf : direwolf.o aprs_tt.o audio_portaudio.o audio_stats.o ax25_link.o ax25
|
||||||
demod.o digipeater.o cdigipeater.o dlq.o dsp.o dtime_now.o dtmf.o dwgps.o \
|
demod.o digipeater.o cdigipeater.o dlq.o dsp.o dtime_now.o dtmf.o dwgps.o \
|
||||||
encode_aprs.o encode_aprs.o fcs_calc.o fcs_calc.o gen_tone.o \
|
encode_aprs.o encode_aprs.o fcs_calc.o fcs_calc.o gen_tone.o \
|
||||||
geotranz.a hdlc_rec.o hdlc_rec2.o hdlc_send.o igate.o kiss_frame.o \
|
geotranz.a hdlc_rec.o hdlc_rec2.o hdlc_send.o igate.o kiss_frame.o \
|
||||||
kiss.o kissnet.o latlong.o latlong.o log.o morse.o multi_modem.o \
|
kiss.o kissserial.o kissnet.o latlong.o latlong.o log.o morse.o multi_modem.o \
|
||||||
waypoint.o serial_port.o pfilter.o ptt.o rdq.o recv.o rrbb.o server.o \
|
waypoint.o serial_port.o pfilter.o ptt.o rdq.o recv.o rrbb.o server.o \
|
||||||
symbols.o telemetry.o textcolor.o tq.o tt_text.o tt_user.o xid.o xmit.o \
|
symbols.o telemetry.o textcolor.o tq.o tt_text.o tt_user.o xid.o xmit.o \
|
||||||
dwgps.o dwgpsnmea.o mheard.o
|
dwgps.o dwgpsnmea.o mheard.o
|
||||||
|
@ -359,15 +359,26 @@ install : $(APPS) direwolf.conf tocalls.txt symbols-new.txt symbolsX.txt dw-icon
|
||||||
$(INSTALL) -D --mode=644 LICENSE-dire-wolf.txt $(INSTALLDIR)/share/doc/direwolf/LICENSE-dire-wolf.txt
|
$(INSTALL) -D --mode=644 LICENSE-dire-wolf.txt $(INSTALLDIR)/share/doc/direwolf/LICENSE-dire-wolf.txt
|
||||||
$(INSTALL) -D --mode=644 LICENSE-other.txt $(INSTALLDIR)/share/doc/direwolf/LICENSE-other.txt
|
$(INSTALL) -D --mode=644 LICENSE-other.txt $(INSTALLDIR)/share/doc/direwolf/LICENSE-other.txt
|
||||||
#
|
#
|
||||||
$(INSTALL) -D --mode=644 doc/User-Guide.pdf $(INSTALLDIR)/share/doc/direwolf/User-Guide.pdf
|
# ./README.md is an overview for the project main page.
|
||||||
|
# doc/README.md contains an overview of the PDF file contents and is more useful here.
|
||||||
|
#
|
||||||
|
$(INSTALL) -D --mode=644 doc/README.md $(INSTALLDIR)/share/doc/direwolf/README.md
|
||||||
|
$(INSTALL) -D --mode=644 doc/2400-4800-PSK-for-APRS-Packet-Radio.pdf $(INSTALLDIR)/share/doc/direwolf/2400-4800-PSK-for-APRS-Packet-Radio.pdf
|
||||||
|
$(INSTALL) -D --mode=644 doc/A-Better-APRS-Packet-Demodulator-Part-1-1200-baud.pdf $(INSTALLDIR)/share/doc/direwolf/A-Better-APRS-Packet-Demodulator-Part-1-1200-baud.pdf
|
||||||
|
$(INSTALL) -D --mode=644 doc/A-Better-APRS-Packet-Demodulator-Part-2-9600-baud.pdf $(INSTALLDIR)/share/doc/direwolf/A-Better-APRS-Packet-Demodulator-Part-2-9600-baud.pdf
|
||||||
|
$(INSTALL) -D --mode=644 doc/A-Closer-Look-at-the-WA8LMF-TNC-Test-CD.pdf $(INSTALLDIR)/share/doc/direwolf/A-Closer-Look-at-the-WA8LMF-TNC-Test-CD.pdf
|
||||||
|
$(INSTALL) -D --mode=644 doc/APRS-Telemetry-Toolkit.pdf $(INSTALLDIR)/share/doc/direwolf/APRS-Telemetry-Toolkit.pdf
|
||||||
|
$(INSTALL) -D --mode=644 doc/APRStt-Implementation-Notes.pdf $(INSTALLDIR)/share/doc/direwolf/APRStt-Implementation-Notes.pdf
|
||||||
|
$(INSTALL) -D --mode=644 doc/APRStt-interface-for-SARTrack.pdf $(INSTALLDIR)/share/doc/direwolf/APRStt-interface-for-SARTrack.pdf
|
||||||
|
$(INSTALL) -D --mode=644 doc/APRStt-Listening-Example.pdf $(INSTALLDIR)/share/doc/direwolf/APRStt-Listening-Example.pdf
|
||||||
|
$(INSTALL) -D --mode=644 doc/Bluetooth-KISS-TNC.pdf $(INSTALLDIR)/share/doc/direwolf/Bluetooth-KISS-TNC.pdf
|
||||||
|
$(INSTALL) -D --mode=644 doc/Going-beyond-9600-baud.pdf $(INSTALLDIR)/share/doc/direwolf/Going-beyond-9600-baud.pdf
|
||||||
$(INSTALL) -D --mode=644 doc/Raspberry-Pi-APRS.pdf $(INSTALLDIR)/share/doc/direwolf/Raspberry-Pi-APRS.pdf
|
$(INSTALL) -D --mode=644 doc/Raspberry-Pi-APRS.pdf $(INSTALLDIR)/share/doc/direwolf/Raspberry-Pi-APRS.pdf
|
||||||
$(INSTALL) -D --mode=644 doc/Raspberry-Pi-APRS-Tracker.pdf $(INSTALLDIR)/share/doc/direwolf/Raspberry-Pi-APRS-Tracker.pdf
|
$(INSTALL) -D --mode=644 doc/Raspberry-Pi-APRS-Tracker.pdf $(INSTALLDIR)/share/doc/direwolf/Raspberry-Pi-APRS-Tracker.pdf
|
||||||
$(INSTALL) -D --mode=644 doc/Raspberry-Pi-SDR-IGate.pdf $(INSTALLDIR)/share/doc/direwolf/Raspberry-Pi-SDR-IGate.pdf
|
$(INSTALL) -D --mode=644 doc/Raspberry-Pi-SDR-IGate.pdf $(INSTALLDIR)/share/doc/direwolf/Raspberry-Pi-SDR-IGate.pdf
|
||||||
$(INSTALL) -D --mode=644 doc/APRStt-Implementation-Notes.pdf $(INSTALLDIR)/share/doc/direwolf/APRStt-Implementation-Notes.pdf
|
$(INSTALL) -D --mode=644 doc/Successful-APRS-IGate-Operation.pdf $(INSTALLDIR)/share/doc/direwolf/Successful-APRS-IGate-Operation.pdf
|
||||||
$(INSTALL) -D --mode=644 doc/APRStt-interface-for-SARTrack.pdf $(INSTALLDIR)/share/doc/direwolf/APRStt-interface-for-SARTrack.pdf
|
$(INSTALL) -D --mode=644 doc/User-Guide.pdf $(INSTALLDIR)/share/doc/direwolf/User-Guide.pdf
|
||||||
$(INSTALL) -D --mode=644 doc/APRS-Telemetry-Toolkit.pdf $(INSTALLDIR)/share/doc/direwolf/APRS-Telemetry-Toolkit.pdf
|
$(INSTALL) -D --mode=644 doc/WA8LMF-TNC-Test-CD-Results.pdf $(INSTALLDIR)/share/doc/direwolf/WA8LMF-TNC-Test-CD-Results.pdf
|
||||||
$(INSTALL) -D --mode=644 doc/A-Better-APRS-Packet-Demodulator-Part-1-1200-baud.pdf $(INSTALLDIR)/share/doc/direwolf/A-Better-APRS-Packet-Demodulator-Part-1-1200-baud.pdf
|
|
||||||
$(INSTALL) -D --mode=644 doc/A-Better-APRS-Packet-Demodulator-Part-2-9600-baud.pdf $(INSTALLDIR)/share/doc/direwolf/A-Better-APRS-Packet-Demodulator-Part-2-9600-baud.pdf
|
|
||||||
#
|
#
|
||||||
# Sample config files also go into the doc directory.
|
# Sample config files also go into the doc directory.
|
||||||
# When building from source, these can be put in home directory with "make install-conf".
|
# When building from source, these can be put in home directory with "make install-conf".
|
||||||
|
|
19
Makefile.win
19
Makefile.win
|
@ -98,7 +98,7 @@ demod_psk.o : fsk_demod_state.h
|
||||||
direwolf : direwolf.o config.o recv.o demod.o dsp.o demod_afsk.o demod_psk.o demod_9600.o hdlc_rec.o \
|
direwolf : direwolf.o config.o recv.o demod.o dsp.o demod_afsk.o demod_psk.o demod_9600.o hdlc_rec.o \
|
||||||
hdlc_rec2.o multi_modem.o rdq.o rrbb.o dlq.o \
|
hdlc_rec2.o multi_modem.o rdq.o rrbb.o dlq.o \
|
||||||
fcs_calc.o ax25_pad.o ax25_pad2.o xid.o \
|
fcs_calc.o ax25_pad.o ax25_pad2.o xid.o \
|
||||||
decode_aprs.o symbols.o server.o kiss.o kissnet.o kiss_frame.o hdlc_send.o fcs_calc.o \
|
decode_aprs.o symbols.o server.o kiss.o kissserial.o kissnet.o kiss_frame.o hdlc_send.o fcs_calc.o \
|
||||||
gen_tone.o morse.o audio_win.o audio_stats.o digipeater.o cdigipeater.o pfilter.o dedupe.o tq.o xmit.o \
|
gen_tone.o morse.o audio_win.o audio_stats.o digipeater.o cdigipeater.o pfilter.o dedupe.o tq.o xmit.o \
|
||||||
ptt.o beacon.o dwgps.o encode_aprs.o latlong.o textcolor.o \
|
ptt.o beacon.o dwgps.o encode_aprs.o latlong.o textcolor.o \
|
||||||
dtmf.o aprs_tt.o tt_user.o tt_text.o igate.o waypoint.o serial_port.o log.o telemetry.o \
|
dtmf.o aprs_tt.o tt_user.o tt_text.o igate.o waypoint.o serial_port.o log.o telemetry.o \
|
||||||
|
@ -193,6 +193,12 @@ gen_packets : gen_packets.o ax25_pad.o hdlc_send.o fcs_calc.o gen_tone.o morse.
|
||||||
$(CC) $(CFLAGS) -o $@ $^
|
$(CC) $(CFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
|
||||||
|
# Connected mode packet application server.
|
||||||
|
|
||||||
|
appserver : appserver.o textcolor.o ax25_pad.o fcs_calc.o misc.a
|
||||||
|
$(CC) $(CFLAGS) -o $@ $^ -lwinmm -lws2_32
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------- Libraries --------------------------------------------
|
# ------------------------------------------- Libraries --------------------------------------------
|
||||||
|
|
||||||
|
@ -600,20 +606,25 @@ dist-win : direwolf.exe decode_aprs.exe text2tt.exe tt2text.exe ll2utm.exe utm2l
|
||||||
rm -f ../$z-win.zip
|
rm -f ../$z-win.zip
|
||||||
egrep '^C|^W' generic.conf | cut -c2-999 > direwolf.conf
|
egrep '^C|^W' generic.conf | cut -c2-999 > direwolf.conf
|
||||||
unix2dos direwolf.conf
|
unix2dos direwolf.conf
|
||||||
|
cp doc/README.md README-doc.md
|
||||||
zip --junk-paths ../$z-win.zip \
|
zip --junk-paths ../$z-win.zip \
|
||||||
README.md \
|
README.md \
|
||||||
CHANGES.md \
|
CHANGES.md \
|
||||||
doc/User-Guide.pdf \
|
README-doc.md \
|
||||||
doc/Raspberry-Pi-APRS.pdf \
|
doc/2400-4800-PSK-for-APRS-Packet-Radio.pdf \
|
||||||
doc/A-Better-APRS-Packet-Demodulator-Part-1-1200-baud.pdf \
|
doc/A-Better-APRS-Packet-Demodulator-Part-1-1200-baud.pdf \
|
||||||
doc/A-Better-APRS-Packet-Demodulator-Part-2-9600-baud.pdf \
|
doc/A-Better-APRS-Packet-Demodulator-Part-2-9600-baud.pdf \
|
||||||
|
doc/A-Closer-Look-at-the-WA8LMF-TNC-Test-CD.pdf \
|
||||||
doc/APRS-Telemetry-Toolkit.pdf \
|
doc/APRS-Telemetry-Toolkit.pdf \
|
||||||
doc/APRStt-Implementation-Notes.pdf \
|
doc/APRStt-Implementation-Notes.pdf \
|
||||||
doc/APRStt-interface-for-SARTrack.pdf \
|
doc/APRStt-interface-for-SARTrack.pdf \
|
||||||
doc/APRStt-Listening-Example.pdf \
|
doc/APRStt-Listening-Example.pdf \
|
||||||
|
doc/Bluetooth-KISS-TNC.pdf \
|
||||||
|
doc/Going-beyond-9600-baud.pdf \
|
||||||
doc/Raspberry-Pi-APRS.pdf \
|
doc/Raspberry-Pi-APRS.pdf \
|
||||||
doc/Raspberry-Pi-APRS-Tracker.pdf \
|
doc/Raspberry-Pi-APRS-Tracker.pdf \
|
||||||
doc/Raspberry-Pi-SDR-IGate.pdf \
|
doc/Raspberry-Pi-SDR-IGate.pdf \
|
||||||
|
doc/Successful-APRS-IGate-Operation.pdf \
|
||||||
doc/User-Guide.pdf \
|
doc/User-Guide.pdf \
|
||||||
doc/WA8LMF-TNC-Test-CD-Results.pdf \
|
doc/WA8LMF-TNC-Test-CD-Results.pdf \
|
||||||
LICENSE* \
|
LICENSE* \
|
||||||
|
@ -630,6 +641,7 @@ dist-win : direwolf.exe decode_aprs.exe text2tt.exe tt2text.exe ll2utm.exe utm2l
|
||||||
ttcalc.exe \
|
ttcalc.exe \
|
||||||
dwespeak.bat \
|
dwespeak.bat \
|
||||||
telemetry-toolkit/*
|
telemetry-toolkit/*
|
||||||
|
rm README-doc.md
|
||||||
|
|
||||||
|
|
||||||
# Reminders if pdf files are not up to date.
|
# Reminders if pdf files are not up to date.
|
||||||
|
@ -668,3 +680,4 @@ backup :
|
||||||
#
|
#
|
||||||
# DO NOT DELETE
|
# DO NOT DELETE
|
||||||
|
|
||||||
|
|
||||||
|
|
56
config.c
56
config.c
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 John Langner, WB2OSZ
|
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2017 John Langner, WB2OSZ
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -870,8 +870,9 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
/* Ideally we'd like to figure out if com0com is installed */
|
/* Ideally we'd like to figure out if com0com is installed */
|
||||||
/* and automatically enable this. */
|
/* and automatically enable this. */
|
||||||
|
|
||||||
//strlcpy (p_misc_config->nullmodem, DEFAULT_NULLMODEM, sizeof(p_misc_config->nullmodem));
|
strlcpy (p_misc_config->kiss_serial_port, "", sizeof(p_misc_config->kiss_serial_port));
|
||||||
strlcpy (p_misc_config->nullmodem, "", sizeof(p_misc_config->nullmodem));
|
p_misc_config->kiss_serial_speed = 0;
|
||||||
|
p_misc_config->kiss_serial_poll = 0;
|
||||||
|
|
||||||
strlcpy (p_misc_config->gpsnmea_port, "", sizeof(p_misc_config->gpsnmea_port));
|
strlcpy (p_misc_config->gpsnmea_port, "", sizeof(p_misc_config->gpsnmea_port));
|
||||||
strlcpy (p_misc_config->waypoint_port, "", sizeof(p_misc_config->waypoint_port));
|
strlcpy (p_misc_config->waypoint_port, "", sizeof(p_misc_config->waypoint_port));
|
||||||
|
@ -4102,17 +4103,58 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NULLMODEM - Device name for our end of the virtual "null modem"
|
* NULLMODEM name [ speed ] - Device name for serial port or our end of the virtual "null modem"
|
||||||
|
* SERIALKISS name [ speed ]
|
||||||
|
*
|
||||||
|
* Version 1.5: Added SERIALKISS which is equivalent to NULLMODEM.
|
||||||
|
* The original name sort of made sense when it was used only for one end of a virtual
|
||||||
|
* null modem cable on Windows only. Now it is also available for Linux.
|
||||||
|
* TODO1.5: In retrospect, this doesn't seem like such a good name.
|
||||||
*/
|
*/
|
||||||
else if (strcasecmp(t, "nullmodem") == 0) {
|
|
||||||
|
else if (strcasecmp(t, "NULLMODEM") == 0 || strcasecmp(t, "SERIALKISS") == 0) {
|
||||||
t = split(NULL,0);
|
t = split(NULL,0);
|
||||||
if (t == NULL) {
|
if (t == NULL) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("Config file: Missing device name for my end of the 'null modem' on line %d.\n", line);
|
dw_printf ("Config file: Missing serial port name on line %d.\n", line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
strlcpy (p_misc_config->nullmodem, t, sizeof(p_misc_config->nullmodem));
|
if (strlen(p_misc_config->kiss_serial_port) > 0) {
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf ("Config file: Warning serial port name on line %d replaces earlier value.\n", line);
|
||||||
|
}
|
||||||
|
strlcpy (p_misc_config->kiss_serial_port, t, sizeof(p_misc_config->kiss_serial_port));
|
||||||
|
p_misc_config->kiss_serial_speed = 0;
|
||||||
|
p_misc_config->kiss_serial_poll = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
t = split(NULL,0);
|
||||||
|
if (t != NULL) {
|
||||||
|
p_misc_config->kiss_serial_speed = atoi(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SERIALKISSPOLL name - Poll for serial port name that might come and go.
|
||||||
|
* e.g. /dev/rfcomm0 for bluetooth.
|
||||||
|
*/
|
||||||
|
|
||||||
|
else if (strcasecmp(t, "SERIALKISSPOLL") == 0) {
|
||||||
|
t = split(NULL,0);
|
||||||
|
if (t == NULL) {
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf ("Config file: Missing serial port name on line %d.\n", line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (strlen(p_misc_config->kiss_serial_port) > 0) {
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf ("Config file: Warning serial port name on line %d replaces earlier value.\n", line);
|
||||||
|
}
|
||||||
|
strlcpy (p_misc_config->kiss_serial_port, t, sizeof(p_misc_config->kiss_serial_port));
|
||||||
|
p_misc_config->kiss_serial_speed = 0;
|
||||||
|
p_misc_config->kiss_serial_poll = 1; // set polling.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
15
config.h
15
config.h
|
@ -34,13 +34,24 @@ enum sendto_type_e { SENDTO_XMIT, SENDTO_IGATE, SENDTO_RECV };
|
||||||
struct misc_config_s {
|
struct misc_config_s {
|
||||||
|
|
||||||
int agwpe_port; /* Port number for the "AGW TCPIP Socket Interface" */
|
int agwpe_port; /* Port number for the "AGW TCPIP Socket Interface" */
|
||||||
int kiss_port; /* Port number for the "KISS" protocol. */
|
int kiss_port; /* Port number for the "TCP KISS" protocol. */
|
||||||
int enable_kiss_pt; /* Enable pseudo terminal for KISS. */
|
int enable_kiss_pt; /* Enable pseudo terminal for KISS. */
|
||||||
/* Want this to be off by default because it hangs */
|
/* Want this to be off by default because it hangs */
|
||||||
/* after a while if nothing is reading from other end. */
|
/* after a while if nothing is reading from other end. */
|
||||||
|
|
||||||
char nullmodem[20]; /* Serial port name for our end of the */
|
char kiss_serial_port[20];
|
||||||
|
/* Serial port name for our end of the */
|
||||||
/* virtual null modem for native Windows apps. */
|
/* virtual null modem for native Windows apps. */
|
||||||
|
/* Version 1.5 add same capability for Linux. */
|
||||||
|
|
||||||
|
int kiss_serial_speed; /* Speed, in bps, for the KISS serial port. */
|
||||||
|
/* If 0, just leave what was already there. */
|
||||||
|
|
||||||
|
int kiss_serial_poll; /* When using Bluetooth KISS, the /dev/rfcomm0 device */
|
||||||
|
/* will appear and disappear as the remote application */
|
||||||
|
/* opens and closes the virtual COM port. */
|
||||||
|
/* When this is non-zero, we will check periodically to */
|
||||||
|
/* see if the device has appeared and we will open it. */
|
||||||
|
|
||||||
char gpsnmea_port[20]; /* Serial port name for reading NMEA sentences from GPS. */
|
char gpsnmea_port[20]; /* Serial port name for reading NMEA sentences from GPS. */
|
||||||
/* e.g. COM22, /dev/ttyACM0 */
|
/* e.g. COM22, /dev/ttyACM0 */
|
||||||
|
|
21
direwolf.c
21
direwolf.c
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 John Langner, WB2OSZ
|
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2017 John Langner, WB2OSZ
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -94,6 +94,7 @@
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "kiss.h"
|
#include "kiss.h"
|
||||||
#include "kissnet.h"
|
#include "kissnet.h"
|
||||||
|
#include "kissserial.h"
|
||||||
#include "kiss_frame.h"
|
#include "kiss_frame.h"
|
||||||
#include "waypoint.h"
|
#include "waypoint.h"
|
||||||
#include "gen_tone.h"
|
#include "gen_tone.h"
|
||||||
|
@ -260,8 +261,8 @@ int main (int argc, char *argv[])
|
||||||
text_color_init(t_opt);
|
text_color_init(t_opt);
|
||||||
text_color_set(DW_COLOR_INFO);
|
text_color_set(DW_COLOR_INFO);
|
||||||
//dw_printf ("Dire Wolf version %d.%d (%s) Beta Test\n", MAJOR_VERSION, MINOR_VERSION, __DATE__);
|
//dw_printf ("Dire Wolf version %d.%d (%s) Beta Test\n", MAJOR_VERSION, MINOR_VERSION, __DATE__);
|
||||||
//dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "H", __DATE__);
|
dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "A", __DATE__);
|
||||||
dw_printf ("Dire Wolf version %d.%d\n", MAJOR_VERSION, MINOR_VERSION);
|
//dw_printf ("Dire Wolf version %d.%d\n", MAJOR_VERSION, MINOR_VERSION);
|
||||||
|
|
||||||
#if defined(ENABLE_GPSD) || defined(USE_HAMLIB)
|
#if defined(ENABLE_GPSD) || defined(USE_HAMLIB)
|
||||||
dw_printf ("Includes optional support for: ");
|
dw_printf ("Includes optional support for: ");
|
||||||
|
@ -466,7 +467,7 @@ int main (int argc, char *argv[])
|
||||||
|
|
||||||
case 'a': server_set_debug(1); break;
|
case 'a': server_set_debug(1); break;
|
||||||
|
|
||||||
case 'k': d_k_opt++; kiss_serial_set_debug (d_k_opt); break;
|
case 'k': d_k_opt++; kissserial_set_debug (d_k_opt); kisspt_set_debug (d_k_opt); break;
|
||||||
case 'n': d_n_opt++; kiss_net_set_debug (d_n_opt); break;
|
case 'n': d_n_opt++; kiss_net_set_debug (d_n_opt); break;
|
||||||
|
|
||||||
case 'u': d_u_opt = 1; break;
|
case 'u': d_u_opt = 1; break;
|
||||||
|
@ -766,7 +767,8 @@ int main (int argc, char *argv[])
|
||||||
/*
|
/*
|
||||||
* Create a pseudo terminal and KISS TNC emulator.
|
* Create a pseudo terminal and KISS TNC emulator.
|
||||||
*/
|
*/
|
||||||
kiss_init (&misc_config);
|
kisspt_init (&misc_config);
|
||||||
|
kissserial_init (&misc_config);
|
||||||
kiss_frame_init (&audio_config);
|
kiss_frame_init (&audio_config);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1084,9 +1086,10 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
|
||||||
|
|
||||||
flen = ax25_pack(pp, fbuf);
|
flen = ax25_pack(pp, fbuf);
|
||||||
|
|
||||||
server_send_rec_packet (chan, pp, fbuf, flen);
|
server_send_rec_packet (chan, pp, fbuf, flen); // AGW net protocol
|
||||||
kissnet_send_rec_packet (chan, fbuf, flen);
|
kissnet_send_rec_packet (chan, fbuf, flen, -1); // KISS TCP
|
||||||
kiss_send_rec_packet (chan, fbuf, flen);
|
kissserial_send_rec_packet (chan, fbuf, flen, -1); // KISS serial port
|
||||||
|
kisspt_send_rec_packet (chan, fbuf, flen, -1); // KISS pseudo terminal
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If it came from DTMF decoder, send it to APRStt gateway.
|
* If it came from DTMF decoder, send it to APRStt gateway.
|
||||||
|
@ -1204,7 +1207,7 @@ static void usage (char **argv)
|
||||||
dw_printf (" -D n Divide audio sample rate by n for channel 0.\n");
|
dw_printf (" -D n Divide audio sample rate by n for channel 0.\n");
|
||||||
dw_printf (" -d Debug options:\n");
|
dw_printf (" -d Debug options:\n");
|
||||||
dw_printf (" a a = AGWPE network protocol client.\n");
|
dw_printf (" a a = AGWPE network protocol client.\n");
|
||||||
dw_printf (" k k = KISS serial port client.\n");
|
dw_printf (" k k = KISS serial port or pseudo terminal client.\n");
|
||||||
dw_printf (" n n = KISS network client.\n");
|
dw_printf (" n n = KISS network client.\n");
|
||||||
dw_printf (" u u = Display non-ASCII text in hexadecimal.\n");
|
dw_printf (" u u = Display non-ASCII text in hexadecimal.\n");
|
||||||
dw_printf (" p p = dump Packets in hexadecimal.\n");
|
dw_printf (" p p = dump Packets in hexadecimal.\n");
|
||||||
|
|
16
fcs_calc.c
16
fcs_calc.c
|
@ -87,6 +87,22 @@ unsigned short fcs_calc (unsigned char *data, int len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CRC is also used for duplicate checking for the digipeater and IGate.
|
||||||
|
* A packet is considered a duplicate if the source, destination, and
|
||||||
|
* information parts match. In other words, we ignore the via path
|
||||||
|
* which changes along the way.
|
||||||
|
* Rather than keeping a variable length string we just keep a 16 bit
|
||||||
|
* CRC which takes less memory and processing to compare.
|
||||||
|
*
|
||||||
|
* This can result in occasional false matches. If we had a random
|
||||||
|
* 16 bit number, there is a 1/65536 ( = 0.0015 % ) chance that it will
|
||||||
|
* match and we will drop something that should be passed along.
|
||||||
|
*
|
||||||
|
* Looking at it another way, there is a 0.9999847412109375 (out of 1)
|
||||||
|
* probability of doing the right thing.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This can be used when we want to calculate a single CRC over disjoint data.
|
* This can be used when we want to calculate a single CRC over disjoint data.
|
||||||
*
|
*
|
||||||
|
|
614
kiss.c
614
kiss.c
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2011, 2013, 2014, 2016 John Langner, WB2OSZ
|
// Copyright (C) 2011, 2013, 2014, 2016, 2017 John Langner, WB2OSZ
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -24,12 +24,8 @@
|
||||||
* Module: kiss.c
|
* Module: kiss.c
|
||||||
*
|
*
|
||||||
* Purpose: Act as a virtual KISS TNC for use by other packet radio applications.
|
* Purpose: Act as a virtual KISS TNC for use by other packet radio applications.
|
||||||
* On Windows, it is a serial port. On Linux, a pseudo terminal.
|
* This file implements it with a pseudo terminal for Linux only.
|
||||||
*
|
*
|
||||||
* Input:
|
|
||||||
*
|
|
||||||
* Outputs:
|
|
||||||
*
|
|
||||||
* Description: It implements the KISS TNC protocol as described in:
|
* Description: It implements the KISS TNC protocol as described in:
|
||||||
* http://www.ka9q.net/papers/kiss.html
|
* http://www.ka9q.net/papers/kiss.html
|
||||||
*
|
*
|
||||||
|
@ -49,94 +45,82 @@
|
||||||
*
|
*
|
||||||
* Commands from application recognized:
|
* Commands from application recognized:
|
||||||
*
|
*
|
||||||
* 0 Data Frame AX.25 frame in raw format.
|
* _0 Data Frame AX.25 frame in raw format.
|
||||||
*
|
*
|
||||||
* 1 TXDELAY See explanation in xmit.c.
|
* _1 TXDELAY See explanation in xmit.c.
|
||||||
*
|
*
|
||||||
* 2 Persistence " "
|
* _2 Persistence " "
|
||||||
*
|
*
|
||||||
* 3 SlotTime " "
|
* _3 SlotTime " "
|
||||||
*
|
*
|
||||||
* 4 TXtail " "
|
* _4 TXtail " "
|
||||||
* Spec says it is obsolete but Xastir
|
* Spec says it is obsolete but Xastir
|
||||||
* sends it and we respect it.
|
* sends it and we respect it.
|
||||||
*
|
*
|
||||||
* 5 FullDuplex Ignored. Always full duplex.
|
* _5 FullDuplex Ignored.
|
||||||
*
|
*
|
||||||
* 6 SetHardware TNC specific. Ignored.
|
* _6 SetHardware TNC specific.
|
||||||
*
|
*
|
||||||
* FF Return Exit KISS mode. Ignored.
|
* FF Return Exit KISS mode. Ignored.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Messages sent to client application:
|
* Messages sent to client application:
|
||||||
*
|
*
|
||||||
* 0 Data Frame Received AX.25 frame in raw format.
|
* _0 Data Frame Received AX.25 frame in raw format.
|
||||||
*
|
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Platform differences:
|
* Platform differences:
|
||||||
*
|
*
|
||||||
* We can use a pseudo terminal for Linux or Cygwin applications.
|
|
||||||
* However, Microsoft Windows doesn't seem to have similar functionality.
|
|
||||||
* Native Windows applications expect to see a device named COM1,
|
|
||||||
* COM2, COM3, or COM4. Some might offer more flexibility but others
|
|
||||||
* might be limited to these four choices.
|
|
||||||
*
|
|
||||||
* The documentation instucts the user to install the com0com
|
|
||||||
* "Null-modem emulator" from http://sourceforge.net/projects/com0com/
|
|
||||||
* and configure it for COM3 & COM4.
|
|
||||||
*
|
|
||||||
* By default Dire Wolf will use COM3 (/dev/ttyS2 or /dev/com3 - lower case!)
|
|
||||||
* and the client application will use COM4 (available as /dev/ttyS or
|
|
||||||
* /dev/com4 for Cygwin applications).
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This can get confusing.
|
|
||||||
*
|
|
||||||
* If __WIN32__ is defined,
|
|
||||||
* We use the Windows interface to the specfied serial port.
|
|
||||||
* This could be a real serial port or the nullmodem driver
|
|
||||||
* connected to another application.
|
|
||||||
*
|
|
||||||
* If __CYGWIN__ is defined,
|
|
||||||
* We connect to a serial port as in the previous case but
|
|
||||||
* use the Linux I/O interface.
|
|
||||||
* We also supply a pseudo terminal for any Cygwin applications
|
|
||||||
* such as Xastir so the null modem is not needed.
|
|
||||||
*
|
|
||||||
* For the Linux case,
|
* For the Linux case,
|
||||||
* We supply a pseudo terminal for use by other applications.
|
* We supply a pseudo terminal for use by other applications.
|
||||||
*
|
*
|
||||||
*
|
* Version 1.5: Split serial port version off into its own file.
|
||||||
* Reference: http://www.robbayer.com/files/serial-win.pdf
|
|
||||||
*
|
*
|
||||||
*---------------------------------------------------------------*/
|
*---------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
#if __WIN32__ // Stub for Windows.
|
||||||
|
|
||||||
|
#include "direwolf.h"
|
||||||
|
#include "kiss.h"
|
||||||
|
|
||||||
|
void kisspt_init (struct misc_config_s *mc)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void kisspt_set_debug (int n)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void kisspt_send_rec_packet (int chan, unsigned char *fbuf, int flen, int client)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#else // Rest of file is for Linux only.
|
||||||
|
|
||||||
|
|
||||||
#include "direwolf.h"
|
#include "direwolf.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#if __WIN32__
|
|
||||||
#include <stdlib.h>
|
|
||||||
#else
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
#ifdef __OpenBSD__
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#else
|
#else
|
||||||
#include <sys/errno.h>
|
#include <sys/errno.h>
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
|
|
||||||
#include "tq.h"
|
#include "tq.h"
|
||||||
#include "ax25_pad.h"
|
#include "ax25_pad.h"
|
||||||
|
@ -146,29 +130,21 @@
|
||||||
#include "xmit.h"
|
#include "xmit.h"
|
||||||
|
|
||||||
|
|
||||||
#if __WIN32__
|
/*
|
||||||
typedef HANDLE MYFDTYPE;
|
* Accumulated KISS frame and state of decoder.
|
||||||
#define MYFDERROR INVALID_HANDLE_VALUE
|
*/
|
||||||
#else
|
|
||||||
typedef int MYFDTYPE;
|
|
||||||
#define MYFDERROR (-1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
static kiss_frame_t kf;
|
||||||
static kiss_frame_t kf; /* Accumulated KISS frame and state of decoder. */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are for a Linux/Cygwin pseudo terminal.
|
* These are for a Linux pseudo terminal.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if ! __WIN32__
|
static int pt_master_fd = -1; /* File descriptor for my end. */
|
||||||
|
|
||||||
static MYFDTYPE pt_master_fd = MYFDERROR; /* File descriptor for my end. */
|
|
||||||
|
|
||||||
static char pt_slave_name[32]; /* Pseudo terminal slave name */
|
|
||||||
/* like /dev/pts/999 */
|
|
||||||
|
|
||||||
|
static char pt_slave_name[32]; /* Pseudo terminal slave name */
|
||||||
|
/* like /dev/pts/999 */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -177,40 +153,15 @@ static char pt_slave_name[32]; /* Pseudo terminal slave name */
|
||||||
|
|
||||||
#define TMP_KISSTNC_SYMLINK "/tmp/kisstnc"
|
#define TMP_KISSTNC_SYMLINK "/tmp/kisstnc"
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
static void * kisspt_listen_thread (void *arg);
|
||||||
* This is for native Windows applications and a virtual null modem.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if __CYGWIN__ || __WIN32__
|
|
||||||
|
|
||||||
static MYFDTYPE nullmodem_fd = MYFDERROR;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: define in one place, use everywhere.
|
static int kisspt_debug = 0; /* Print information flowing from and to client. */
|
||||||
#if __WIN32__
|
|
||||||
#define THREAD_F unsigned __stdcall
|
|
||||||
#else
|
|
||||||
#define THREAD_F void *
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static THREAD_F kiss_listen_thread (void *arg);
|
void kisspt_set_debug (int n)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if DEBUG9
|
|
||||||
static FILE *log_fp;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static int kiss_debug = 0; /* Print information flowing from and to client. */
|
|
||||||
|
|
||||||
void kiss_serial_set_debug (int n)
|
|
||||||
{
|
{
|
||||||
kiss_debug = n;
|
kisspt_debug = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -224,12 +175,12 @@ void hex_dump (unsigned char *p, int len);
|
||||||
|
|
||||||
/*-------------------------------------------------------------------
|
/*-------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Name: kiss_init
|
* Name: kisspt_init
|
||||||
*
|
*
|
||||||
* Purpose: Set up a pseudo terminal acting as a virtual KISS TNC.
|
* Purpose: Set up a pseudo terminal acting as a virtual KISS TNC.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Inputs: mc->nullmodem - name of device for our end of nullmodem.
|
* Inputs:
|
||||||
*
|
*
|
||||||
* Outputs:
|
* Outputs:
|
||||||
*
|
*
|
||||||
|
@ -240,43 +191,28 @@ void hex_dump (unsigned char *p, int len);
|
||||||
*
|
*
|
||||||
*--------------------------------------------------------------------*/
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
#if __WIN32__
|
static int kisspt_open_pt (void);
|
||||||
static MYFDTYPE kiss_open_nullmodem (char *device);
|
|
||||||
#else
|
|
||||||
static MYFDTYPE kiss_open_pt (void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void kiss_init (struct misc_config_s *mc)
|
void kisspt_init (struct misc_config_s *mc)
|
||||||
{
|
{
|
||||||
|
|
||||||
#if __WIN32__
|
|
||||||
HANDLE kiss_nullmodem_listen_th;
|
|
||||||
#else
|
|
||||||
pthread_t kiss_pterm_listen_tid;
|
pthread_t kiss_pterm_listen_tid;
|
||||||
//pthread_t kiss_nullmodem_listen_tid;
|
|
||||||
int e;
|
int e;
|
||||||
#endif
|
|
||||||
|
|
||||||
memset (&kf, 0, sizeof(kf));
|
memset (&kf, 0, sizeof(kf));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This reads messages from client.
|
* This reads messages from client.
|
||||||
*/
|
*/
|
||||||
|
pt_master_fd = -1;
|
||||||
#if ! __WIN32__
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Pseudo terminal for Cygwin and Linux versions.
|
|
||||||
*/
|
|
||||||
pt_master_fd = MYFDERROR;
|
|
||||||
|
|
||||||
if (mc->enable_kiss_pt) {
|
if (mc->enable_kiss_pt) {
|
||||||
|
|
||||||
pt_master_fd = kiss_open_pt ();
|
pt_master_fd = kisspt_open_pt ();
|
||||||
|
|
||||||
if (pt_master_fd != MYFDERROR) {
|
if (pt_master_fd != -1) {
|
||||||
e = pthread_create (&kiss_pterm_listen_tid, (pthread_attr_t*)NULL, kiss_listen_thread, NULL);
|
e = pthread_create (&kiss_pterm_listen_tid, (pthread_attr_t*)NULL, kisspt_listen_thread, NULL);
|
||||||
if (e != 0) {
|
if (e != 0) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
perror("Could not create kiss listening thread for Linux pseudo terminal");
|
perror("Could not create kiss listening thread for Linux pseudo terminal");
|
||||||
|
@ -287,72 +223,22 @@ void kiss_init (struct misc_config_s *mc)
|
||||||
text_color_set(DW_COLOR_INFO);
|
text_color_set(DW_COLOR_INFO);
|
||||||
dw_printf ("Use -p command line option to enable KISS pseudo terminal.\n");
|
dw_printf ("Use -p command line option to enable KISS pseudo terminal.\n");
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if __CYGWIN__ || __WIN32
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Cygwin and native Windows versions have serial port connection.
|
|
||||||
*/
|
|
||||||
if (strlen(mc->nullmodem) > 0) {
|
|
||||||
|
|
||||||
#if ! __WIN32__
|
|
||||||
|
|
||||||
/* Translate Windows device name into Linux name. */
|
|
||||||
/* COM1 -> /dev/ttyS0, etc. */
|
|
||||||
|
|
||||||
if (strncasecmp(mc->nullmodem, "COM", 3) == 0) {
|
|
||||||
int n = atoi (mc->nullmodem + 3);
|
|
||||||
text_color_set(DW_COLOR_INFO);
|
|
||||||
dw_printf ("Converted nullmodem device '%s'", mc->nullmodem);
|
|
||||||
if (n < 1) n = 1;
|
|
||||||
snprintf (mc->nullmodem, sizeof(mc->nullmodem), "/dev/ttyS%d", n-1);
|
|
||||||
dw_printf (" to Linux equivalent '%s'\n", mc->nullmodem);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
nullmodem_fd = kiss_open_nullmodem (mc->nullmodem);
|
|
||||||
|
|
||||||
if (nullmodem_fd != MYFDERROR) {
|
|
||||||
#if __WIN32__
|
|
||||||
kiss_nullmodem_listen_th = (HANDLE)_beginthreadex (NULL, 0, kiss_listen_thread, NULL, 0, NULL);
|
|
||||||
if (kiss_nullmodem_listen_th == NULL) {
|
|
||||||
text_color_set(DW_COLOR_ERROR);
|
|
||||||
dw_printf ("Could not create kiss nullmodem thread\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
e = pthread_create (&kiss_nullmodem_listen_tid, NULL, kiss_listen_thread, NULL);
|
|
||||||
if (e != 0) {
|
|
||||||
text_color_set(DW_COLOR_ERROR);
|
|
||||||
perror("Could not create kiss listening thread for Windows virtual COM port.");
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
text_color_set (DW_COLOR_DEBUG);
|
text_color_set (DW_COLOR_DEBUG);
|
||||||
#if ! __WIN32__
|
|
||||||
dw_printf ("end of kiss_init: pt_master_fd = %d\n", pt_master_fd);
|
dw_printf ("end of kisspt_init: pt_master_fd = %d\n", pt_master_fd);
|
||||||
#endif
|
|
||||||
#if __CYGWIN__ || __WIN32__
|
|
||||||
dw_printf ("end of kiss_init: nullmodem_fd = %d\n", nullmodem_fd);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns fd for master side of pseudo terminal or MYFDERROR for error.
|
* Returns fd for master side of pseudo terminal or -1 for error.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if ! __WIN32__
|
static int kisspt_open_pt (void)
|
||||||
|
|
||||||
static MYFDTYPE kiss_open_pt (void)
|
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
char *pts;
|
char *pts;
|
||||||
|
@ -362,19 +248,18 @@ static MYFDTYPE kiss_open_pt (void)
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
dw_printf ("kiss_open_pt ( )\n");
|
dw_printf ("kisspt_open_pt ( )\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
fd = posix_openpt(O_RDWR|O_NOCTTY);
|
fd = posix_openpt(O_RDWR|O_NOCTTY);
|
||||||
|
|
||||||
if (fd == MYFDERROR
|
if (fd == -1
|
||||||
|| grantpt (fd) == MYFDERROR
|
|| grantpt (fd) == -1
|
||||||
|| unlockpt (fd) == MYFDERROR
|
|| unlockpt (fd) == -1
|
||||||
|| (pts = ptsname (fd)) == NULL) {
|
|| (pts = ptsname (fd)) == NULL) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("ERROR - Could not create pseudo terminal for KISS TNC.\n");
|
dw_printf ("ERROR - Could not create pseudo terminal for KISS TNC.\n");
|
||||||
return (MYFDERROR);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
strlcpy (pt_slave_name, pts, sizeof(pt_slave_name));
|
strlcpy (pt_slave_name, pts, sizeof(pt_slave_name));
|
||||||
|
@ -430,11 +315,11 @@ static MYFDTYPE kiss_open_pt (void)
|
||||||
#if 1
|
#if 1
|
||||||
// Sample code shows this. Why would we open it here?
|
// Sample code shows this. Why would we open it here?
|
||||||
// On Ubuntu, the slave side disappears after a few
|
// On Ubuntu, the slave side disappears after a few
|
||||||
// seconds if no one opens it. Same on Raspian which
|
// seconds if no one opens it. Same on Raspbian which
|
||||||
// is also based on Debian.
|
// is also based on Debian.
|
||||||
// Need to revisit this.
|
// Need to revisit this.
|
||||||
|
|
||||||
MYFDTYPE pt_slave_fd;
|
int pt_slave_fd;
|
||||||
|
|
||||||
pt_slave_fd = open(pt_slave_name, O_RDWR|O_NOCTTY);
|
pt_slave_fd = open(pt_slave_name, O_RDWR|O_NOCTTY);
|
||||||
|
|
||||||
|
@ -442,7 +327,7 @@ static MYFDTYPE kiss_open_pt (void)
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("Can't open %s\n", pt_slave_name);
|
dw_printf ("Can't open %s\n", pt_slave_name);
|
||||||
perror ("");
|
perror ("");
|
||||||
return MYFDERROR;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -471,149 +356,11 @@ static MYFDTYPE kiss_open_pt (void)
|
||||||
return (fd);
|
return (fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns fd for our side of null modem or MYFDERROR for error.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#if __CYGWIN__ || __WIN32__
|
|
||||||
|
|
||||||
static MYFDTYPE kiss_open_nullmodem (char *devicename)
|
|
||||||
{
|
|
||||||
|
|
||||||
#if __WIN32__
|
|
||||||
|
|
||||||
MYFDTYPE fd;
|
|
||||||
DCB dcb;
|
|
||||||
int ok;
|
|
||||||
char bettername[50];
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
|
||||||
dw_printf ("kiss_open_nullmodem ( '%s' )\n", devicename);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if DEBUG9
|
|
||||||
log_fp = fopen ("kiss-debug.txt", "w");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Need to use FILE_FLAG_OVERLAPPED for full duplex operation.
|
|
||||||
// Without it, write blocks when waiting on read.
|
|
||||||
|
|
||||||
// Read http://support.microsoft.com/kb/156932
|
|
||||||
|
|
||||||
// Bug fix in release 1.1 - Need to munge name for COM10 and up.
|
|
||||||
// http://support.microsoft.com/kb/115831
|
|
||||||
|
|
||||||
strlcpy (bettername, devicename, sizeof(bettername));
|
|
||||||
if (strncasecmp(devicename, "COM", 3) == 0) {
|
|
||||||
int n;
|
|
||||||
n = atoi(devicename+3);
|
|
||||||
if (n >= 10) {
|
|
||||||
strlcpy (bettername, "\\\\.\\", sizeof(bettername));
|
|
||||||
strlcat (bettername, devicename, sizeof(bettername));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = CreateFile(bettername, GENERIC_READ | GENERIC_WRITE,
|
|
||||||
0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
|
||||||
|
|
||||||
if (fd == MYFDERROR) {
|
|
||||||
text_color_set(DW_COLOR_ERROR);
|
|
||||||
dw_printf ("ERROR - Could not connect to %s side of null modem for Windows KISS TNC.\n", devicename);
|
|
||||||
return (MYFDERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363201(v=vs.85).aspx */
|
|
||||||
|
|
||||||
memset (&dcb, 0, sizeof(dcb));
|
|
||||||
dcb.DCBlength = sizeof(DCB);
|
|
||||||
|
|
||||||
ok = GetCommState (fd, &dcb);
|
|
||||||
if (! ok) {
|
|
||||||
text_color_set(DW_COLOR_ERROR);
|
|
||||||
dw_printf ("kiss_open_nullmodem: GetCommState failed.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa363214(v=vs.85).aspx */
|
|
||||||
|
|
||||||
dcb.DCBlength = sizeof(DCB);
|
|
||||||
dcb.BaudRate = CBR_9600; // shouldn't matter
|
|
||||||
dcb.fBinary = 1;
|
|
||||||
dcb.fParity = 0;
|
|
||||||
dcb.fOutxCtsFlow = 0;
|
|
||||||
dcb.fOutxDsrFlow = 0;
|
|
||||||
dcb.fDtrControl = 0;
|
|
||||||
dcb.fDsrSensitivity = 0;
|
|
||||||
dcb.fOutX = 0;
|
|
||||||
dcb.fInX = 0;
|
|
||||||
dcb.fErrorChar = 0;
|
|
||||||
dcb.fNull = 0; /* Don't drop nul characters! */
|
|
||||||
dcb.fRtsControl = 0;
|
|
||||||
dcb.ByteSize = 8;
|
|
||||||
dcb.Parity = NOPARITY;
|
|
||||||
dcb.StopBits = ONESTOPBIT;
|
|
||||||
|
|
||||||
ok = SetCommState (fd, &dcb);
|
|
||||||
if (! ok) {
|
|
||||||
text_color_set(DW_COLOR_ERROR);
|
|
||||||
dw_printf ("kiss_open_nullmodem: SetCommState failed.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
text_color_set(DW_COLOR_INFO);
|
|
||||||
dw_printf("Virtual KISS TNC is connected to %s side of null modem.\n", devicename);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* Cygwin version. */
|
|
||||||
|
|
||||||
int fd;
|
|
||||||
struct termios ts;
|
|
||||||
int e;
|
|
||||||
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
|
||||||
dw_printf ("kiss_open_nullmodem ( '%s' )\n", devicename);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fd = open (devicename, O_RDWR);
|
|
||||||
|
|
||||||
if (fd == MYFDERROR) {
|
|
||||||
text_color_set(DW_COLOR_ERROR);
|
|
||||||
dw_printf ("ERROR - Could not connect to %s side of null modem for Windows KISS TNC.\n", devicename);
|
|
||||||
return (MYFDERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
e = tcgetattr (fd, &ts);
|
|
||||||
if (e != 0) { perror ("nm tcgetattr"); }
|
|
||||||
|
|
||||||
cfmakeraw (&ts);
|
|
||||||
|
|
||||||
ts.c_cc[VMIN] = 1; /* wait for at least one character */
|
|
||||||
ts.c_cc[VTIME] = 0; /* no fancy timing. */
|
|
||||||
|
|
||||||
e = tcsetattr (fd, TCSANOW, &ts);
|
|
||||||
if (e != 0) { perror ("nm tcsetattr"); }
|
|
||||||
|
|
||||||
text_color_set(DW_COLOR_INFO);
|
|
||||||
dw_printf("Virtual KISS TNC is connected to %s side of null modem.\n", devicename);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return (fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------
|
/*-------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Name: kiss_send_rec_packet
|
* Name: kisspt_send_rec_packet
|
||||||
*
|
*
|
||||||
* Purpose: Send a received packet or text string to the client app.
|
* Purpose: Send a received packet or text string to the client app.
|
||||||
*
|
*
|
||||||
|
@ -628,6 +375,10 @@ static MYFDTYPE kiss_open_nullmodem (char *devicename)
|
||||||
* flen - Length of raw received frame not including the FCS
|
* flen - Length of raw received frame not including the FCS
|
||||||
* or -1 for a text string.
|
* or -1 for a text string.
|
||||||
*
|
*
|
||||||
|
* client - Not used for pseudo terminal.
|
||||||
|
* Here so that 3 related functions all have
|
||||||
|
* the same parameter list.
|
||||||
|
*
|
||||||
* Description: Send message to client.
|
* Description: Send message to client.
|
||||||
* We really don't care if anyone is listening or not.
|
* We really don't care if anyone is listening or not.
|
||||||
* I don't even know if we can find out.
|
* I don't even know if we can find out.
|
||||||
|
@ -635,28 +386,20 @@ static MYFDTYPE kiss_open_nullmodem (char *devicename)
|
||||||
*--------------------------------------------------------------------*/
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
void kiss_send_rec_packet (int chan, unsigned char *fbuf, int flen)
|
void kisspt_send_rec_packet (int chan, unsigned char *fbuf, int flen, int client)
|
||||||
{
|
{
|
||||||
unsigned char kiss_buff[2 * AX25_MAX_PACKET_LEN + 2];
|
unsigned char kiss_buff[2 * AX25_MAX_PACKET_LEN + 2];
|
||||||
int kiss_len;
|
int kiss_len;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
#if ! __WIN32__
|
|
||||||
if (pt_master_fd == MYFDERROR) {
|
if (pt_master_fd == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if __CYGWIN__ || __WIN32__
|
|
||||||
|
|
||||||
if (nullmodem_fd == MYFDERROR) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (flen < 0) {
|
if (flen < 0) {
|
||||||
flen = strlen((char*)fbuf);
|
flen = strlen((char*)fbuf);
|
||||||
if (kiss_debug) {
|
if (kisspt_debug) {
|
||||||
kiss_debug_print (TO_CLIENT, "Fake command prompt", fbuf, flen);
|
kiss_debug_print (TO_CLIENT, "Fake command prompt", fbuf, flen);
|
||||||
}
|
}
|
||||||
strlcpy ((char *)kiss_buff, (char *)fbuf, sizeof(kiss_buff));
|
strlcpy ((char *)kiss_buff, (char *)fbuf, sizeof(kiss_buff));
|
||||||
|
@ -664,15 +407,18 @@ void kiss_send_rec_packet (int chan, unsigned char *fbuf, int flen)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
|
|
||||||
unsigned char stemp[AX25_MAX_PACKET_LEN + 1];
|
unsigned char stemp[AX25_MAX_PACKET_LEN + 1];
|
||||||
|
|
||||||
assert (flen < (int)(sizeof(stemp)));
|
if (flen > (int)(sizeof(stemp)) - 1) {
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf ("\nPseudo Terminal KISS buffer too small. Truncated.\n\n");
|
||||||
|
flen = (int)(sizeof(stemp)) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
stemp[0] = (chan << 4) + 0;
|
stemp[0] = (chan << 4) + 0;
|
||||||
memcpy (stemp+1, fbuf, flen);
|
memcpy (stemp+1, fbuf, flen);
|
||||||
|
|
||||||
if (kiss_debug >= 2) {
|
if (kisspt_debug >= 2) {
|
||||||
/* AX.25 frame with the CRC removed. */
|
/* AX.25 frame with the CRC removed. */
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
dw_printf ("\n");
|
dw_printf ("\n");
|
||||||
|
@ -684,16 +430,12 @@ void kiss_send_rec_packet (int chan, unsigned char *fbuf, int flen)
|
||||||
|
|
||||||
/* This has KISS framing and escapes for sending to client app. */
|
/* This has KISS framing and escapes for sending to client app. */
|
||||||
|
|
||||||
if (kiss_debug) {
|
if (kisspt_debug) {
|
||||||
kiss_debug_print (TO_CLIENT, NULL, kiss_buff, kiss_len);
|
kiss_debug_print (TO_CLIENT, NULL, kiss_buff, kiss_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ! __WIN32__
|
|
||||||
|
|
||||||
/* Pseudo terminal for Cygwin and Linux. */
|
|
||||||
|
|
||||||
err = write (pt_master_fd, kiss_buff, (size_t)kiss_len);
|
err = write (pt_master_fd, kiss_buff, (size_t)kiss_len);
|
||||||
|
|
||||||
if (err == -1 && errno == EWOULDBLOCK) {
|
if (err == -1 && errno == EWOULDBLOCK) {
|
||||||
|
@ -709,84 +451,18 @@ void kiss_send_rec_packet (int chan, unsigned char *fbuf, int flen)
|
||||||
perror ("pt write");
|
perror ("pt write");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
} /* kisspt_send_rec_packet */
|
||||||
|
|
||||||
#if __CYGWIN__ || __WIN32__
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This write can block if nothing is connected to the other end.
|
|
||||||
* The solution is found in the com0com ReadMe file:
|
|
||||||
*
|
|
||||||
* Q. My application hangs during its startup when it sends anything to one paired
|
|
||||||
* COM port. The only way to unhang it is to start HyperTerminal, which is connected
|
|
||||||
* to the other paired COM port. I didn't have this problem with physical serial
|
|
||||||
* ports.
|
|
||||||
* A. Your application can hang because receive buffer overrun is disabled by
|
|
||||||
* default. You can fix the problem by enabling receive buffer overrun for the
|
|
||||||
* receiving port. Also, to prevent some flow control issues you need to enable
|
|
||||||
* baud rate emulation for the sending port. So, if your application use port CNCA0
|
|
||||||
* and other paired port is CNCB0, then:
|
|
||||||
*
|
|
||||||
* 1. Launch the Setup Command Prompt shortcut.
|
|
||||||
* 2. Enter the change commands, for example:
|
|
||||||
*
|
|
||||||
* command> change CNCB0 EmuOverrun=yes
|
|
||||||
* command> change CNCA0 EmuBR=yes
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if __WIN32__
|
|
||||||
|
|
||||||
DWORD nwritten;
|
|
||||||
|
|
||||||
/* Without this, write blocks while we are waiting on a read. */
|
|
||||||
static OVERLAPPED ov_wr;
|
|
||||||
memset (&ov_wr, 0, sizeof(ov_wr));
|
|
||||||
|
|
||||||
if ( ! WriteFile (nullmodem_fd, kiss_buff, kiss_len, &nwritten, &ov_wr))
|
|
||||||
{
|
|
||||||
err = GetLastError();
|
|
||||||
if (err != ERROR_IO_PENDING)
|
|
||||||
{
|
|
||||||
text_color_set(DW_COLOR_ERROR);
|
|
||||||
dw_printf ("\nError sending KISS message to client application thru null modem. Error %d.\n\n", (int)GetLastError());
|
|
||||||
//CloseHandle (nullmodem_fd);
|
|
||||||
//nullmodem_fd = MYFDERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((int)nwritten != kiss_len)
|
|
||||||
{
|
|
||||||
text_color_set(DW_COLOR_ERROR);
|
|
||||||
dw_printf ("\nError sending KISS message to client application thru null modem. Only %d of %d written.\n\n", (int)nwritten, kiss_len);
|
|
||||||
//CloseHandle (nullmodem_fd);
|
|
||||||
//nullmodem_fd = MYFDERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
err = write (nullmodem_fd, kiss_buf, (size_t)kiss_len);
|
|
||||||
if (err != len)
|
|
||||||
{
|
|
||||||
text_color_set(DW_COLOR_ERROR);
|
|
||||||
dw_printf ("\nError sending KISS message to client application thru null modem. err=%d\n\n", err);
|
|
||||||
//close (nullmodem_fd);
|
|
||||||
//nullmodem_fd = MYFDERROR;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} /* kiss_send_rec_packet */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------
|
/*-------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Name: kiss_get
|
* Name: kisspt_get
|
||||||
*
|
*
|
||||||
* Purpose: Read one byte from the KISS client app.
|
* Purpose: Read one byte from the KISS client app.
|
||||||
*
|
*
|
||||||
* Global In: nullmodem_fd (Windows) or pt_master_fd (Linux)
|
* Global In: pt_master_fd
|
||||||
*
|
*
|
||||||
* Returns: one byte (value 0 - 255) or terminate thread on error.
|
* Returns: one byte (value 0 - 255) or terminate thread on error.
|
||||||
*
|
*
|
||||||
|
@ -799,78 +475,10 @@ void kiss_send_rec_packet (int chan, unsigned char *fbuf, int flen)
|
||||||
*--------------------------------------------------------------------*/
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
static int kiss_get (/* MYFDTYPE fd*/ void )
|
static int kisspt_get (void)
|
||||||
{
|
{
|
||||||
unsigned char ch;
|
unsigned char ch;
|
||||||
|
|
||||||
#if __WIN32__ /* Native Windows version. */
|
|
||||||
|
|
||||||
DWORD n;
|
|
||||||
static OVERLAPPED ov_rd;
|
|
||||||
|
|
||||||
memset (&ov_rd, 0, sizeof(ov_rd));
|
|
||||||
ov_rd.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
|
|
||||||
|
|
||||||
|
|
||||||
/* Overlapped I/O makes reading rather complicated. */
|
|
||||||
/* See: http://msdn.microsoft.com/en-us/library/ms810467.aspx */
|
|
||||||
|
|
||||||
/* It seems that the read completes OK with a count */
|
|
||||||
/* of 0 every time we send a message to the serial port. */
|
|
||||||
|
|
||||||
n = 0; /* Number of characters read. */
|
|
||||||
|
|
||||||
while (n == 0) {
|
|
||||||
|
|
||||||
if ( ! ReadFile (nullmodem_fd, &ch, 1, &n, &ov_rd))
|
|
||||||
{
|
|
||||||
int err1 = GetLastError();
|
|
||||||
|
|
||||||
if (err1 == ERROR_IO_PENDING)
|
|
||||||
{
|
|
||||||
/* Wait for completion. */
|
|
||||||
|
|
||||||
if (WaitForSingleObject (ov_rd.hEvent, INFINITE) == WAIT_OBJECT_0)
|
|
||||||
{
|
|
||||||
if ( ! GetOverlappedResult (nullmodem_fd, &ov_rd, &n, 1))
|
|
||||||
{
|
|
||||||
int err3 = GetLastError();
|
|
||||||
|
|
||||||
text_color_set(DW_COLOR_ERROR);
|
|
||||||
dw_printf ("\nKISS GetOverlappedResult error %d.\n\n", err3);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Success! n should be 1 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
text_color_set(DW_COLOR_ERROR);
|
|
||||||
dw_printf ("\nKISS ReadFile error %d. Closing connection.\n\n", err1);
|
|
||||||
CloseHandle (nullmodem_fd);
|
|
||||||
nullmodem_fd = MYFDERROR;
|
|
||||||
//pthread_exit (NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* end while n==0 */
|
|
||||||
|
|
||||||
CloseHandle(ov_rd.hEvent);
|
|
||||||
|
|
||||||
if (n != 1) {
|
|
||||||
text_color_set(DW_COLOR_ERROR);
|
|
||||||
dw_printf ("\nKISS failed to get one byte. n=%d.\n\n", (int)n);
|
|
||||||
|
|
||||||
#if DEBUG9
|
|
||||||
fprintf (log_fp, "n=%d\n", n);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#else /* Linux/Cygwin version */
|
|
||||||
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
fd_set fd_in, fd_ex;
|
fd_set fd_in, fd_ex;
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -934,7 +542,7 @@ static int kiss_get (/* MYFDTYPE fd*/ void )
|
||||||
continue; // When could we get a 0?
|
continue; // When could we get a 0?
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc == MYFDERROR
|
if (rc == -1
|
||||||
|| (n = read(pt_master_fd, &ch, (size_t)1)) != 1)
|
|| (n = read(pt_master_fd, &ch, (size_t)1)) != 1)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -944,70 +552,52 @@ static int kiss_get (/* MYFDTYPE fd*/ void )
|
||||||
|
|
||||||
close (pt_master_fd);
|
close (pt_master_fd);
|
||||||
|
|
||||||
pt_master_fd = MYFDERROR;
|
pt_master_fd = -1;
|
||||||
unlink (TMP_KISSTNC_SYMLINK);
|
unlink (TMP_KISSTNC_SYMLINK);
|
||||||
pthread_exit (NULL);
|
pthread_exit (NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if DEBUGx
|
#if DEBUGx
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
dw_printf ("kiss_get(%d) returns 0x%02x\n", fd, ch);
|
dw_printf ("kisspt_get(%d) returns 0x%02x\n", fd, ch);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DEBUG9
|
|
||||||
fprintf (log_fp, "%02x %c %c", ch,
|
|
||||||
isprint(ch) ? ch : '.' ,
|
|
||||||
(isupper(ch>>1) || isdigit(ch>>1) || (ch>>1) == ' ') ? (ch>>1) : '.');
|
|
||||||
if (ch == FEND) fprintf (log_fp, " FEND");
|
|
||||||
if (ch == FESC) fprintf (log_fp, " FESC");
|
|
||||||
if (ch == TFEND) fprintf (log_fp, " TFEND");
|
|
||||||
if (ch == TFESC) fprintf (log_fp, " TFESC");
|
|
||||||
if (ch == '\r') fprintf (log_fp, " CR");
|
|
||||||
if (ch == '\n') fprintf (log_fp, " LF");
|
|
||||||
fprintf (log_fp, "\n");
|
|
||||||
if (ch == FEND) fflush (log_fp);
|
|
||||||
#endif
|
|
||||||
return (ch);
|
return (ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------
|
/*-------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Name: kiss_listen_thread
|
* Name: kisspt_listen_thread
|
||||||
*
|
*
|
||||||
* Purpose: Read messages from serial port KISS client application.
|
* Purpose: Read messages from serial port KISS client application.
|
||||||
*
|
*
|
||||||
* Global In: nullmodem_fd (Windows) or pt_master_fd (Linux)
|
* Global In:
|
||||||
*
|
*
|
||||||
* Description: Reads bytes from the KISS client app and
|
* Description: Reads bytes from the KISS client app and
|
||||||
* sends them to kiss_rec_byte for processing.
|
* sends them to kiss_rec_byte for processing.
|
||||||
*
|
*
|
||||||
*--------------------------------------------------------------------*/
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void * kisspt_listen_thread (void *arg)
|
||||||
static THREAD_F kiss_listen_thread (void *arg)
|
|
||||||
{
|
{
|
||||||
unsigned char ch;
|
unsigned char ch;
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
dw_printf ("kiss_listen_thread ( %d )\n", fd);
|
dw_printf ("kisspt_listen_thread ( %d )\n", fd);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
ch = kiss_get();
|
ch = kisspt_get();
|
||||||
kiss_rec_byte (&kf, ch, kiss_debug, kiss_send_rec_packet);
|
kiss_rec_byte (&kf, ch, kisspt_debug, -1, kisspt_send_rec_packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __WIN32__
|
return (void *) 0; /* Unreachable but avoids compiler warning. */
|
||||||
return(0);
|
|
||||||
#else
|
|
||||||
return (THREAD_F) 0; /* Unreachable but avoids compiler warning. */
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // Linux version
|
||||||
|
|
||||||
/* end kiss.c */
|
/* end kiss.c */
|
||||||
|
|
8
kiss.h
8
kiss.h
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Name: kiss.h
|
* Name: kiss.h
|
||||||
|
*
|
||||||
|
* This is for the pseudo terminal KISS interface.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,11 +13,11 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void kiss_init (struct misc_config_s *misc_config);
|
void kisspt_init (struct misc_config_s *misc_config);
|
||||||
|
|
||||||
void kiss_send_rec_packet (int chan, unsigned char *fbuf, int flen);
|
void kisspt_send_rec_packet (int chan, unsigned char *fbuf, int flen, int client);
|
||||||
|
|
||||||
void kiss_serial_set_debug (int n);
|
void kisspt_set_debug (int n);
|
||||||
|
|
||||||
|
|
||||||
/* end kiss.h */
|
/* end kiss.h */
|
||||||
|
|
86
kiss_frame.c
86
kiss_frame.c
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2013, 2014 John Langner, WB2OSZ
|
// Copyright (C) 2013, 2014, 2017 John Langner, WB2OSZ
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -43,28 +43,28 @@
|
||||||
*
|
*
|
||||||
* Commands from application recognized:
|
* Commands from application recognized:
|
||||||
*
|
*
|
||||||
* 0 Data Frame AX.25 frame in raw format.
|
* _0 Data Frame AX.25 frame in raw format.
|
||||||
*
|
*
|
||||||
* 1 TXDELAY See explanation in xmit.c.
|
* _1 TXDELAY See explanation in xmit.c.
|
||||||
*
|
*
|
||||||
* 2 Persistence " "
|
* _2 Persistence " "
|
||||||
*
|
*
|
||||||
* 3 SlotTime " "
|
* _3 SlotTime " "
|
||||||
*
|
*
|
||||||
* 4 TXtail " "
|
* _4 TXtail " "
|
||||||
* Spec says it is obsolete but Xastir
|
* Spec says it is obsolete but Xastir
|
||||||
* sends it and we respect it.
|
* sends it and we respect it.
|
||||||
*
|
*
|
||||||
* 5 FullDuplex Ignored. Always full duplex.
|
* _5 FullDuplex Ignored.
|
||||||
*
|
*
|
||||||
* 6 SetHardware TNC specific. Ignored.
|
* _6 SetHardware TNC specific.
|
||||||
*
|
*
|
||||||
* FF Return Exit KISS mode. Ignored.
|
* FF Return Exit KISS mode. Ignored.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Messages sent to client application:
|
* Messages sent to client application:
|
||||||
*
|
*
|
||||||
* 0 Data Frame Received AX.25 frame in raw format.
|
* _0 Data Frame Received AX.25 frame in raw format.
|
||||||
*
|
*
|
||||||
*---------------------------------------------------------------*/
|
*---------------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -291,6 +291,8 @@ static int kiss_unwrap (unsigned char *in, int ilen, unsigned char *out)
|
||||||
* Inputs: kf - Current state of building a frame.
|
* Inputs: kf - Current state of building a frame.
|
||||||
* ch - A byte from the input stream.
|
* ch - A byte from the input stream.
|
||||||
* debug - Activates debug output.
|
* debug - Activates debug output.
|
||||||
|
* client - Client app number for TCP KISS.
|
||||||
|
* Ignored for pseudo termal and serial port.
|
||||||
* sendfun - Function to send something to the client application.
|
* sendfun - Function to send something to the client application.
|
||||||
*
|
*
|
||||||
* Outputs: kf - Current state is updated.
|
* Outputs: kf - Current state is updated.
|
||||||
|
@ -326,7 +328,7 @@ static int kiss_unwrap (unsigned char *in, int ilen, unsigned char *out)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void kiss_rec_byte (kiss_frame_t *kf, unsigned char ch, int debug, void (*sendfun)(int,unsigned char*,int))
|
void kiss_rec_byte (kiss_frame_t *kf, unsigned char ch, int debug, int client, void (*sendfun)(int,unsigned char*,int,int))
|
||||||
{
|
{
|
||||||
|
|
||||||
//dw_printf ("kiss_frame ( %c %02x ) \n", ch, ch);
|
//dw_printf ("kiss_frame ( %c %02x ) \n", ch, ch);
|
||||||
|
@ -367,10 +369,10 @@ void kiss_rec_byte (kiss_frame_t *kf, unsigned char ch, int debug, void (*sendfu
|
||||||
/* Try to appease client app by sending something back. */
|
/* Try to appease client app by sending something back. */
|
||||||
if (strcasecmp("restart\r", (char*)(kf->noise)) == 0 ||
|
if (strcasecmp("restart\r", (char*)(kf->noise)) == 0 ||
|
||||||
strcasecmp("reset\r", (char*)(kf->noise)) == 0) {
|
strcasecmp("reset\r", (char*)(kf->noise)) == 0) {
|
||||||
(*sendfun) (0, (unsigned char *)"\xc0\xc0", -1);
|
(*sendfun) (0, (unsigned char *)"\xc0\xc0", -1, client);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
(*sendfun) (0, (unsigned char *)"\r\ncmd:", -1);
|
(*sendfun) (0, (unsigned char *)"\r\ncmd:", -1, client);
|
||||||
}
|
}
|
||||||
kf->noise_len = 0;
|
kf->noise_len = 0;
|
||||||
}
|
}
|
||||||
|
@ -550,19 +552,22 @@ static void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug)
|
||||||
case 5: /* FullDuplex */
|
case 5: /* FullDuplex */
|
||||||
|
|
||||||
text_color_set(DW_COLOR_INFO);
|
text_color_set(DW_COLOR_INFO);
|
||||||
dw_printf ("KISS protocol set FullDuplex = %d, port %d\n", kiss_msg[1], port);
|
dw_printf ("KISS protocol set FullDuplex = %d, port %d - Ignored\n", kiss_msg[1], port);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6: /* TNC specific */
|
case 6: /* TNC specific */
|
||||||
|
|
||||||
text_color_set(DW_COLOR_INFO);
|
text_color_set(DW_COLOR_INFO);
|
||||||
dw_printf ("KISS protocol set hardware - ignored.\n");
|
dw_printf ("KISS protocol set hardware - Ignored.\n");
|
||||||
|
|
||||||
|
// TODO: kiss_set_hardware (...)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 15: /* End KISS mode, port should be 15. */
|
case 15: /* End KISS mode, port should be 15. */
|
||||||
/* Ignore it. */
|
/* Ignore it. */
|
||||||
text_color_set(DW_COLOR_INFO);
|
text_color_set(DW_COLOR_INFO);
|
||||||
dw_printf ("KISS protocol end KISS mode\n");
|
dw_printf ("KISS protocol end KISS mode - Ignored.\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -581,6 +586,57 @@ static void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug)
|
||||||
} /* end kiss_process_msg */
|
} /* end kiss_process_msg */
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Name: kiss_set_hardware
|
||||||
|
*
|
||||||
|
* Purpose: Process the "set hardware" command.
|
||||||
|
*
|
||||||
|
* Inputs:
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Description: This is new in version 1.5. "Set hardware" was previously ignored.
|
||||||
|
*
|
||||||
|
* There are times when the client app might want to send configuration
|
||||||
|
* commands, such as modem speed, to the KISS TNC or inquire about its
|
||||||
|
* current state.
|
||||||
|
*
|
||||||
|
* The immediate motivation for adding this is that one application wants
|
||||||
|
* to know how many frames are currently in the transmit queue. This can
|
||||||
|
* be used for throttling of large transmissions and performing some action
|
||||||
|
* after the last frame has been sent.
|
||||||
|
*
|
||||||
|
* The original KISS protocol spec offers no guidance on what this might look
|
||||||
|
* like. I'm aware of only two, drastically different, implementations:
|
||||||
|
*
|
||||||
|
* fldigi - http://www.w1hkj.com/FldigiHelp-3.22/kiss_command_page.html
|
||||||
|
*
|
||||||
|
* Everything is in human readable text in the form of:
|
||||||
|
* COMMAND : [ parameter [ , parameter ... ] ]
|
||||||
|
*
|
||||||
|
* Used by applications, http://www.w1hkj.com/FldigiHelp/kiss_host_prgs_page.html
|
||||||
|
* - BPQ32
|
||||||
|
* - UIChar
|
||||||
|
* - YAAC
|
||||||
|
*
|
||||||
|
* mobilinkd - https://raw.githubusercontent.com/mobilinkd/tnc1/tnc2/bertos/net/kiss.c
|
||||||
|
*
|
||||||
|
* Single byte with the command / response code, followed by
|
||||||
|
* zero or more value bytes.
|
||||||
|
*
|
||||||
|
* Used by applications:
|
||||||
|
* - APRSdroid
|
||||||
|
*
|
||||||
|
* It would be beneficial to adopt one of them rather than doing something
|
||||||
|
* completely different. It might even be possible to recognize both.
|
||||||
|
* This might allow leveraging of other existing applications.
|
||||||
|
*
|
||||||
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// static void kiss_set_hardware (...)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------
|
/*-------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Name: kiss_debug_print
|
* Name: kiss_debug_print
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
|
|
||||||
|
|
||||||
enum kiss_state_e {
|
enum kiss_state_e {
|
||||||
KS_SEARCHING, /* Looking for FEND to start KISS frame. */
|
KS_SEARCHING = 0, /* Looking for FEND to start KISS frame. */
|
||||||
|
/* Must be 0 so we can simply zero whole structure to initialize. */
|
||||||
KS_COLLECTING}; /* In process of collecting KISS frame. */
|
KS_COLLECTING}; /* In process of collecting KISS frame. */
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ void kiss_frame_init (struct audio_s *pa);
|
||||||
|
|
||||||
int kiss_encapsulate (unsigned char *in, int ilen, unsigned char *out);
|
int kiss_encapsulate (unsigned char *in, int ilen, unsigned char *out);
|
||||||
|
|
||||||
void kiss_rec_byte (kiss_frame_t *kf, unsigned char ch, int debug, void (*sendfun)(int,unsigned char*,int));
|
void kiss_rec_byte (kiss_frame_t *kf, unsigned char ch, int debug, int client, void (*sendfun)(int,unsigned char*,int,int));
|
||||||
|
|
||||||
|
|
||||||
typedef enum fromto_e { FROM_CLIENT=0, TO_CLIENT=1 } fromto_t;
|
typedef enum fromto_e { FROM_CLIENT=0, TO_CLIENT=1 } fromto_t;
|
||||||
|
|
377
kissnet.c
377
kissnet.c
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2011-2014, 2015 John Langner, WB2OSZ
|
// Copyright (C) 2011-2014, 2015, 2017 John Langner, WB2OSZ
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -49,28 +49,28 @@
|
||||||
*
|
*
|
||||||
* Commands from application recognized:
|
* Commands from application recognized:
|
||||||
*
|
*
|
||||||
* 0 Data Frame AX.25 frame in raw format.
|
* _0 Data Frame AX.25 frame in raw format.
|
||||||
*
|
*
|
||||||
* 1 TXDELAY See explanation in xmit.c.
|
* _1 TXDELAY See explanation in xmit.c.
|
||||||
*
|
*
|
||||||
* 2 Persistence " "
|
* _2 Persistence " "
|
||||||
*
|
*
|
||||||
* 3 SlotTime " "
|
* _3 SlotTime " "
|
||||||
*
|
*
|
||||||
* 4 TXtail " "
|
* _4 TXtail " "
|
||||||
* Spec says it is obsolete but Xastir
|
* Spec says it is obsolete but Xastir
|
||||||
* sends it and we respect it.
|
* sends it and we respect it.
|
||||||
*
|
*
|
||||||
* 5 FullDuplex Ignored. Always full duplex.
|
* _5 FullDuplex Ignored.
|
||||||
*
|
*
|
||||||
* 6 SetHardware TNC specific. Ignored.
|
* _6 SetHardware TNC specific.
|
||||||
*
|
*
|
||||||
* FF Return Exit KISS mode. Ignored.
|
* FF Return Exit KISS mode. Ignored.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Messages sent to client application:
|
* Messages sent to client application:
|
||||||
*
|
*
|
||||||
* 0 Data Frame Received AX.25 frame in raw format.
|
* _0 Data Frame Received AX.25 frame in raw format.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
@ -91,7 +91,6 @@
|
||||||
/*
|
/*
|
||||||
* Native Windows: Use the Winsock interface.
|
* Native Windows: Use the Winsock interface.
|
||||||
* Linux: Use the BSD socket interface.
|
* Linux: Use the BSD socket interface.
|
||||||
* Cygwin: Can use either one.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -131,15 +130,27 @@
|
||||||
void hex_dump (unsigned char *p, int len); // This should be in a .h file.
|
void hex_dump (unsigned char *p, int len); // This should be in a .h file.
|
||||||
|
|
||||||
|
|
||||||
static kiss_frame_t kf; /* Accumulated KISS frame and state of decoder. */
|
/*
|
||||||
// TODO: multiple instances if multiple KISS network clients!
|
* Early on we allowed one AGW connection and one KISS TCP connection at a time.
|
||||||
|
* In version 1.1, we allowed multiple concurrent client apps to attach with the AGW network protocol.
|
||||||
|
* In Version 1.5, we do essentially the same here to allow multiple concurrent KISS TCP clients.
|
||||||
|
* The default is a limit of 3 client applications at the same time.
|
||||||
|
* You can increase the limit by changing the line below.
|
||||||
|
* A larger number consumes more resources so don't go crazy by making it larger than needed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAX_NET_CLIENTS 3
|
||||||
|
|
||||||
static int client_sock; /* File descriptor for socket for */
|
static int client_sock[MAX_NET_CLIENTS];
|
||||||
|
/* File descriptor for socket for */
|
||||||
/* communication with client application. */
|
/* communication with client application. */
|
||||||
/* Set to -1 if not connected. */
|
/* Set to -1 if not connected. */
|
||||||
/* (Don't use SOCKET type because it is unsigned.) */
|
/* (Don't use SOCKET type because it is unsigned.) */
|
||||||
|
|
||||||
|
static kiss_frame_t kf[MAX_NET_CLIENTS];
|
||||||
|
/* Accumulated KISS frame and state of decoder. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: define in one place, use everywhere.
|
// TODO: define in one place, use everywhere.
|
||||||
#if __WIN32__
|
#if __WIN32__
|
||||||
|
@ -187,12 +198,14 @@ void kiss_net_set_debug (int n)
|
||||||
|
|
||||||
void kissnet_init (struct misc_config_s *mc)
|
void kissnet_init (struct misc_config_s *mc)
|
||||||
{
|
{
|
||||||
|
int client;
|
||||||
|
|
||||||
#if __WIN32__
|
#if __WIN32__
|
||||||
HANDLE connect_listen_th;
|
HANDLE connect_listen_th;
|
||||||
HANDLE cmd_listen_th;
|
HANDLE cmd_listen_th[MAX_NET_CLIENTS];
|
||||||
#else
|
#else
|
||||||
pthread_t connect_listen_tid;
|
pthread_t connect_listen_tid;
|
||||||
pthread_t cmd_listen_tid;
|
pthread_t cmd_listen_tid[MAX_NET_CLIENTS];
|
||||||
int e;
|
int e;
|
||||||
#endif
|
#endif
|
||||||
int kiss_port = mc->kiss_port;
|
int kiss_port = mc->kiss_port;
|
||||||
|
@ -203,9 +216,11 @@ void kissnet_init (struct misc_config_s *mc)
|
||||||
dw_printf ("kissnet_init ( %d )\n", kiss_port);
|
dw_printf ("kissnet_init ( %d )\n", kiss_port);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memset (&kf, 0, sizeof(kf));
|
|
||||||
|
|
||||||
client_sock = -1;
|
for (client=0; client<MAX_NET_CLIENTS; client++) {
|
||||||
|
client_sock[client] = -1;
|
||||||
|
memset (&(kf[client]), 0, sizeof(kf[client]));
|
||||||
|
}
|
||||||
|
|
||||||
if (kiss_port == 0) {
|
if (kiss_port == 0) {
|
||||||
text_color_set(DW_COLOR_INFO);
|
text_color_set(DW_COLOR_INFO);
|
||||||
|
@ -214,7 +229,7 @@ void kissnet_init (struct misc_config_s *mc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This waits for a client to connect and sets client_sock.
|
* This waits for a client to connect and sets client_sock[n].
|
||||||
*/
|
*/
|
||||||
#if __WIN32__
|
#if __WIN32__
|
||||||
connect_listen_th = (HANDLE)_beginthreadex (NULL, 0, connect_listen_thread, (void *)kiss_port, 0, NULL);
|
connect_listen_th = (HANDLE)_beginthreadex (NULL, 0, connect_listen_thread, (void *)kiss_port, 0, NULL);
|
||||||
|
@ -233,23 +248,28 @@ void kissnet_init (struct misc_config_s *mc)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This reads messages from client when client_sock is valid.
|
* These read messages from client when client_sock[n] is valid.
|
||||||
|
* Currently we start up a separate thread for each potential connection.
|
||||||
|
* Possible later refinement. Start one now, others only as needed.
|
||||||
*/
|
*/
|
||||||
|
for (client = 0; client < MAX_NET_CLIENTS; client++) {
|
||||||
|
|
||||||
#if __WIN32__
|
#if __WIN32__
|
||||||
cmd_listen_th = (HANDLE)_beginthreadex (NULL, 0, kissnet_listen_thread, NULL, 0, NULL);
|
cmd_listen_th[client] = (HANDLE)_beginthreadex (NULL, 0, kissnet_listen_thread, (void*)client, 0, NULL);
|
||||||
if (cmd_listen_th == NULL) {
|
if (cmd_listen_th[client] == NULL) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("Could not create KISS socket command listening thread\n");
|
dw_printf ("Could not create KISS socket command listening thread\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
e = pthread_create (&cmd_listen_tid, NULL, kissnet_listen_thread, NULL);
|
e = pthread_create (&(cmd_listen_tid[client]), NULL, kissnet_listen_thread, NULL);
|
||||||
if (e != 0) {
|
if (e != 0) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
perror("Could not create KISS socket command listening thread");
|
perror("Could not create KISS socket command listening thread");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -352,35 +372,50 @@ static THREAD_F connect_listen_thread (void *arg)
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
while (client_sock > 0) {
|
int client;
|
||||||
SLEEP_SEC(1); /* Already connected. Try again later. */
|
int c;
|
||||||
|
|
||||||
|
client = -1;
|
||||||
|
for (c = 0; c < MAX_NET_CLIENTS && client < 0; c++) {
|
||||||
|
if (client_sock[c] <= 0) {
|
||||||
|
client = c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define QUEUE_SIZE 5
|
/*
|
||||||
|
* Listen for connection if we have not reached maximum.
|
||||||
|
*/
|
||||||
|
if (client >= 0) {
|
||||||
|
|
||||||
if(listen(listen_sock,QUEUE_SIZE) == SOCKET_ERROR)
|
if(listen(listen_sock, MAX_NET_CLIENTS) == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf("Listen failed with error: %d\n", WSAGetLastError());
|
dw_printf("Listen failed with error: %d\n", WSAGetLastError());
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
text_color_set(DW_COLOR_INFO);
|
text_color_set(DW_COLOR_INFO);
|
||||||
dw_printf("Ready to accept KISS client application on port %s ...\n", kiss_port_str);
|
dw_printf("Ready to accept KISS TCP client application %d on port %s ...\n", client, kiss_port_str);
|
||||||
|
|
||||||
client_sock = accept(listen_sock, NULL, NULL);
|
client_sock[client] = accept(listen_sock, NULL, NULL);
|
||||||
|
|
||||||
if (client_sock == -1) {
|
if (client_sock[client] == -1) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf("Accept failed with error: %d\n", WSAGetLastError());
|
dw_printf("Accept failed with error: %d\n", WSAGetLastError());
|
||||||
closesocket(listen_sock);
|
closesocket(listen_sock);
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
text_color_set(DW_COLOR_INFO);
|
text_color_set(DW_COLOR_INFO);
|
||||||
dw_printf("\nConnected to KISS client application ...\n\n");
|
dw_printf("\nAttached to KISS TCP client application %d ...\n\n", client);
|
||||||
|
|
||||||
|
// Reset the state and buffer.
|
||||||
|
memset (&(kf[client]), 0, sizeof(kf[client]));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SLEEP_SEC(1); /* wait then check again if more clients allowed. */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -430,32 +465,44 @@ static THREAD_F connect_listen_thread (void *arg)
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
dw_printf("opened KISS socket as fd (%d) on port (%d) for stream i/o\n", listen_sock, ntohs(sockaddr.sin_port) );
|
dw_printf("opened KISS TCP socket as fd (%d) on port (%d) for stream i/o\n", listen_sock, ntohs(sockaddr.sin_port) );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
while (client_sock > 0) {
|
int client;
|
||||||
SLEEP_SEC(1); /* Already connected. Try again later. */
|
int c;
|
||||||
|
|
||||||
|
client = -1;
|
||||||
|
for (c = 0; c < MAX_NET_CLIENTS && client < 0; c++) {
|
||||||
|
if (client_sock[c] <= 0) {
|
||||||
|
client = c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define QUEUE_SIZE 5
|
if (client >= 0) {
|
||||||
|
|
||||||
if(listen(listen_sock,QUEUE_SIZE) == -1)
|
if(listen(listen_sock,MAX_NET_CLIENTS) == -1)
|
||||||
{
|
{
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
perror ("connect_listen_thread: Listen failed");
|
perror ("connect_listen_thread: Listen failed");
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
text_color_set(DW_COLOR_INFO);
|
text_color_set(DW_COLOR_INFO);
|
||||||
dw_printf("Ready to accept KISS client application on port %d ...\n", kiss_port);
|
dw_printf("Ready to accept KISS TCP client application %d on port %d ...\n", client, kiss_port);
|
||||||
|
|
||||||
client_sock = accept(listen_sock, (struct sockaddr*)(&sockaddr),&sockaddr_size);
|
client_sock[client] = accept(listen_sock, (struct sockaddr*)(&sockaddr),&sockaddr_size);
|
||||||
|
|
||||||
text_color_set(DW_COLOR_INFO);
|
text_color_set(DW_COLOR_INFO);
|
||||||
dw_printf("\nConnected to KISS client application ...\n\n");
|
dw_printf("\nAttached to KISS TCP client application %d...\n\n", client);
|
||||||
|
|
||||||
|
// Reset the state and buffer.
|
||||||
|
memset (&(kf[client]), 0, sizeof(kf[client]));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SLEEP_SEC(1); /* wait then check again if more clients allowed. */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -477,80 +524,121 @@ static THREAD_F connect_listen_thread (void *arg)
|
||||||
* or a text string.
|
* or a text string.
|
||||||
*
|
*
|
||||||
* flen - Number of bytes for AX.25 frame.
|
* flen - Number of bytes for AX.25 frame.
|
||||||
* or -1 for a text string.
|
* When called from kiss_rec_byte, flen will be -1
|
||||||
*
|
* indicating a text string rather than frame content.
|
||||||
|
* This is used to fake out an application that thinks
|
||||||
|
* it is using a traditional TNC and tries to put it
|
||||||
|
* into KISS mode.
|
||||||
*
|
*
|
||||||
* Description: Send message to client if connected.
|
* tcpclient - It is possible to have more than client attached
|
||||||
|
* at the same time with TCP KISS.
|
||||||
|
* When a frame is received from the radio we want it
|
||||||
|
* to go to all of the clients. In this case specify -1.
|
||||||
|
* When responding to a command from the client, we want
|
||||||
|
* to send only to that one client app. In this case
|
||||||
|
* use the value 0 .. MAX_NET_CLIENTS-1.
|
||||||
|
*
|
||||||
|
* Description: Send message to client(s) if connected.
|
||||||
* Disconnect from client, and notify user, if any error.
|
* Disconnect from client, and notify user, if any error.
|
||||||
*
|
*
|
||||||
*--------------------------------------------------------------------*/
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
void kissnet_send_rec_packet (int chan, unsigned char *fbuf, int flen)
|
void kissnet_send_rec_packet (int chan, unsigned char *fbuf, int flen, int tcpclient)
|
||||||
{
|
{
|
||||||
unsigned char kiss_buff[2 * AX25_MAX_PACKET_LEN];
|
unsigned char kiss_buff[2 * AX25_MAX_PACKET_LEN];
|
||||||
int kiss_len;
|
int kiss_len;
|
||||||
int err;
|
int err;
|
||||||
|
int first, last, client;
|
||||||
|
|
||||||
|
// Something received over the radio would be sent to all attached clients.
|
||||||
|
// However, there are times we want to send a response only to a particular client.
|
||||||
|
// In the case of a serial port or pseudo terminal, there is only one potential client.
|
||||||
|
// so the response would be sent to only one place. A new parameter has been added for this.
|
||||||
|
|
||||||
if (client_sock == -1) {
|
if (tcpclient >= 0 && tcpclient < MAX_NET_CLIENTS) {
|
||||||
return;
|
first = tcpclient;
|
||||||
|
last = tcpclient;
|
||||||
}
|
}
|
||||||
if (flen < 0) {
|
else if (tcpclient == -1) {
|
||||||
flen = strlen((char*)fbuf);
|
first = 0;
|
||||||
if (kiss_debug) {
|
last = MAX_NET_CLIENTS - 1;
|
||||||
kiss_debug_print (TO_CLIENT, "Fake command prompt", fbuf, flen);
|
|
||||||
}
|
|
||||||
strlcpy ((char *)kiss_buff, (char *)fbuf, sizeof(kiss_buff));
|
|
||||||
kiss_len = strlen((char *)kiss_buff);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf ("KISS TCP: Internal error, kissnet_send_rec_packet, tcpclient = %d.\n", tcpclient);
|
||||||
unsigned char stemp[AX25_MAX_PACKET_LEN + 1];
|
return;
|
||||||
|
|
||||||
assert (flen < (int)(sizeof(stemp)));
|
|
||||||
|
|
||||||
stemp[0] = (chan << 4) + 0;
|
|
||||||
memcpy (stemp+1, fbuf, flen);
|
|
||||||
|
|
||||||
if (kiss_debug >= 2) {
|
|
||||||
/* AX.25 frame with the CRC removed. */
|
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
|
||||||
dw_printf ("\n");
|
|
||||||
dw_printf ("Packet content before adding KISS framing and any escapes:\n");
|
|
||||||
hex_dump (fbuf, flen);
|
|
||||||
}
|
|
||||||
|
|
||||||
kiss_len = kiss_encapsulate (stemp, flen+1, kiss_buff);
|
|
||||||
|
|
||||||
/* This has the escapes and the surrounding FENDs. */
|
|
||||||
|
|
||||||
if (kiss_debug) {
|
|
||||||
kiss_debug_print (TO_CLIENT, NULL, kiss_buff, kiss_len);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (client = first; client <= last; client++) {
|
||||||
|
|
||||||
|
if (client_sock[client] != -1) {
|
||||||
|
|
||||||
|
if (flen < 0) {
|
||||||
|
|
||||||
|
// A client app might think it is attached to a traditional TNC.
|
||||||
|
// It might try sending commands over and over again trying to get the TNC into KISS mode.
|
||||||
|
// We recognize this attempt and send it something to keep it happy.
|
||||||
|
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf ("KISS TCP: Something unexpected from client application.\n");
|
||||||
|
dw_printf ("Is client app treating this like an old TNC with command mode?\n");
|
||||||
|
|
||||||
|
flen = strlen((char*)fbuf);
|
||||||
|
if (kiss_debug) {
|
||||||
|
kiss_debug_print (TO_CLIENT, "Fake command prompt", fbuf, flen);
|
||||||
|
}
|
||||||
|
strlcpy ((char *)kiss_buff, (char *)fbuf, sizeof(kiss_buff));
|
||||||
|
kiss_len = strlen((char *)kiss_buff);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unsigned char stemp[AX25_MAX_PACKET_LEN + 1];
|
||||||
|
|
||||||
|
assert (flen < (int)(sizeof(stemp)));
|
||||||
|
|
||||||
|
stemp[0] = (chan << 4) + 0;
|
||||||
|
memcpy (stemp+1, fbuf, flen);
|
||||||
|
|
||||||
|
if (kiss_debug >= 2) {
|
||||||
|
/* AX.25 frame with the CRC removed. */
|
||||||
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
|
dw_printf ("\n");
|
||||||
|
dw_printf ("Packet content before adding KISS framing and any escapes:\n");
|
||||||
|
hex_dump (fbuf, flen);
|
||||||
|
}
|
||||||
|
|
||||||
|
kiss_len = kiss_encapsulate (stemp, flen+1, kiss_buff);
|
||||||
|
|
||||||
|
/* This has the escapes and the surrounding FENDs. */
|
||||||
|
|
||||||
|
if (kiss_debug) {
|
||||||
|
kiss_debug_print (TO_CLIENT, NULL, kiss_buff, kiss_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if __WIN32__
|
#if __WIN32__
|
||||||
err = send (client_sock, (char*)kiss_buff, kiss_len, 0);
|
err = send (client_sock[client], (char*)kiss_buff, kiss_len, 0);
|
||||||
if (err == SOCKET_ERROR)
|
if (err == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("\nError %d sending message to KISS client application. Closing connection.\n\n", WSAGetLastError());
|
dw_printf ("\nError %d sending message to KISS client application. Closing connection.\n\n", WSAGetLastError());
|
||||||
closesocket (client_sock);
|
closesocket (client_sock[client]);
|
||||||
client_sock = -1;
|
client_sock[client] = -1;
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
err = write (client_sock, kiss_buff, kiss_len);
|
err = write (client_sock[client], kiss_buff, kiss_len);
|
||||||
if (err <= 0)
|
if (err <= 0)
|
||||||
{
|
{
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("\nError sending message to KISS client application. Closing connection.\n\n");
|
dw_printf ("\nError sending message to KISS client application. Closing connection.\n\n");
|
||||||
close (client_sock);
|
close (client_sock[client]);
|
||||||
client_sock = -1;
|
client_sock[client] = -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} /* end kissnet_send_rec_packet */
|
} /* end kissnet_send_rec_packet */
|
||||||
|
|
||||||
|
@ -586,15 +674,13 @@ static int read_from_socket (int fd, char *ptr, int len)
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
#if __WIN32__
|
#if __WIN32__
|
||||||
|
|
||||||
//TODO: any flags for send/recv?
|
|
||||||
//TODO: Would be useful to have more detailed explanation from the error code.
|
|
||||||
|
|
||||||
n = recv (fd, ptr + got_bytes, len - got_bytes, 0);
|
n = recv (fd, ptr + got_bytes, len - got_bytes, 0);
|
||||||
#else
|
#else
|
||||||
n = read (fd, ptr + got_bytes, len - got_bytes);
|
n = read (fd, ptr + got_bytes, len - got_bytes);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//Would be useful to have more detailed explanation from the error code.
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
dw_printf ("read_from_socket: n = %d\n", n);
|
dw_printf ("read_from_socket: n = %d\n", n);
|
||||||
|
@ -621,9 +707,9 @@ static int read_from_socket (int fd, char *ptr, int len)
|
||||||
*
|
*
|
||||||
* Purpose: Wait for KISS messages from an application.
|
* Purpose: Wait for KISS messages from an application.
|
||||||
*
|
*
|
||||||
* Inputs: arg - Not used.
|
* Inputs: arg - client number, 0 .. MAX_NET_CLIENTS-1
|
||||||
*
|
*
|
||||||
* Outputs: client_sock - File descriptor for communicating with client app.
|
* Outputs: client_sock[n] - File descriptor for communicating with client app.
|
||||||
*
|
*
|
||||||
* Description: Process messages from the client application.
|
* Description: Process messages from the client application.
|
||||||
* Note that the client can go away and come back again and
|
* Note that the client can go away and come back again and
|
||||||
|
@ -635,20 +721,20 @@ static int read_from_socket (int fd, char *ptr, int len)
|
||||||
/* Return one byte (value 0 - 255) */
|
/* Return one byte (value 0 - 255) */
|
||||||
|
|
||||||
|
|
||||||
static int kiss_get (void)
|
static int kiss_get (int client)
|
||||||
{
|
{
|
||||||
unsigned char ch;
|
unsigned char ch;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
while (client_sock <= 0) {
|
while (client_sock[client] <= 0) {
|
||||||
SLEEP_SEC(1); /* Not connected. Try again later. */
|
SLEEP_SEC(1); /* Not connected. Try again later. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Just get one byte at a time. */
|
/* Just get one byte at a time. */
|
||||||
|
|
||||||
n = read_from_socket (client_sock, (char *)(&ch), 1);
|
n = read_from_socket (client_sock[client], (char *)(&ch), 1);
|
||||||
|
|
||||||
if (n == 1) {
|
if (n == 1) {
|
||||||
#if DEBUG9
|
#if DEBUG9
|
||||||
|
@ -668,13 +754,13 @@ static int kiss_get (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("\nError reading KISS byte from client application. Closing connection.\n\n");
|
dw_printf ("\nError reading KISS byte from client application %d. Closing connection.\n\n", client);
|
||||||
#if __WIN32__
|
#if __WIN32__
|
||||||
closesocket (client_sock);
|
closesocket (client_sock[client]);
|
||||||
#else
|
#else
|
||||||
close (client_sock);
|
close (client_sock[client]);
|
||||||
#endif
|
#endif
|
||||||
client_sock = -1;
|
client_sock[client] = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,9 +775,26 @@ static THREAD_F kissnet_listen_thread (void *arg)
|
||||||
dw_printf ("kissnet_listen_thread ( socket = %d )\n", client_sock);
|
dw_printf ("kissnet_listen_thread ( socket = %d )\n", client_sock);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int client = (int)(long)arg;
|
||||||
|
|
||||||
|
assert (client >= 0 && client < MAX_NET_CLIENTS);
|
||||||
|
|
||||||
|
|
||||||
|
// So why is kissnet_send_rec_packet mentioned here for incoming from the client app?
|
||||||
|
// The logic exists for the serial port case where the client might think it is
|
||||||
|
// attached to a traditional TNC. It might try sending commands over and over again
|
||||||
|
// trying to get the TNC into KISS mode. To keep it happy, we recognize this attempt
|
||||||
|
// and send it something to keep it happy.
|
||||||
|
// In the case of a serial port or pseudo terminal, there is only one potential client
|
||||||
|
// so the response would be sent to only one place.
|
||||||
|
// Starting in version 1.5, this now can have multiple attached clients. We wouldn't
|
||||||
|
// want to send the response to all of them. Actually, we should be providing only
|
||||||
|
// "Simply KISS" as some call it.
|
||||||
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
ch = kiss_get();
|
ch = kiss_get(client);
|
||||||
kiss_rec_byte (&kf, ch, kiss_debug, kissnet_send_rec_packet);
|
kiss_rec_byte (&(kf[client]), ch, kiss_debug, client, kissnet_send_rec_packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __WIN32__
|
#if __WIN32__
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
void kissnet_init (struct misc_config_s *misc_config);
|
void kissnet_init (struct misc_config_s *misc_config);
|
||||||
|
|
||||||
void kissnet_send_rec_packet (int chan, unsigned char *fbuf, int flen);
|
void kissnet_send_rec_packet (int chan, unsigned char *fbuf, int flen, int client);
|
||||||
|
|
||||||
void kiss_net_set_debug (int n);
|
void kiss_net_set_debug (int n);
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,7 @@
|
||||||
|
|
||||||
// TODO: Needs more clean up and testing of error conditions.
|
|
||||||
|
|
||||||
// TODO: use this in place of other similar code.
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2014, 2015 John Langner, WB2OSZ
|
// Copyright (C) 2014, 2015, 2017 John Langner, WB2OSZ
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -73,8 +67,10 @@
|
||||||
* Inputs: devicename - For Windows, usually like COM5.
|
* Inputs: devicename - For Windows, usually like COM5.
|
||||||
* For Linux, usually /dev/tty...
|
* For Linux, usually /dev/tty...
|
||||||
* "COMn" also allowed and converted to /dev/ttyS(n-1)
|
* "COMn" also allowed and converted to /dev/ttyS(n-1)
|
||||||
|
* Could be /dev/rfcomm0 for Bluetooth.
|
||||||
*
|
*
|
||||||
* baud - Speed. 4800, 9600, etc.
|
* baud - Speed. 1200, 4800, 9600 bps, etc.
|
||||||
|
* If 0, leave it alone.
|
||||||
*
|
*
|
||||||
* Returns Handle for serial port or MYFDERROR for error.
|
* Returns Handle for serial port or MYFDERROR for error.
|
||||||
*
|
*
|
||||||
|
@ -143,6 +139,7 @@ MYFDTYPE serial_port_open (char *devicename, int baud)
|
||||||
|
|
||||||
switch (baud) {
|
switch (baud) {
|
||||||
|
|
||||||
|
case 0: /* Leave it alone. */ break;
|
||||||
case 1200: dcb.BaudRate = CBR_1200; break;
|
case 1200: dcb.BaudRate = CBR_1200; break;
|
||||||
case 2400: dcb.BaudRate = CBR_2400; break;
|
case 2400: dcb.BaudRate = CBR_2400; break;
|
||||||
case 4800: dcb.BaudRate = CBR_4800; break;
|
case 4800: dcb.BaudRate = CBR_4800; break;
|
||||||
|
@ -233,6 +230,7 @@ MYFDTYPE serial_port_open (char *devicename, int baud)
|
||||||
|
|
||||||
switch (baud) {
|
switch (baud) {
|
||||||
|
|
||||||
|
case 0: /* Leave it alone. */ break;
|
||||||
case 1200: cfsetispeed (&ts, B1200); cfsetospeed (&ts, B1200); break;
|
case 1200: cfsetispeed (&ts, B1200); cfsetospeed (&ts, B1200); break;
|
||||||
case 2400: cfsetispeed (&ts, B2400); cfsetospeed (&ts, B2400); break;
|
case 2400: cfsetispeed (&ts, B2400); cfsetospeed (&ts, B2400); break;
|
||||||
case 4800: cfsetispeed (&ts, B4800); cfsetospeed (&ts, B4800); break;
|
case 4800: cfsetispeed (&ts, B4800); cfsetospeed (&ts, B4800); break;
|
||||||
|
@ -305,8 +303,10 @@ int serial_port_write (MYFDTYPE fd, char *str, int len)
|
||||||
}
|
}
|
||||||
else if ((int)nwritten != len)
|
else if ((int)nwritten != len)
|
||||||
{
|
{
|
||||||
text_color_set(DW_COLOR_ERROR);
|
// Do we want this message here?
|
||||||
dw_printf ("Error writing to serial port. Only %d of %d written.\n\n", (int)nwritten, len);
|
// Or rely on caller to check and provide something more meaningful for the usage?
|
||||||
|
//text_color_set(DW_COLOR_ERROR);
|
||||||
|
//dw_printf ("Error writing to serial port. Only %d of %d written.\n\n", (int)nwritten, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (nwritten);
|
return (nwritten);
|
||||||
|
@ -317,8 +317,10 @@ int serial_port_write (MYFDTYPE fd, char *str, int len)
|
||||||
written = write (fd, str, (size_t)len);
|
written = write (fd, str, (size_t)len);
|
||||||
if (written != len)
|
if (written != len)
|
||||||
{
|
{
|
||||||
text_color_set(DW_COLOR_ERROR);
|
// Do we want this message here?
|
||||||
dw_printf ("Error writing to serial port. err=%d\n\n", written);
|
// Or rely on caller to check and provide something more meaningful for the usage?
|
||||||
|
//text_color_set(DW_COLOR_ERROR);
|
||||||
|
//dw_printf ("Error writing to serial port. err=%d\n\n", written);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,8 +404,9 @@ int serial_port_get1 (MYFDTYPE fd)
|
||||||
CloseHandle(ov_rd.hEvent);
|
CloseHandle(ov_rd.hEvent);
|
||||||
|
|
||||||
if (n != 1) {
|
if (n != 1) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
//text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("Serial port failed to get one byte. n=%d.\n\n", (int)n);
|
//dw_printf ("Serial port failed to get one byte. n=%d.\n\n", (int)n);
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -414,8 +417,8 @@ int serial_port_get1 (MYFDTYPE fd)
|
||||||
n = read(fd, &ch, (size_t)1);
|
n = read(fd, &ch, (size_t)1);
|
||||||
|
|
||||||
if (n != 1) {
|
if (n != 1) {
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
//text_color_set(DW_COLOR_DEBUG);
|
||||||
dw_printf ("serial_port_get1(%d) returns -1 for error.\n", fd);
|
//dw_printf ("serial_port_get1(%d) returns -1 for error.\n", fd);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,8 +450,14 @@ int serial_port_get1 (MYFDTYPE fd)
|
||||||
*
|
*
|
||||||
*--------------------------------------------------------------------*/
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void serial_port_close (MYFDTYPE fd)
|
||||||
// TODO:
|
{
|
||||||
|
#if __WIN32__
|
||||||
|
CloseHandle (fd);
|
||||||
|
#else
|
||||||
|
close (fd);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* end serial_port.c */
|
/* end serial_port.c */
|
||||||
|
|
5
server.c
5
server.c
|
@ -637,8 +637,7 @@ static THREAD_F connect_listen_thread (void *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
text_color_set(DW_COLOR_INFO);
|
text_color_set(DW_COLOR_INFO);
|
||||||
// TODO: "attached" or some other term would be better because "connected" has a different meaning for AX.25.
|
dw_printf("\nAttached to AGW client application %d ...\n\n", client);
|
||||||
dw_printf("\nConnected to AGW client application %d ...\n\n", client);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The command to change this is actually a toggle, not explicit on or off.
|
* The command to change this is actually a toggle, not explicit on or off.
|
||||||
|
@ -729,7 +728,7 @@ static THREAD_F connect_listen_thread (void *arg)
|
||||||
client_sock[client] = accept(listen_sock, (struct sockaddr*)(&sockaddr),&sockaddr_size);
|
client_sock[client] = accept(listen_sock, (struct sockaddr*)(&sockaddr),&sockaddr_size);
|
||||||
|
|
||||||
text_color_set(DW_COLOR_INFO);
|
text_color_set(DW_COLOR_INFO);
|
||||||
dw_printf("\nConnected to AGW client application %d...\n\n", client);
|
dw_printf("\nAttached to AGW client application %d...\n\n", client);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The command to change this is actually a toggle, not explicit on or off.
|
* The command to change this is actually a toggle, not explicit on or off.
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
|
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "kiss.h"
|
#include "kiss.h"
|
||||||
|
#include "kissserial.h"
|
||||||
#include "kissnet.h"
|
#include "kissnet.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -895,8 +896,9 @@ static void xmit_object_report (int i, int first_time)
|
||||||
flen = ax25_pack(pp, fbuf);
|
flen = ax25_pack(pp, fbuf);
|
||||||
|
|
||||||
server_send_rec_packet (save_tt_config_p->obj_recv_chan, pp, fbuf, flen);
|
server_send_rec_packet (save_tt_config_p->obj_recv_chan, pp, fbuf, flen);
|
||||||
kissnet_send_rec_packet (save_tt_config_p->obj_recv_chan, fbuf, flen);
|
kissnet_send_rec_packet (save_tt_config_p->obj_recv_chan, fbuf, flen, -1);
|
||||||
kiss_send_rec_packet (save_tt_config_p->obj_recv_chan, fbuf, flen);
|
kissserial_send_rec_packet (save_tt_config_p->obj_recv_chan, fbuf, flen, -1);
|
||||||
|
kisspt_send_rec_packet (save_tt_config_p->obj_recv_chan, fbuf, flen, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (first_time && save_tt_config_p->obj_send_to_ig) {
|
if (first_time && save_tt_config_p->obj_send_to_ig) {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
/* Dire Wolf version 1.4 */
|
/* Dire Wolf version 1.5 */
|
||||||
|
|
||||||
#define APP_TOCALL "APDW"
|
#define APP_TOCALL "APDW"
|
||||||
|
|
||||||
#define MAJOR_VERSION 1
|
#define MAJOR_VERSION 1
|
||||||
#define MINOR_VERSION 4
|
#define MINOR_VERSION 5
|
||||||
//#define EXTRA_VERSION "Beta Test"
|
//#define EXTRA_VERSION "Beta Test"
|
||||||
|
|
Loading…
Reference in New Issue