Refactoring command line option handling

* Use own function to define and parse command line options

 * Command line options can be defined by config file also

 * --limesdr allows to auto-set required SDR option for LimeSDR
This commit is contained in:
Andreas Eversberg 2018-05-19 10:56:43 +02:00
parent 6ba1b8acab
commit 3b81007210
37 changed files with 1434 additions and 1444 deletions

1
.gitignore vendored
View File

@ -20,6 +20,7 @@ compile
.libs
.dirstamp
m4
src/liboptions/liboptions.a
src/libdebug/libdebug.a
src/libmobile/libmobile.a
src/libdisplay/libdisplay.a

View File

@ -49,6 +49,7 @@ AS_IF([test "x$with_imagemagick" == "xyes"],[AC_MSG_NOTICE( Compiling with Image
AS_IF([test "x$with_alsa" != "xyes" -a "x$with_sdr" != "xyes"],[AC_MSG_FAILURE( Without sound nor SDR support this project does not make sense. Please support sound card for analog transceivers or better SDR!" )],[])
AC_OUTPUT(
src/liboptions/Makefile
src/libdebug/Makefile
src/libmobile/Makefile
src/libdisplay/Makefile

View File

@ -67,7 +67,7 @@ LimeSDR
</p>
<p>
If you have this device, you need to install the SoapySDR, then the LimeSuit and finally run configure with Osmocom Analog, compile and install.
If you have this device, you need to install the SoapySDR, then the LimeSuite and finally run configure with Osmocom Analog, compile and install.
Run Osmocom Analog with --help again, and you should see a bunch of option for SDR.
In case of B-Netz, I use the following parameters:
</p>
@ -75,14 +75,21 @@ In case of B-Netz, I use the following parameters:
<pre>
# bnetz --sdr-soapy \
--sdr-tx-gain 50 \
--sdr-rx-antenna LNAL \
--sdr-rx-gain 30 \
--sdr-tx-gain 30 \
--sdr-samplerate 5000000 \
-s 100000 \
-k 17
</pre>
<p>
Be sure to select the right RX antenna input.
The frequencies we use require the low frequency filter network, so I suggest to connect your antenna to RX_1_L and select "--sdr-rx-antenna LNAL".
Different versions of LimeSuite have different default antenna inputs, so be sure to set your RX antenna.
</p>
<p>
In order to change from analog sound card to SDR, you need <b>--sdr-soapy</b> option.
In my setup I use antennas directly connected to the SDR.
@ -170,7 +177,8 @@ Because C-Netz uses only odd channel numbers for 10 KHz spacing, we use channel
<pre>
# cnetz --sdr-soapy \
--sdr-rx-gain 50 \
--sdr-rx-antenna LNAL \
--sdr-rx-gain 30 \
--sdr-tx-gain 30 \
--sdr-samplerate 5000000 \
-s 100000 \

View File

@ -1,6 +1,7 @@
AUTOMAKE_OPTIONS = foreign
SUBDIRS = \
liboptions \
libdebug \
libmobile \
libdisplay \

View File

@ -26,6 +26,7 @@ amps_SOURCES = \
amps_LDADD = \
$(COMMON_LA) \
libamps.a \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libdebug/libdebug.a \
$(top_builddir)/src/libmobile/libmobile.a \
$(top_builddir)/src/libdisplay/libdisplay.a \

View File

@ -19,13 +19,14 @@
#include <stdio.h>
#include <stdint.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "../libsample/sample.h"
#include "../libmobile/main_mobile.h"
#include "../libdebug/debug.h"
#include "../libmobile/call.h"
#include "../liboptions/options.h"
#include "amps.h"
#include "dsp.h"
#include "frame.h"
@ -103,152 +104,132 @@ void print_help(const char *arg0)
main_mobile_print_hotkeys();
}
static int handle_options(int argc, char **argv)
static void add_options(void)
{
main_mobile_add_options();
option_add('T', "channel-type", 1);
option_add('F', "flip-polarity", 1);
option_add('P', "ms-power", 1);
option_add('D', "dtx", 1);
option_add('S', "sysinfo", 1);
option_add('O', "tolerant", 0);
}
static int handle_options(int short_option, int argi, char **argv)
{
const char *p;
int skip_args = 0;
int rc;
static struct option long_options_special[] = {
{"channel-type", 1, 0, 'T'},
{"flip-polarity", 1, 0, 'F'},
{"ms-power", 1, 0, 'P'},
{"dtx", 1, 0, 'D'},
{"sysinfo", 1, 0, 'S'},
{"tolerant", 0, 0, 'O'},
{0, 0, 0, 0}
};
main_mobile_set_options("T:F:P:D:S:O", long_options_special);
while (1) {
int option_index = 0, c;
c = getopt_long(argc, argv, optstring, long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'T':
if (!strcmp(optarg, "list")) {
amps_channel_list();
exit(0);
}
rc = amps_channel_by_short_name(optarg);
if (rc < 0) {
fprintf(stderr, "Error, channel type '%s' unknown. Please use '-t list' to get a list. I suggest to use the default.\n", optarg);
exit(0);
}
OPT_ARRAY(num_chan_type, chan_type, rc)
skip_args += 2;
break;
case 'F':
if (!strcasecmp(optarg, "no"))
flip_polarity = "no";
else if (!strcasecmp(optarg, "yes"))
flip_polarity = "yes";
else {
fprintf(stderr, "Given polarity '%s' is illegal, see help!\n", optarg);
exit(0);
}
skip_args += 2;
break;
case 'P':
ms_power = atoi(optarg);
if (ms_power > 7)
ms_power = 7;
if (ms_power < 0)
ms_power = 0;
skip_args += 2;
break;
case 'D':
dtx = atoi(optarg);
if (dtx > 3)
dtx = 3;
if (dtx < 0)
dtx = 0;
skip_args += 2;
break;
case 'S':
p = strchr(optarg, '=');
if (!p) {
fprintf(stderr, "Given sysinfo parameter '%s' requires '=' character to set value, see help!\n", optarg);
exit(0);
}
p++;
if (!strncasecmp(optarg, "sid=", p - optarg)
|| !strncasecmp(optarg, "aid=", p - optarg)) {
if (!strcasecmp(p, "list")) {
list_stations();
exit(0);
}
sid = atoi(p);
if (sid > 32767)
sid = 32767;
if (sid < 0)
sid = 0;
} else
if (!strncasecmp(optarg, "dcc=", p - optarg)) {
dcc = atoi(p);
if (dcc > 3)
dcc = 3;
if (dcc < 0)
dcc = 0;
} else
if (!strncasecmp(optarg, "scc=", p - optarg)) {
scc = atoi(p);
if (scc > 2)
scc = 2;
if (scc < 0)
scc = 0;
} else
if (!strncasecmp(optarg, "regincr=", p - optarg)) {
regincr = atoi(p);
} else
if (!strncasecmp(optarg, "pureg=", p - optarg)) {
pureg = atoi(p) & 1;
} else
if (!strncasecmp(optarg, "pdreg=", p - optarg)) {
pdreg = atoi(p) & 1;
} else
if (!strncasecmp(optarg, "locaid=", p - optarg)) {
locaid = atoi(p);
if (locaid > 4095)
locaid = 4095;
} else
if (!strncasecmp(optarg, "regh=", p - optarg)) {
regh = atoi(p) & 1;
} else
if (!strncasecmp(optarg, "regr=", p - optarg)) {
regr = atoi(p) & 1;
} else
if (!strncasecmp(optarg, "bis=", p - optarg)) {
bis = atoi(p) & 1;
} else {
fprintf(stderr, "Given sysinfo parameter '%s' unknown, see help!\n", optarg);
exit(0);
}
skip_args += 2;
break;
case 'O':
tolerant = 1;
skip_args += 1;
break;
default:
main_mobile_opt_switch(c, argv[0], &skip_args);
switch (short_option) {
case 'T':
if (!strcmp(argv[argi], "list")) {
amps_channel_list();
return 0;
}
rc = amps_channel_by_short_name(argv[argi]);
if (rc < 0) {
fprintf(stderr, "Error, channel type '%s' unknown. Please use '-t list' to get a list. I suggest to use the default.\n", argv[argi]);
return -EINVAL;
}
OPT_ARRAY(num_chan_type, chan_type, rc)
break;
case 'F':
if (!strcasecmp(argv[argi], "no"))
flip_polarity = "no";
else if (!strcasecmp(argv[argi], "yes"))
flip_polarity = "yes";
else {
fprintf(stderr, "Given polarity '%s' is illegal, use '-h' for help!\n", argv[argi]);
return -EINVAL;
}
break;
case 'P':
ms_power = atoi(argv[argi]);
if (ms_power > 7)
ms_power = 7;
if (ms_power < 0)
ms_power = 0;
break;
case 'D':
dtx = atoi(argv[argi]);
if (dtx > 3)
dtx = 3;
if (dtx < 0)
dtx = 0;
break;
case 'S':
p = strchr(argv[argi], '=');
if (!p) {
fprintf(stderr, "Given sysinfo parameter '%s' requires '=' character to set value, use '-h' for help!\n", argv[argi]);
return -EINVAL;
}
p++;
if (!strncasecmp(argv[argi], "sid=", p - argv[argi])
|| !strncasecmp(argv[argi], "aid=", p - argv[argi])) {
if (!strcasecmp(p, "list")) {
list_stations();
return 0;
}
sid = atoi(p);
if (sid > 32767)
sid = 32767;
if (sid < 0)
sid = 0;
} else
if (!strncasecmp(argv[argi], "dcc=", p - argv[argi])) {
dcc = atoi(p);
if (dcc > 3)
dcc = 3;
if (dcc < 0)
dcc = 0;
} else
if (!strncasecmp(argv[argi], "scc=", p - argv[argi])) {
scc = atoi(p);
if (scc > 2)
scc = 2;
if (scc < 0)
scc = 0;
} else
if (!strncasecmp(argv[argi], "regincr=", p - argv[argi])) {
regincr = atoi(p);
} else
if (!strncasecmp(argv[argi], "pureg=", p - argv[argi])) {
pureg = atoi(p) & 1;
} else
if (!strncasecmp(argv[argi], "pdreg=", p - argv[argi])) {
pdreg = atoi(p) & 1;
} else
if (!strncasecmp(argv[argi], "locaid=", p - argv[argi])) {
locaid = atoi(p);
if (locaid > 4095)
locaid = 4095;
} else
if (!strncasecmp(argv[argi], "regh=", p - argv[argi])) {
regh = atoi(p) & 1;
} else
if (!strncasecmp(argv[argi], "regr=", p - argv[argi])) {
regr = atoi(p) & 1;
} else
if (!strncasecmp(argv[argi], "bis=", p - argv[argi])) {
bis = atoi(p) & 1;
} else {
fprintf(stderr, "Given sysinfo parameter '%s' unknown, use '-h' for help!\n", argv[argi]);
return -EINVAL;
}
break;
case 'O':
tolerant = 1;
break;
default:
return main_mobile_handle_options(short_option, argi, argv);
}
free(long_options);
return skip_args;
return 1;
}
int main_amps_tacs(int argc, char *argv[])
{
int rc;
int skip_args;
int rc, argi;
const char *station_id = "";
int polarity;
int i;
@ -258,12 +239,24 @@ int main_amps_tacs(int argc, char *argv[])
main_mobile_init();
skip_args = handle_options(argc, argv);
argc -= skip_args;
argv += skip_args;
/* handle options / config file */
add_options();
if (!tacs) {
rc = options_config_file("~/.osmocom/analog/amps.conf", handle_options);
} else if (!jtacs) {
rc = options_config_file("~/.osmocom/analog/tacs.conf", handle_options);
} else {
rc = options_config_file("~/.osmocom/analog/jtacs.conf", handle_options);
}
if (rc < 0)
return 0;
argi = options_command_line(argc, argv, handle_options);
if (argi <= 0)
return argi;
if (argc > 1) {
station_id = argv[1];
if (argi < argc) {
station_id = argv[argi];
if (strlen(station_id) != 10) {
printf("Given station ID '%s' does not have 10 digits\n", station_id);
return 0;
@ -272,7 +265,7 @@ int main_amps_tacs(int argc, char *argv[])
if (!num_kanal) {
printf("No channel (\"Kanal\") is specified, I suggest channel %d.\n\n", (!tacs) ? 334 : 323);
print_help(argv[-skip_args]);
print_help(argv[0]);
return 0;
}
if (use_sdr) {
@ -380,7 +373,7 @@ int main_amps_tacs(int argc, char *argv[])
else if (use_sdr)
polarity = 1; /* SDR is always positive */
else {
fprintf(stderr, "You must define, if the the TX deviation polarity has to be flipped. (-F yes | no) See help.\n");
fprintf(stderr, "You must define, if the the TX deviation polarity has to be flipped. (-F yes | no) use '-h' for help.\n");
exit(0);
}

View File

@ -18,6 +18,7 @@ anetz_SOURCES = \
anetz_LDADD = \
$(COMMON_LA) \
libgermanton.a \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libdebug/libdebug.a \
$(top_builddir)/src/libmobile/libmobile.a \
$(top_builddir)/src/libdisplay/libdisplay.a \

View File

@ -19,15 +19,16 @@
#include <stdio.h>
#include <stdint.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <math.h>
#include "../libsample/sample.h"
#include "../libmobile/main_mobile.h"
#include "../libdebug/debug.h"
#include "../libtimer/timer.h"
#include "../libmobile/call.h"
#include "../liboptions/options.h"
#include "freiton.h"
#include "besetztton.h"
#include "anetz.h"
@ -69,79 +70,60 @@ void print_help(const char *arg0)
main_mobile_print_hotkeys();
}
static int handle_options(int argc, char **argv)
static void add_options(void)
{
main_mobile_add_options();
option_add('O', "operator", 1);
option_add('G', "geo", 1);
option_add('V', "page-gain", 1);
option_add('P', "page-sequence", 1);
option_add('S', "squelch", 1);
}
static int handle_options(int short_option, int argi, char **argv)
{
int skip_args = 0;
char *p;
double gain_db;
static struct option long_options_special[] = {
{"operator", 1, 0, 'O'},
{"geo", 1, 0, 'G'},
{"page-gain", 1, 0, 'V'},
{"page-sequence", 1, 0, 'P'},
{"squelch", 1, 0, 'S'},
{0, 0, 0, 0}
};
main_mobile_set_options("O:G:V:P:S:", long_options_special);
while (1) {
int option_index = 0, c;
c = getopt_long(argc, argv, optstring, long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'O':
strncpy(operator, optarg, sizeof(operator) - 1);
operator[sizeof(operator) - 1] = '\0';
skip_args += 2;
break;
case 'G':
if (!strcasecmp(optarg, "list")) {
station_list();
exit(0);
}
if ((p = strchr(optarg, ','))) {
get_station_by_coordinates(atof(optarg), atof(p + 1));
exit(0);
}
fprintf(stderr, "Invalid geo parameter\n");
exit(0);
break;
case 'V':
gain_db = atof(optarg);
page_gain = pow(10, gain_db / 20.0);
skip_args += 2;
break;
case 'P':
page_sequence = atoi(optarg);
skip_args += 2;
break;
case 'S':
if (!strcasecmp(optarg, "auto"))
squelch_db = 0.0;
else
squelch_db = atof(optarg);
skip_args += 2;
break;
default:
main_mobile_opt_switch(c, argv[0], &skip_args);
switch (short_option) {
case 'O':
strncpy(operator, argv[argi], sizeof(operator) - 1);
operator[sizeof(operator) - 1] = '\0';
break;
case 'G':
if (!strcasecmp(argv[argi], "list")) {
station_list();
return 0;
}
if ((p = strchr(argv[argi], ','))) {
get_station_by_coordinates(atof(argv[argi]), atof(p + 1));
return 0;
}
fprintf(stderr, "Invalid geo parameter\n");
return -EINVAL;
case 'V':
gain_db = atof(argv[argi]);
page_gain = pow(10, gain_db / 20.0);
break;
case 'P':
page_sequence = atoi(argv[argi]);
break;
case 'S':
if (!strcasecmp(argv[argi], "auto"))
squelch_db = 0.0;
else
squelch_db = atof(argv[argi]);
break;
default:
return main_mobile_handle_options(short_option, argi, argv);
}
free(long_options);
return skip_args;
return 1;
}
int main(int argc, char *argv[])
{
int rc;
int skip_args;
int rc, argi;
const char *station_id = "";
int i;
@ -154,12 +136,17 @@ int main(int argc, char *argv[])
main_mobile_init();
skip_args = handle_options(argc, argv);
argc -= skip_args;
argv += skip_args;
/* handle options / config file */
add_options();
rc = options_config_file("~/.osmocom/analog/anetz.conf", handle_options);
if (rc < 0)
return 0;
argi = options_command_line(argc, argv, handle_options);
if (argi <= 0)
return argi;
if (argc > 1) {
station_id = argv[1];
if (argi < argc) {
station_id = argv[argi];
if (strlen(station_id) != 5 && strlen(station_id) != 7) {
printf("Given station ID '%s' does not have 7 or (the last) 5 digits\n", station_id);
return 0;
@ -170,7 +157,7 @@ int main(int argc, char *argv[])
if (!num_kanal) {
printf("No channel (\"Kanal\") is specified, I suggest channel 30.\n\n");
print_help(argv[-skip_args]);
print_help(argv[0]);
return 0;
}
if (use_sdr) {

View File

@ -15,6 +15,7 @@ bnetz_SOURCES = \
bnetz_LDADD = \
$(COMMON_LA) \
../anetz/libgermanton.a \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libdebug/libdebug.a \
$(top_builddir)/src/libmobile/libmobile.a \
$(top_builddir)/src/libdisplay/libdisplay.a \
@ -36,6 +37,7 @@ bnetz_dialer_SOURCES = \
dialer.c
bnetz_dialer_LDADD = \
$(COMMON_LA) \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libdebug/libdebug.a \
$(top_builddir)/src/libfsk/libfsk.a \
$(top_builddir)/src/libfm/libfm.a \

View File

@ -19,10 +19,10 @@
#include <stdio.h>
#include <stdint.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "../libsample/sample.h"
#include "../libfsk/fsk.h"
#include "../libwave/wave.h"
@ -30,6 +30,7 @@
#ifdef HAVE_ALSA
#include "../libsound/sound.h"
#endif
#include "../liboptions/options.h"
#include "telegramm.h"
#define MAX_PAUSE 0.5 /* pause before and after dialing sequence */
@ -92,7 +93,6 @@ static void print_help(const char *arg0)
printf(" -a --audio-device hw:<card>,<device>\n");
printf(" Sound card and device number (default = '%s')\n", audiodev);
#endif
printf(" Don't set it for SDR!\n");
printf(" -s --samplerate <rate>\n");
printf(" Sample rate of sound device (default = '%d')\n", samplerate);
printf(" -w --write-tx-wave <file>\n");
@ -106,70 +106,50 @@ static void print_help(const char *arg0)
printf(" Indicate to base station that we are a pay phone. ('Muenztelefon')\n");
}
static int handle_options(int argc, char **argv)
static void add_options(void)
{
const char *optstring;
int skip_args = 0;
option_add('h', "help", 0);
option_add('i', "station-id", 1);
option_add('a', "audio-device", 1);
option_add('s', "samplerate", 1);
option_add('w', "write-tx-wave", 1);
option_add('g', "gebuehrenimpuls", 0);
option_add(OPT_METERING, "metering", 0);
option_add('m', "muenztelefon", 0);
option_add(OPT_COIN_BOX, "coin-box", 0);
}
static struct option long_options[] = {
{"help", 0, 0, 'h'},
{"station-id", 1, 0, 'i'},
{"audio-device", 1, 0, 'a'},
{"samplerate", 1, 0, 's'},
{"write-tx-wave", 1, 0, 'w'},
{"gebuehrenimpuls", 0, 0, 'g'},
{"metering", 0, 0, OPT_METERING},
{"muenztelefon", 0, 0, 'm'},
{"coin-box", 0, 0, OPT_COIN_BOX},
{0, 0, 0, 0},
};
optstring = "hi:a:s:w:gm";
while (1) {
int option_index = 0, c;
c = getopt_long(argc, argv, optstring, long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'h':
print_help(argv[0]);
exit(0);
case 'i':
station_id = strdup(optarg);
skip_args += 2;
break;
case 'a':
audiodev = strdup(optarg);
skip_args += 2;
break;
case 's':
samplerate = atoi(optarg);
skip_args += 2;
break;
case 'w':
write_tx_wave = strdup(optarg);
skip_args += 2;
break;
case 'g':
case OPT_METERING:
start_digit = 'S';
skip_args += 1;
break;
case 'm':
case OPT_COIN_BOX:
start_digit = 'M';
skip_args += 1;
break;
default:
break;
}
static int handle_options(int short_option, int __attribute__((unused)) argi, char **argv)
{
switch (short_option) {
case 'h':
print_help(argv[0]);
return 0;
case 'i':
station_id = strdup(argv[argi]);
break;
case 'a':
audiodev = strdup(argv[argi]);
break;
case 's':
samplerate = atoi(argv[argi]);
break;
case 'w':
write_tx_wave = strdup(argv[argi]);
break;
case 'g':
case OPT_METERING:
start_digit = 'S';
break;
case 'm':
case OPT_COIN_BOX:
start_digit = 'M';
break;
default:
return -EINVAL;
}
return skip_args;
return 1;
}
@ -301,10 +281,8 @@ static void process_signal(void)
int main(int argc, char *argv[])
{
const char *arg0 = argv[0];
int skip_args;
int i;
int rc;
int rc, argi;
/* init */
bnetz_init_telegramm();
@ -313,13 +291,15 @@ int main(int argc, char *argv[])
/* latency of send buffer in samples */
latspl = samplerate * latency / 1000;
skip_args = handle_options(argc, argv);
argc -= skip_args;
argv += skip_args;
/* handle options / config file */
add_options();
argi = options_command_line(argc, argv, handle_options);
if (argi <= 0)
return argi;
if (argc <= 1) {
if (argi >= argc) {
printf("No phone number given!\n\n");
print_help(arg0);
print_help(argv[0]);
goto exit;
}
@ -336,7 +316,7 @@ int main(int argc, char *argv[])
}
/* check for valid phone number */
dialing = argv[1];
dialing = argv[argi];
if (strlen(dialing) < 4) {
printf("Given phone number '%s' has too few digits! (less than minimum of 4 digits)\n", dialing);
goto exit;

View File

@ -19,9 +19,9 @@
#include <stdio.h>
#include <stdint.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <math.h>
#include "../libsample/sample.h"
#include "../libdebug/debug.h"
@ -29,6 +29,7 @@
#include "../libmobile/main_mobile.h"
#include "../anetz/freiton.h"
#include "../anetz/besetztton.h"
#include "../liboptions/options.h"
#include "bnetz.h"
#include "dsp.h"
#include "stations.h"
@ -79,70 +80,54 @@ void print_help(const char *arg0)
main_mobile_print_hotkeys();
}
static int handle_options(int argc, char **argv)
static void add_options(void)
{
main_mobile_add_options();
option_add('G', "gfs", 1);
option_add('M', "gebuehrenimpuls", 1);
option_add('P', "paging", 1);
option_add('S', "squelch", 1);
}
static int handle_options(int short_option, int argi, char **argv)
{
int skip_args = 0;
char *p;
static struct option long_options_special[] = {
{"gfs", 1, 0, 'G'},
{"gebuehrenimpuls", 1, 0, 'M'},
{"paging", 1, 0, 'P'},
{"squelch", 1, 0, 'S'},
{0, 0, 0, 0},
};
main_mobile_set_options("G:M:P:S:", long_options_special);
while (1) {
int option_index = 0, c;
c = getopt_long(argc, argv, optstring, long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'G':
if (!strcasecmp(optarg, "list")) {
station_list();
exit(0);
}
if ((p = strchr(optarg, ','))) {
gfs = get_station_by_coordinates(atof(optarg), atof(p + 1));
if (gfs == 0)
exit(0);
} else
gfs = atoi(optarg);
skip_args += 2;
break;
case 'M':
metering = atoi(optarg);
skip_args += 2;
break;
case 'P':
paging = strdup(optarg);
skip_args += 2;
break;
case 'S':
if (!strcasecmp(optarg, "auto"))
squelch_db = 0.0;
else
squelch_db = atof(optarg);
skip_args += 2;
break;
default:
main_mobile_opt_switch(c, argv[0], &skip_args);
switch (short_option) {
case 'G':
if (!strcasecmp(argv[argi], "list")) {
station_list();
return 0;
}
if ((p = strchr(argv[argi], ','))) {
gfs = get_station_by_coordinates(atof(argv[argi]), atof(p + 1));
if (gfs == 0)
return -EINVAL;
} else
gfs = atoi(argv[argi]);
break;
case 'M':
metering = atoi(argv[argi]);
break;
case 'P':
paging = strdup(argv[argi]);
break;
case 'S':
if (!strcasecmp(argv[argi], "auto"))
squelch_db = 0.0;
else
squelch_db = atof(argv[argi]);
break;
default:
return main_mobile_handle_options(short_option, argi, argv);
}
return skip_args;
return 1;
}
int main(int argc, char *argv[])
{
int rc;
int skip_args;
int rc, argi;
const char *station_id = "";
int i;
@ -153,12 +138,17 @@ int main(int argc, char *argv[])
main_mobile_init();
skip_args = handle_options(argc, argv);
argc -= skip_args;
argv += skip_args;
/* handle options / config file */
add_options();
rc = options_config_file("~/.osmocom/analog/bnetz.conf", handle_options);
if (rc < 0)
return 0;
argi = options_command_line(argc, argv, handle_options);
if (argi <= 0)
return argi;
if (argc > 1) {
station_id = argv[1];
if (argi < argc) {
station_id = argv[argi];
if (strlen(station_id) != 5) {
printf("Given station ID '%s' does not have 5 digits\n", station_id);
return 0;
@ -167,7 +157,7 @@ int main(int argc, char *argv[])
if (!num_kanal) {
printf("No channel (\"Kanal\") is specified, I suggest channel 1 (sound card) or 17 (SDR).\n\n");
print_help(argv[-skip_args]);
print_help(argv[0]);
return 0;
}
if (use_sdr) {

View File

@ -17,6 +17,7 @@ cnetz_SOURCES = \
cnetz_LDADD = \
$(COMMON_LA) \
../anetz/libgermanton.a \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libdebug/libdebug.a \
$(top_builddir)/src/libmobile/libmobile.a \
$(top_builddir)/src/libdisplay/libdisplay.a \

View File

@ -19,15 +19,16 @@
#include <stdio.h>
#include <stdint.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "../libsample/sample.h"
#include "../libmobile/main_mobile.h"
#include "../libdebug/debug.h"
#include "../libmobile/call.h"
#include "../anetz/freiton.h"
#include "../anetz/besetztton.h"
#include "../liboptions/options.h"
#include "cnetz.h"
#include "database.h"
#include "sysinfo.h"
@ -216,198 +217,174 @@ static int atoi_limit(const char *p, int l1, int l2)
#define OPT_WARTESCHLANGE 256
static int handle_options(int argc, char **argv)
static void add_options(void)
{
main_mobile_add_options();
option_add('T', "channel-type", 1);
option_add('M', "measure-speed", 0);
option_add('C', "clock-speed", 1);
option_add('F', "flip-polarity", 1);
option_add('P', "ms-power", 1);
option_add('A', "authentication", 0);
option_add('Q', "queue", 1);
option_add(OPT_WARTESCHLANGE, "warteschlange", 1);
option_add('G', "gebuehren", 1);
option_add('S', "sysinfo", 1);
option_add('D', "demod", 1);
}
static int handle_options(int short_option, int argi, char **argv)
{
int skip_args = 0;
int rc;
const char *p;
static struct option long_options_special[] = {
{"channel-type", 1, 0, 'T'},
{"measure-speed", 0, 0, 'M'},
{"clock-speed", 1, 0, 'C'},
{"flip-polarity", 1, 0, 'F'},
{"ms-power", 1, 0, 'P'},
{"authentication", 0, 0, 'A'},
{"queue", 1, 0, 'Q'},
{"warteschlange", 1, 0, OPT_WARTESCHLANGE},
{"gebuehren", 1, 0, 'G'},
{"sysinfo", 1, 0, 'S'},
{"demod", 1, 0, 'D'},
{0, 0, 0, 0}
};
main_mobile_set_options("T:MC:F:P:AQ:G:S:D:", long_options_special);
while (1) {
int option_index = 0, c;
c = getopt_long(argc, argv, optstring, long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'T':
if (!strcmp(optarg, "list")) {
cnetz_channel_list();
exit(0);
}
rc = cnetz_channel_by_short_name(optarg);
if (rc < 0) {
fprintf(stderr, "Error, channel type '%s' unknown. Please use '-t list' to get a list. I suggest to use the default.\n", optarg);
exit(0);
}
OPT_ARRAY(num_chan_type, chan_type, rc)
skip_args += 2;
break;
case 'M':
measure_speed = 1;
skip_args++;
break;
case 'C':
p = strchr(optarg, ',');
if (!p) {
fprintf(stderr, "Illegal clock speed, use two values, seperated by comma and no spaces!\n");
exit(0);
}
clock_speed[0] = strtold(optarg, NULL);
clock_speed[1] = strtold(p + 1, NULL);
set_clock_speed = 1;
skip_args += 2;
break;
case 'F':
if (!strcasecmp(optarg, "no"))
flip_polarity = "no";
else if (!strcasecmp(optarg, "yes"))
flip_polarity = "yes";
else if (!strcasecmp(optarg, "auto"))
flip_polarity = "auto";
else {
fprintf(stderr, "Given polarity '%s' is illegal, see help!\n", optarg);
exit(0);
}
skip_args += 2;
break;
case 'P':
ms_power = atoi_limit(optarg, 0, 3);
skip_args += 2;
break;
case 'A':
auth = 1;
skip_args += 1;
break;
case 'Q':
case OPT_WARTESCHLANGE:
warteschlange = atoi_limit(optarg, 0, 1);;
skip_args += 2;
break;
case 'G':
metering = atoi(optarg);
skip_args += 2;
break;
case 'S':
p = strchr(optarg, '=');
if (!p) {
fprintf(stderr, "Given sysinfo parameter '%s' requires '=' character to set value, see help!\n", optarg);
exit(0);
}
p++;
if (!strncasecmp(optarg, "fuz-nat=", p - optarg)) {
fuz_nat = atoi_limit(p, 0, 7);
} else
if (!strncasecmp(optarg, "fuz-fuvst=", p - optarg)) {
fuz_fuvst = atoi_limit(p, 0, 32);
} else
if (!strncasecmp(optarg, "fuz-rest=", p - optarg)) {
fuz_rest = atoi_limit(p, 0, 255);
} else
if (!strncasecmp(optarg, "kennung-fufst=", p - optarg)) {
kennung_fufst = atoi_limit(p, 0, 3);
} else
if (!strncasecmp(optarg, "ws-kennung=", p - optarg)) {
ws_kennung = atoi_limit(p, 0, 3);
} else
if (!strncasecmp(optarg, "fuvst-sperren=", p - optarg)) {
fuvst_sperren = atoi_limit(p, 0, 3);
} else
if (!strncasecmp(optarg, "grenz-einbuchen=", p - optarg)) {
grenz_einbuchen = atoi_limit(p, 0, 7);
} else
if (!strncasecmp(optarg, "grenz-umschalten=", p - optarg)) {
grenz_umschalten = atoi_limit(p, 0, 15);
} else
if (!strncasecmp(optarg, "grenz-ausloesen=", p - optarg)) {
grenz_ausloesen = atoi_limit(p, 0, 15);
} else
if (!strncasecmp(optarg, "mittel-umschalten=", p - optarg)) {
mittel_umschalten = atoi_limit(p, 0, 5);
} else
if (!strncasecmp(optarg, "mittel-ausloesen=", p - optarg)) {
mittel_ausloesen = atoi_limit(p, 0, 5);
} else
if (!strncasecmp(optarg, "genauigkeit=", p - optarg)) {
genauigkeit = atoi_limit(p, 0, 1);
} else
if (!strncasecmp(optarg, "bewertung=", p - optarg)) {
bewertung = atoi_limit(p, 0, 1);
} else
if (!strncasecmp(optarg, "entfernung=", p - optarg)) {
entfernung = atoi_limit(p, 0, 15);
} else
if (!strncasecmp(optarg, "nachbar-prio=", p - optarg)) {
nachbar_prio = atoi_limit(p, 0, 1);
} else
if (!strncasecmp(optarg, "futln-sperre=", p - optarg)) {
char value[128], *v, *q;
strncpy(value, p, sizeof(value) - 1);
value[sizeof(value) - 1] = '\0';
v = value;
q = strchr(value, '-');
if (q)
*q++ = '\0';
if (strlen(v) > 5)
v += strlen(v) - 5;
futln_sperre_start = atoi(v) & 0xf;
if (q) {
if (strlen(q) > 5)
q += strlen(q) - 5;
futln_sperre_end = atoi(q) & 0xf;
}
} else
{
fprintf(stderr, "Given sysinfo parameter '%s' unknown, see help!\n", optarg);
exit(0);
}
skip_args += 2;
break;
case 'D':
if (!strcasecmp(optarg, "auto"))
demod = FSK_DEMOD_AUTO;
else if (!strcasecmp(optarg, "slope"))
demod = FSK_DEMOD_SLOPE;
else if (!strcasecmp(optarg, "level"))
demod = FSK_DEMOD_LEVEL;
else {
fprintf(stderr, "Given demodulation type '%s' is illegal, see help!\n", optarg);
exit(0);
}
skip_args += 2;
break;
default:
main_mobile_opt_switch(c, argv[0], &skip_args);
switch (short_option) {
case 'T':
if (!strcmp(argv[argi], "list")) {
cnetz_channel_list();
return 0;
}
rc = cnetz_channel_by_short_name(argv[argi]);
if (rc < 0) {
fprintf(stderr, "Error, channel type '%s' unknown. Please use '-t list' to get a list. I suggest to use the default.\n", argv[argi]);
return -EINVAL;
}
OPT_ARRAY(num_chan_type, chan_type, rc)
break;
case 'M':
measure_speed = 1;
break;
case 'C':
p = strchr(argv[argi], ',');
if (!p) {
fprintf(stderr, "Illegal clock speed, use two values, seperated by comma and no spaces!\n");
return -EINVAL;
}
clock_speed[0] = strtold(argv[argi], NULL);
clock_speed[1] = strtold(p + 1, NULL);
set_clock_speed = 1;
break;
case 'F':
if (!strcasecmp(argv[argi], "no"))
flip_polarity = "no";
else if (!strcasecmp(argv[argi], "yes"))
flip_polarity = "yes";
else if (!strcasecmp(argv[argi], "auto"))
flip_polarity = "auto";
else {
fprintf(stderr, "Given polarity '%s' is illegal, use '-h' for help!\n", argv[argi]);
return -EINVAL;
}
break;
case 'P':
ms_power = atoi_limit(argv[argi], 0, 3);
break;
case 'A':
auth = 1;
break;
case 'Q':
case OPT_WARTESCHLANGE:
warteschlange = atoi_limit(argv[argi], 0, 1);;
break;
case 'G':
metering = atoi(argv[argi]);
break;
case 'S':
p = strchr(argv[argi], '=');
if (!p) {
fprintf(stderr, "Given sysinfo parameter '%s' requires '=' character to set value, use '-h' for help!\n", argv[argi]);
return -EINVAL;
}
p++;
if (!strncasecmp(argv[argi], "fuz-nat=", p - argv[argi])) {
fuz_nat = atoi_limit(p, 0, 7);
} else
if (!strncasecmp(argv[argi], "fuz-fuvst=", p - argv[argi])) {
fuz_fuvst = atoi_limit(p, 0, 32);
} else
if (!strncasecmp(argv[argi], "fuz-rest=", p - argv[argi])) {
fuz_rest = atoi_limit(p, 0, 255);
} else
if (!strncasecmp(argv[argi], "kennung-fufst=", p - argv[argi])) {
kennung_fufst = atoi_limit(p, 0, 3);
} else
if (!strncasecmp(argv[argi], "ws-kennung=", p - argv[argi])) {
ws_kennung = atoi_limit(p, 0, 3);
} else
if (!strncasecmp(argv[argi], "fuvst-sperren=", p - argv[argi])) {
fuvst_sperren = atoi_limit(p, 0, 3);
} else
if (!strncasecmp(argv[argi], "grenz-einbuchen=", p - argv[argi])) {
grenz_einbuchen = atoi_limit(p, 0, 7);
} else
if (!strncasecmp(argv[argi], "grenz-umschalten=", p - argv[argi])) {
grenz_umschalten = atoi_limit(p, 0, 15);
} else
if (!strncasecmp(argv[argi], "grenz-ausloesen=", p - argv[argi])) {
grenz_ausloesen = atoi_limit(p, 0, 15);
} else
if (!strncasecmp(argv[argi], "mittel-umschalten=", p - argv[argi])) {
mittel_umschalten = atoi_limit(p, 0, 5);
} else
if (!strncasecmp(argv[argi], "mittel-ausloesen=", p - argv[argi])) {
mittel_ausloesen = atoi_limit(p, 0, 5);
} else
if (!strncasecmp(argv[argi], "genauigkeit=", p - argv[argi])) {
genauigkeit = atoi_limit(p, 0, 1);
} else
if (!strncasecmp(argv[argi], "bewertung=", p - argv[argi])) {
bewertung = atoi_limit(p, 0, 1);
} else
if (!strncasecmp(argv[argi], "entfernung=", p - argv[argi])) {
entfernung = atoi_limit(p, 0, 15);
} else
if (!strncasecmp(argv[argi], "nachbar-prio=", p - argv[argi])) {
nachbar_prio = atoi_limit(p, 0, 1);
} else
if (!strncasecmp(argv[argi], "futln-sperre=", p - argv[argi])) {
char value[128], *v, *q;
strncpy(value, p, sizeof(value) - 1);
value[sizeof(value) - 1] = '\0';
v = value;
q = strchr(value, '-');
if (q)
*q++ = '\0';
if (strlen(v) > 5)
v += strlen(v) - 5;
futln_sperre_start = atoi(v) & 0xf;
if (q) {
if (strlen(q) > 5)
q += strlen(q) - 5;
futln_sperre_end = atoi(q) & 0xf;
}
} else
{
fprintf(stderr, "Given sysinfo parameter '%s' unknown, use '-h' for help!\n", argv[argi]);
return -EINVAL;
}
break;
case 'D':
if (!strcasecmp(argv[argi], "auto"))
demod = FSK_DEMOD_AUTO;
else if (!strcasecmp(argv[argi], "slope"))
demod = FSK_DEMOD_SLOPE;
else if (!strcasecmp(argv[argi], "level"))
demod = FSK_DEMOD_LEVEL;
else {
fprintf(stderr, "Given demodulation type '%s' is illegal, use '-h' for help!\n", argv[argi]);
return -EINVAL;
}
break;
default:
return main_mobile_handle_options(short_option, argi, argv);
}
free(long_options);
return skip_args;
return 1;
}
int main(int argc, char *argv[])
{
int rc;
int skip_args;
int rc, argi;
const char *station_id = "";
int mandatory = 0;
int polarity;
@ -422,12 +399,17 @@ int main(int argc, char *argv[])
main_mobile_init();
skip_args = handle_options(argc, argv);
argc -= skip_args;
argv += skip_args;
/* handle options / config file */
add_options();
rc = options_config_file("~/.osmocom/analog/cnetz.conf", handle_options);
if (rc < 0)
return 0;
argi = options_command_line(argc, argv, handle_options);
if (argi <= 0)
return argi;
if (argc > 1) {
station_id = argv[1];
if (argi < argc) {
station_id = argv[argi];
if (strlen(station_id) != 7) {
printf("Given station ID '%s' does not have 7 digits\n", station_id);
return 0;
@ -470,7 +452,7 @@ int main(int argc, char *argv[])
}
if (mandatory) {
print_help(argv[-skip_args]);
print_help(argv[0]);
return 0;
}

View File

@ -11,6 +11,7 @@ jollycom_SOURCES = \
jollycom_LDADD = \
$(COMMON_LA) \
../anetz/libgermanton.a \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libdebug/libdebug.a \
$(top_builddir)/src/libmobile/libmobile.a \
$(top_builddir)/src/libdisplay/libdisplay.a \

View File

@ -1,4 +1,4 @@
/* main
/* JollyCom main
*
* (C) 2017 by Andreas Eversberg <jolly@eversberg.eu>
* All Rights Reserved
@ -19,11 +19,11 @@
#include <stdio.h>
#include <stdint.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
@ -34,6 +34,7 @@
#include "../libmncc/mncc_sock.h"
#include "../anetz/freiton.h"
#include "../anetz/besetztton.h"
#include "../liboptions/options.h"
#include "jolly.h"
#include "dsp.h"
#include "voice.h"
@ -70,73 +71,55 @@ void print_help(const char *arg0)
main_mobile_print_hotkeys();
}
static int handle_options(int argc, char **argv)
static void add_options(void)
{
int skip_args = 0;
main_mobile_add_options();
option_add('F', "frequency", 1);
option_add('S', "squelch", 1);
option_add('N', "nbfm", 0);
option_add('R', "repeater", 0);
}
static struct option long_options_special[] = {
{"frequency", 1, 0, 'F'},
{"squelch", 1, 0, 'S'},
{"nbfm", 0, 0, 'N'},
{"repeater", 0, 0, 'R'},
{0, 0, 0, 0}
};
static int handle_options(int short_option, int argi, char **argv)
{
char *string, *string_dl, *string_ul, *string_step;
main_mobile_set_options("F:S:NR", long_options_special);
while (1) {
int option_index = 0, c;
char *string, *string_dl, *string_ul, *string_step;
c = getopt_long(argc, argv, optstring, long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'F':
string = strdup(optarg);
string_dl = strsep(&string, ",");
string_ul = strsep(&string, ",");
string_step = strsep(&string, ",");
if (!string_dl || !string_ul || !string_step) {
fprintf(stderr, "Please give 3 values for --frequency, seperated by comma and no space!\n");
exit(0);
}
dl_freq = atof(string_dl);
ul_freq = atof(string_ul);
step = atof(string_step);
skip_args += 2;
break;
case 'S':
if (!strcasecmp(optarg, "auto"))
squelch_db = 0.0;
else
squelch_db = atof(optarg);
skip_args += 2;
break;
case 'N':
nbfm = 1;
skip_args += 1;
break;
case 'R':
repeater = 1;
skip_args += 1;
break;
default:
main_mobile_opt_switch(c, argv[0], &skip_args);
switch (short_option) {
case 'F':
string = strdup(argv[argi]);
string_dl = strsep(&string, ",");
string_ul = strsep(&string, ",");
string_step = strsep(&string, ",");
if (!string_dl || !string_ul || !string_step) {
fprintf(stderr, "Please give 3 values for --frequency, seperated by comma and no space!\n");
exit(0);
}
dl_freq = atof(string_dl);
ul_freq = atof(string_ul);
step = atof(string_step);
break;
case 'S':
if (!strcasecmp(argv[argi], "auto"))
squelch_db = 0.0;
else
squelch_db = atof(argv[argi]);
break;
case 'N':
nbfm = 1;
break;
case 'R':
repeater = 1;
break;
default:
return main_mobile_handle_options(short_option, argi, argv);
}
free(long_options);
return skip_args;
return 1;
}
int main(int argc, char *argv[])
{
int rc;
int skip_args;
int rc, argi;
const char *station_id = "";
int mandatory = 0;
int i;
@ -148,12 +131,17 @@ int main(int argc, char *argv[])
main_mobile_init();
skip_args = handle_options(argc, argv);
argc -= skip_args;
argv += skip_args;
/* handle options / config file */
add_options();
rc = options_config_file("~/.osmocom/analog/jollycom.conf", handle_options);
if (rc < 0)
return 0;
argi = options_command_line(argc, argv, handle_options);
if (argi <= 0)
return argi;
if (argc > 1) {
station_id = argv[1];
if (argi < argc) {
station_id = argv[argi];
if (strlen(station_id) != 4) {
printf("Given station ID '%s' does not have 4 digits\n", station_id);
return 0;
@ -178,7 +166,7 @@ int main(int argc, char *argv[])
}
if (mandatory) {
print_help(argv[-skip_args]);
print_help(argv[0]);
return 0;
}

View File

@ -12,6 +12,7 @@ jtacs_SOURCES = \
jtacs_LDADD = \
$(COMMON_LA) \
../amps/libamps.a \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libdebug/libdebug.a \
$(top_builddir)/src/libmobile/libmobile.a \
$(top_builddir)/src/libdisplay/libdisplay.a \

View File

@ -41,6 +41,7 @@ struct debug_cat {
const char *name;
const char *color;
} debug_cat[] = {
{ "options", "\033[1;37m" },
{ "sender", "\033[1;33m" },
{ "sound", "\033[0;35m" },
{ "dsp", "\033[0;31m" },

View File

@ -4,28 +4,29 @@
#define DEBUG_NOTICE 2 /* something unexpected happens */
#define DEBUG_ERROR 3 /* there is an error with this software */
#define DSENDER 0
#define DSOUND 1
#define DDSP 2
#define DANETZ 3
#define DBNETZ 4
#define DCNETZ 5
#define DNMT 6
#define DAMPS 7
#define DR2000 8
#define DJOLLY 9
#define DFRAME 10
#define DCALL 11
#define DMNCC 12
#define DDB 13
#define DTRANS 14
#define DDMS 15
#define DSMS 16
#define DSDR 17
#define DUHD 18
#define DSOAPY 19
#define DWAVE 20
#define DRADIO 21
#define DOPTIONS 0
#define DSENDER 1
#define DSOUND 2
#define DDSP 3
#define DANETZ 4
#define DBNETZ 5
#define DCNETZ 6
#define DNMT 7
#define DAMPS 8
#define DR2000 9
#define DJOLLY 10
#define DFRAME 11
#define DCALL 12
#define DMNCC 13
#define DDB 14
#define DTRANS 15
#define DDMS 16
#define DSMS 17
#define DSDR 18
#define DUHD 19
#define DSOAPY 20
#define DWAVE 21
#define DRADIO 22
void get_win_size(int *w, int *h);

View File

@ -19,7 +19,6 @@
#include <stdio.h>
#include <stdint.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
@ -28,7 +27,6 @@
#include <math.h>
#include <termios.h>
#include <errno.h>
#include <getopt.h>
#include "../libsample/sample.h"
#include "main_mobile.h"
#include "../libdebug/debug.h"
@ -42,6 +40,7 @@
#include "../libsdr/sdr.h"
#include "../libsdr/sdr_config.h"
#endif
#include "../liboptions/options.h"
#define DEFAULT_LO_OFFSET -1000000.0
@ -153,6 +152,8 @@ void main_mobile_print_help(const char *arg0, const char *ext_usage)
printf(" --read-tx-wave <file>\n");
printf(" Replace transmitted audio by given wave file.\n");
#ifdef HAVE_SDR
printf(" --limesdr\n");
printf(" Auto-select several required options for LimeSDR\n");
sdr_config_print_help();
#endif
printf("\nNetwork specific options:\n");
@ -178,214 +179,167 @@ void main_mobile_print_hotkeys(void)
#define OPT_READ_TX_WAVE 1004
#define OPT_CALL_SAMPLERATE 1005
#define OPT_MNCC_NAME 1006
#define OPT_LIMESDR 1100
static struct option main_mobile_long_options[] = {
{"help", 0, 0, 'h'},
{"debug", 1, 0, 'v'},
{"kanal", 1, 0, 'k'},
{"channel", 1, 0, OPT_CHANNEL},
{"audio-device", 1, 0, 'a'},
{"samplerate", 1, 0, 's'},
{"interval", 1, 0, 'i'},
{"buffer", 1, 0, 'b'},
{"pre-emphasis", 0, 0, 'p'},
{"de-emphasis", 0, 0, 'd'},
{"rx-gain", 1, 0, 'g'},
{"echo-test", 0, 0, 'e'},
{"mncc-cross", 0, 0, 'x'},
{"mncc-sock", 0, 0, 'm'},
{"mncc-name", 1, 0, OPT_MNCC_NAME},
{"call-device", 1, 0, 'c'},
{"call-samplerate", 1, 0, OPT_CALL_SAMPLERATE},
{"tones", 0, 0, 't'},
{"loopback", 1, 0, 'l'},
{"realtime", 1, 0, 'r'},
{"write-rx-wave", 1, 0, OPT_WRITE_RX_WAVE},
{"write-tx-wave", 1, 0, OPT_WRITE_TX_WAVE},
{"read-rx-wave", 1, 0, OPT_READ_RX_WAVE},
{"read-tx-wave", 1, 0, OPT_READ_TX_WAVE},
{0, 0, 0, 0}
void main_mobile_add_options(void)
{
option_add('h', "help", 0);
option_add('v', "debug", 1);
option_add('k', "kanal", 1);
option_add(OPT_CHANNEL, "channel", 1);
option_add('a', "audio-device", 1);
option_add('s', "samplerate", 1);
option_add('i', "interval", 1);
option_add('b', "buffer", 1);
option_add('p', "pre-emphasis", 0);
option_add('d', "de-emphasis", 0);
option_add('g', "rx-gain", 1);
option_add('e', "echo-test", 0);
option_add('x', "mncc-cross", 0);
option_add('m', "mncc-sock", 0);
option_add(OPT_MNCC_NAME, "mncc-name", 1);
option_add('c', "call-device", 1);
option_add(OPT_CALL_SAMPLERATE, "call-samplerate", 1);
option_add('t', "tones", 0);
option_add('l', "loopback", 1);
option_add('r', "realtime", 1);
option_add(OPT_WRITE_RX_WAVE, "write-rx-wave", 1);
option_add(OPT_WRITE_TX_WAVE, "write-tx-wave", 1);
option_add(OPT_READ_RX_WAVE, "read-rx-wave", 1);
option_add(OPT_READ_TX_WAVE, "read-tx-wave", 1);
#ifdef HAVE_SDR
option_add(OPT_LIMESDR, "limesdr", 0);
sdr_config_add_options();
#endif
};
static const char *main_mobile_optstring = "hv:k:a:s:i:b:pdg:exmc:t:l:r:";
struct option *long_options;
char *optstring;
static void check_duplicate_option(int num, struct option *option)
{
int i;
for (i = 0; i < num; i++) {
if (long_options[i].val == option->val) {
fprintf(stderr, "Duplicate option %d. Please fix!\n", option->val);
abort();
}
}
}
void main_mobile_set_options(const char *optstring_special, struct option *long_options_special)
{
int i = 0, j;
long_options = calloc(sizeof(*long_options), 256);
for (j = 0; main_mobile_long_options[j].name; i++, j++) {
check_duplicate_option(i, &main_mobile_long_options[j]);
memcpy(&long_options[i], &main_mobile_long_options[j], sizeof(*long_options));
}
#ifdef HAVE_SDR
for (j = 0; sdr_config_long_options[j].name; i++, j++) {
check_duplicate_option(i, &sdr_config_long_options[j]);
memcpy(&long_options[i], &sdr_config_long_options[j], sizeof(*long_options));
}
#endif
for (; long_options_special->name; i++) {
check_duplicate_option(i, long_options_special);
memcpy(&long_options[i], long_options_special++, sizeof(*long_options));
}
optstring = calloc(256, 2);
strcpy(optstring, main_mobile_optstring);
#ifdef HAVE_SDR
strcat(optstring, sdr_config_optstring);
#endif
strcat(optstring, optstring_special);
}
void print_help(const char *arg0);
void main_mobile_opt_switch(int c, char *arg0, int *skip_args)
int main_mobile_handle_options(int short_option, int argi, char **argv)
{
double gain_db;
#ifdef HAVE_SDR
int rc;
#endif
switch (c) {
switch (short_option) {
case 'h':
print_help(arg0);
exit(0);
print_help(argv[0]);
return 0;
case 'v':
if (!strcasecmp(optarg, "list")) {
if (!strcasecmp(argv[argi], "list")) {
debug_list_cat();
exit(0);
return 0;
}
if (parse_debug_opt(optarg)) {
rc = parse_debug_opt(argv[argi]);
if (rc < 0) {
fprintf(stderr, "Failed to parse debug option, please use -h for help.\n");
exit(0);
return rc;
}
*skip_args += 2;
break;
case 'k':
case OPT_CHANNEL:
OPT_ARRAY(num_kanal, kanal, atoi(optarg))
*skip_args += 2;
OPT_ARRAY(num_kanal, kanal, atoi(argv[argi]))
break;
case 'a':
OPT_ARRAY(num_audiodev, audiodev, strdup(optarg))
*skip_args += 2;
OPT_ARRAY(num_audiodev, audiodev, strdup(argv[argi]))
break;
case 's':
samplerate = atoi(optarg);
*skip_args += 2;
samplerate = atoi(argv[argi]);
break;
case 'i':
interval = atoi(optarg);
*skip_args += 2;
interval = atoi(argv[argi]);
if (interval < 1)
interval = 1;
if (interval > 25)
interval = 25;
break;
case 'b':
latency = atoi(optarg);
*skip_args += 2;
latency = atoi(argv[argi]);
break;
case 'p':
if (!uses_emphasis) {
no_emph:
fprintf(stderr, "This network does not use emphasis, please do not enable pre- or de-emphasis! Disable emphasis on transceiver, if possible.\n");
exit(0);
return -EINVAL;
}
do_pre_emphasis = 1;
*skip_args += 1;
break;
case 'd':
if (!uses_emphasis)
goto no_emph;
do_de_emphasis = 1;
*skip_args += 1;
break;
case 'g':
gain_db = atof(optarg);
gain_db = atof(argv[argi]);
if (gain_db < 0.0) {
fprintf(stderr, "Given gain is below 0. To reduce RX signal, use sound card's mixer (or resistor net)!\n");
exit(0);
return -EINVAL;
}
rx_gain = pow(10, gain_db / 20.0);
*skip_args += 2;
break;
case 'e':
echo_test = 1;
*skip_args += 1;
break;
case 'x':
use_mncc_cross = 1;
*skip_args += 1;
break;
case 'm':
use_mncc_sock = 1;
*skip_args += 1;
break;
case OPT_MNCC_NAME:
mncc_name = strdup(optarg);
*skip_args += 2;
mncc_name = strdup(argv[argi]);
break;
case 'c':
call_audiodev = strdup(optarg);
*skip_args += 2;
call_audiodev = strdup(argv[argi]);
break;
case OPT_CALL_SAMPLERATE:
call_samplerate = atoi(optarg);
*skip_args += 2;
call_samplerate = atoi(argv[argi]);
break;
case 't':
send_patterns = atoi(optarg);
*skip_args += 2;
send_patterns = atoi(argv[argi]);
break;
case 'l':
loopback = atoi(optarg);
*skip_args += 2;
loopback = atoi(argv[argi]);
break;
case 'r':
rt_prio = atoi(optarg);
*skip_args += 2;
rt_prio = atoi(argv[argi]);
break;
case OPT_WRITE_RX_WAVE:
write_rx_wave = strdup(optarg);
*skip_args += 2;
write_rx_wave = strdup(argv[argi]);
break;
case OPT_WRITE_TX_WAVE:
write_tx_wave = strdup(optarg);
*skip_args += 2;
write_tx_wave = strdup(argv[argi]);
break;
case OPT_READ_RX_WAVE:
read_rx_wave = strdup(optarg);
*skip_args += 2;
read_rx_wave = strdup(argv[argi]);
break;
case OPT_READ_TX_WAVE:
read_tx_wave = strdup(optarg);
*skip_args += 2;
read_tx_wave = strdup(argv[argi]);
break;
#ifdef HAVE_SDR
case OPT_LIMESDR:
{
char *argv_lime[] = { argv[0],
"--sdr-soapy",
"--sdr-rx-antenna", "LNAL",
"--sdr-rx-gain", "30",
"--sdr-tx-gain", "30",
"--sdr-samplerate", "5000000",
"--sdr-bandwidth", "15000000",
"-s", "200000",
};
int argc_lime = sizeof(argv_lime) / sizeof (*argv_lime);
return options_command_line(argc_lime, argv_lime, main_mobile_handle_options);
}
#endif
default:
#ifdef HAVE_SDR
rc = sdr_config_opt_switch(c, skip_args);
if (rc < 0)
exit (0);
return sdr_config_handle_options(short_option, argi, argv);
#else
return -EINVAL;
#endif
break;
}
return 1;
}
/* global variable to quit main loop */

View File

@ -22,10 +22,8 @@ extern const char *read_tx_wave;
void main_mobile_init(void);
void main_mobile_print_help(const char *arg0, const char *ext_usage);
void main_mobile_print_hotkeys(void);
extern struct option *long_options;
extern char *optstring;
void main_mobile_set_options(const char *optstring_special, struct option *long_options_special);
void main_mobile_opt_switch(int c, char *arg0, int *skip_args);
void main_mobile_add_options(void);
int main_mobile_handle_options(int short_option, int argi, char **argv);
#define OPT_ARRAY(num_name, name, value) \
{ \

View File

@ -0,0 +1,7 @@
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes)
noinst_LIBRARIES = liboptions.a
liboptions_a_SOURCES = \
options.c

221
src/liboptions/options.c Normal file
View File

@ -0,0 +1,221 @@
/* command line options and config file parsing
*
* (C) 2018 by Andreas Eversberg <jolly@eversberg.eu>
* All Rights Reserved
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "options.h"
#include "../libdebug/debug.h"
typedef struct option {
struct option *next;
int short_option;
const char *long_option;
int parameter_count;
} option_t;
static option_t *option_head = NULL;
static option_t **option_tailp = &option_head;
static int first_option = 1;
void option_add(int short_option, const char *long_option, int parameter_count)
{
option_t *option;
/* check if option already exists */
for (option = option_head; option; option = option->next) {
if (option->short_option == short_option
|| !strcmp(option->long_option, long_option)) {
PDEBUG(DOPTIONS, DEBUG_ERROR, "Option '%s' added twice, please fix!\n", option->long_option);
abort();
}
}
option = calloc(1, sizeof(*option));
if (!option) {
PDEBUG(DOPTIONS, DEBUG_ERROR, "No mem!\n");
abort();
}
option->short_option = short_option;
option->long_option = long_option;
option->parameter_count = parameter_count;
*option_tailp = option;
option_tailp = &(option->next);
}
// FIXME: support more than one option */
int options_config_file(const char *config_file, int (*handle_options)(int short_option, int argi, char *argv[]))
{
static const char *home;
char config[256];
FILE *fp;
char buffer[256], opt[256], param[256], *p, *argv[1];
int line;
int rc = 1;
int i;
option_t *option;
/* open config file */
home = getenv("HOME");
if (home == NULL)
return 1;
sprintf(config, "%s/%s", home, config_file + 2);
fp = fopen(config, "r");
if (!fp) {
PDEBUG(DOPTIONS, DEBUG_INFO, "Config file '%s' seems not to exist, using command line options only.\n", config);
return 1;
}
/* parse config file */
line = 0;
while((fgets(buffer, sizeof(buffer), fp))) {
line++;
/* prevent buffer overflow */
buffer[sizeof(buffer) - 1] = '\0';
/* cut away new-line and white spaces */
while (buffer[0] && buffer[strlen(buffer) - 1] <= ' ')
buffer[strlen(buffer) - 1] = '\0';
p = buffer;
/* remove white spaces in front of first keyword */
while (*p > '\0' && *p <= ' ')
p++;
/* ignore '#' lines */
if (*p == '#')
continue;
/* get option form line */
i = 0;
while (*p > ' ')
opt[i++] = *p++;
opt[i] = '\0';
if (opt[0] == '\0')
continue;
/* skip white spaces behind option */
while (*p > '\0' && *p <= ' ')
p++;
/* get param from line */
i = 0;
while (*p > ' ')
param[i++] = *p++;
param[i] = '\0';
/* search option */
for (option = option_head; option; option = option->next) {
if (opt[0] == option->short_option && opt[1] == '\0') {
PDEBUG(DOPTIONS, DEBUG_INFO, "Config file option '%s' ('%s'), parameter '%s'\n", opt, option->long_option, param);
break;
}
if (!strcmp(opt, option->long_option)) {
PDEBUG(DOPTIONS, DEBUG_INFO, "Config file option '%s', parameter '%s'\n", opt, param);
break;
}
}
if (!option) {
PDEBUG(DOPTIONS, DEBUG_ERROR, "Given option '%s' in config file '%s' at line %d is not a valid option, use '-h' for help!\n", opt, config_file, line);
rc = -EINVAL;
goto done;
}
if (option->parameter_count && !param[0]) {
PDEBUG(DOPTIONS, DEBUG_ERROR, "Given option '%s' in config file '%s' at line %d requires %d parameter(s), use '-h' for help!\n", opt, config_file, line, option->parameter_count);
return -EINVAL;
}
argv[0] = param;
rc = handle_options(option->short_option, 0, argv);
if (rc <= 0)
goto done;
first_option = 0;
}
done:
/* close config file */
fclose(fp);
return rc;
}
int options_command_line(int argc, char *argv[], int (*handle_options)(int short_option, int argi, char *argv[]))
{
option_t *option;
int argi, i;
int rc;
for (argi = 1; argi < argc; argi++) {
if (argv[argi][0] == '-') {
if (argv[argi][1] != '-') {
if (strlen(argv[argi]) != 2) {
PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' exceeds one character, use '-h' for help!\n", argv[argi]);
return -EINVAL;
}
/* -x */
for (option = option_head; option; option = option->next) {
if (argv[argi][1] == option->short_option) {
if (option->parameter_count && argi + option->parameter_count < argc)
PDEBUG(DOPTIONS, DEBUG_INFO, "Command line option '%s' ('--%s'), parameter '%s'\n", argv[argi], option->long_option, argv[argi + 1]);
else
PDEBUG(DOPTIONS, DEBUG_INFO, "Command line option '%s' ('--%s')\n", argv[argi], option->long_option);
break;
}
}
} else {
/* --xxxxxx */
for (option = option_head; option; option = option->next) {
if (!strcmp(argv[argi] + 2, option->long_option)) {
if (option->parameter_count && argi + option->parameter_count < argc)
PDEBUG(DOPTIONS, DEBUG_INFO, "Command line option '%s', parameter '%s'\n", argv[argi], argv[argi + 1]);
else
PDEBUG(DOPTIONS, DEBUG_INFO, "Command line option '%s'\n", argv[argi]);
break;
}
}
}
if (!option) {
PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' is not a valid option, use '-h' for help!\n", argv[argi]);
return -EINVAL;
}
if (argi + option->parameter_count >= argc) {
PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' requires %d parameter(s), use '-h' for help!\n", argv[argi], option->parameter_count);
return -EINVAL;
}
rc = handle_options(option->short_option, argi + 1, argv);
if (rc <= 0)
return rc;
first_option = 0;
argi += option->parameter_count;
} else
break;
}
/* no more options, so we check if there is an option after a non-option parameter */
for (i = argi; i < argc; i++) {
if (argv[i][0] == '-') {
PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' behind command line parameter '%s' not allowed! Please put all command line options before command line parameter(s).\n", argv[i], argv[argi]);
return -EINVAL;
}
}
return argi;
}
int option_is_first(void)
{
return first_option;
}

6
src/liboptions/options.h Normal file
View File

@ -0,0 +1,6 @@
void option_add(int short_option, const char *long_option, int parameter_count);
int options_config_file(const char *config_file, int (*handle_options)(int short_option, int argi, char *argv[]));
int options_command_line(int argc, char *argv[], int (*handle_options)(int short_option, int argi, char *argv[]));
int option_is_first(void);

View File

@ -25,7 +25,6 @@ enum paging_signal;
#include <string.h>
#include <errno.h>
#include <math.h>
#include <getopt.h>
#define __USE_GNU
#include <pthread.h>
#include <unistd.h>

View File

@ -23,8 +23,9 @@ enum paging_signal;
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <getopt.h>
#include <errno.h>
#include "../libsample/sample.h"
#include "../liboptions/options.h"
#include "sdr.h"
#include "sdr_config.h"
@ -122,43 +123,40 @@ void sdr_config_print_hotkeys(void)
#define OPT_SDR_SWAP_LINKS 1517
#define OPT_SDR_UHD_TX_TS 1518
struct option sdr_config_long_options[] = {
{"sdr-uhd", 0, 0, OPT_SDR_UHD},
{"sdr-soapy", 0, 0, OPT_SDR_SOAPY},
{"sdr-channel", 1, 0, OPT_SDR_CHANNEL},
{"sdr-device-args", 1, 0, OPT_SDR_DEVICE_ARGS},
{"sdr-stream-args", 1, 0, OPT_SDR_STREAM_ARGS},
{"sdr-tune-args", 1, 0, OPT_SDR_TUNE_ARGS},
{"sdr-samplerate", 1, 0, OPT_SDR_SAMPLERATE},
{"sdr-lo-offset", 1, 0, OPT_SDR_LO_OFFSET},
{"sdr-bandwidth", 1, 0, OPT_SDR_BANDWIDTH},
{"sdr-rx-antenna", 1, 0, OPT_SDR_RX_ANTENNA},
{"sdr-tx-antenna", 1, 0, OPT_SDR_TX_ANTENNA},
{"sdr-rx-gain", 1, 0, OPT_SDR_RX_GAIN},
{"sdr-tx-gain", 1, 0, OPT_SDR_TX_GAIN},
{"write-iq-rx-wave", 1, 0, OPT_WRITE_IQ_RX_WAVE},
{"write-iq-tx-wave", 1, 0, OPT_WRITE_IQ_TX_WAVE},
{"read-iq-rx-wave", 1, 0, OPT_READ_IQ_RX_WAVE},
{"read-iq-tx-wave", 1, 0, OPT_READ_IQ_TX_WAVE},
{"sdr-swap-links", 0, 0, OPT_SDR_SWAP_LINKS},
{"sdr-uhd-tx-timestamps", 0, 0, OPT_SDR_UHD_TX_TS},
{0, 0, 0, 0}
};
const char *sdr_config_optstring = "";
int sdr_config_opt_switch(int c, int *skip_args)
void sdr_config_add_options(void)
{
switch (c) {
option_add(OPT_SDR_UHD, "sdr-uhd", 0);
option_add(OPT_SDR_SOAPY, "sdr-soapy", 0);
option_add(OPT_SDR_CHANNEL, "sdr-channel", 1);
option_add(OPT_SDR_DEVICE_ARGS, "sdr-device-args", 1);
option_add(OPT_SDR_STREAM_ARGS, "sdr-stream-args", 1);
option_add(OPT_SDR_TUNE_ARGS, "sdr-tune-args", 1);
option_add(OPT_SDR_SAMPLERATE, "sdr-samplerate", 1);
option_add(OPT_SDR_LO_OFFSET, "sdr-lo-offset", 1);
option_add(OPT_SDR_BANDWIDTH, "sdr-bandwidth", 1);
option_add(OPT_SDR_RX_ANTENNA, "sdr-rx-antenna", 1);
option_add(OPT_SDR_TX_ANTENNA, "sdr-tx-antenna", 1);
option_add(OPT_SDR_RX_GAIN, "sdr-rx-gain", 1);
option_add(OPT_SDR_TX_GAIN, "sdr-tx-gain", 1);
option_add(OPT_WRITE_IQ_RX_WAVE, "write-iq-rx-wave", 1);
option_add(OPT_WRITE_IQ_TX_WAVE, "write-iq-tx-wave", 1);
option_add(OPT_READ_IQ_RX_WAVE, "read-iq-rx-wave", 1);
option_add(OPT_READ_IQ_TX_WAVE, "read-iq-tx-wave", 1);
option_add(OPT_SDR_SWAP_LINKS, "sdr-swap-links", 0);
option_add(OPT_SDR_UHD_TX_TS, "sdr-uhd-tx-timestamps", 0);
}
int sdr_config_handle_options(int short_option, int argi, char **argv)
{
switch (short_option) {
case OPT_SDR_UHD:
#ifdef HAVE_UHD
sdr_config->uhd = 1;
use_sdr = 1;
#else
fprintf(stderr, "UHD SDR support not compiled in!\n");
exit(0);
return -EINVAL;
#endif
*skip_args += 1;
break;
case OPT_SDR_SOAPY:
#ifdef HAVE_SOAPY
@ -166,83 +164,65 @@ int sdr_config_opt_switch(int c, int *skip_args)
use_sdr = 1;
#else
fprintf(stderr, "SoapySDR support not compiled in!\n");
exit(0);
return -EINVAL;
#endif
*skip_args += 1;
break;
case OPT_SDR_CHANNEL:
sdr_config->channel = atoi(optarg);
*skip_args += 2;
sdr_config->channel = atoi(argv[argi]);
break;
case OPT_SDR_DEVICE_ARGS:
sdr_config->device_args = strdup(optarg);
*skip_args += 2;
sdr_config->device_args = strdup(argv[argi]);
break;
case OPT_SDR_STREAM_ARGS:
sdr_config->stream_args = strdup(optarg);
*skip_args += 2;
sdr_config->stream_args = strdup(argv[argi]);
break;
case OPT_SDR_TUNE_ARGS:
sdr_config->tune_args = strdup(optarg);
*skip_args += 2;
sdr_config->tune_args = strdup(argv[argi]);
break;
case OPT_SDR_SAMPLERATE:
sdr_config->samplerate = atoi(optarg);
*skip_args += 2;
sdr_config->samplerate = atoi(argv[argi]);
break;
case OPT_SDR_LO_OFFSET:
sdr_config->lo_offset = atof(optarg);
*skip_args += 2;
sdr_config->lo_offset = atof(argv[argi]);
break;
case OPT_SDR_BANDWIDTH:
sdr_config->bandwidth = atof(optarg);
*skip_args += 2;
sdr_config->bandwidth = atof(argv[argi]);
break;
case OPT_SDR_RX_ANTENNA:
sdr_config->rx_antenna = strdup(optarg);
*skip_args += 2;
sdr_config->rx_antenna = strdup(argv[argi]);
break;
case OPT_SDR_TX_ANTENNA:
sdr_config->tx_antenna = strdup(optarg);
*skip_args += 2;
sdr_config->tx_antenna = strdup(argv[argi]);
break;
case OPT_SDR_RX_GAIN:
sdr_config->rx_gain = atof(optarg);
*skip_args += 2;
sdr_config->rx_gain = atof(argv[argi]);
break;
case OPT_SDR_TX_GAIN:
sdr_config->tx_gain = atof(optarg);
*skip_args += 2;
sdr_config->tx_gain = atof(argv[argi]);
break;
case OPT_WRITE_IQ_RX_WAVE:
sdr_config->write_iq_rx_wave = strdup(optarg);
*skip_args += 2;
sdr_config->write_iq_rx_wave = strdup(argv[argi]);
break;
case OPT_WRITE_IQ_TX_WAVE:
sdr_config->write_iq_tx_wave = strdup(optarg);
*skip_args += 2;
sdr_config->write_iq_tx_wave = strdup(argv[argi]);
break;
case OPT_READ_IQ_RX_WAVE:
sdr_config->read_iq_rx_wave = strdup(optarg);
*skip_args += 2;
sdr_config->read_iq_rx_wave = strdup(argv[argi]);
break;
case OPT_READ_IQ_TX_WAVE:
sdr_config->read_iq_tx_wave = strdup(optarg);
*skip_args += 2;
sdr_config->read_iq_tx_wave = strdup(argv[argi]);
break;
case OPT_SDR_SWAP_LINKS:
sdr_config->swap_links = 1;
*skip_args += 1;
break;
case OPT_SDR_UHD_TX_TS:
sdr_config->uhd_tx_timestamps = 1;
*skip_args += 1;
break;
default:
return -1;
return -EINVAL;
}
return 0;
return 1;
}
int sdr_configure(int samplerate)

View File

@ -26,8 +26,7 @@ extern sdr_config_t *sdr_config;
void sdr_config_init(double lo_offset);
void sdr_config_print_help(void);
void sdr_config_print_hotkeys(void);
extern struct option sdr_config_long_options[];
extern const char *sdr_config_optstring;
int sdr_config_opt_switch(int c, int *skip_args);
void sdr_config_add_options(void);
int sdr_config_handle_options(int short_option, int argi, char **argv);
int sdr_configure(int samplerate);

View File

@ -22,6 +22,7 @@ nmt_SOURCES = \
nmt_LDADD = \
$(COMMON_LA) \
libdmssms.a \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libdebug/libdebug.a \
$(top_builddir)/src/libmobile/libmobile.a \
$(top_builddir)/src/libdisplay/libdisplay.a \

View File

@ -19,16 +19,17 @@
#include <stdio.h>
#include <stdint.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "../libsample/sample.h"
#include "../libmobile/main_mobile.h"
#include "../libdebug/debug.h"
#include "../liboptions/options.h"
#include "nmt.h"
#include "frame.h"
#include "dsp.h"
@ -97,141 +98,118 @@ void print_help(const char *arg0)
main_mobile_print_hotkeys();
}
static int handle_options(int argc, char **argv)
static void add_options(void)
{
main_mobile_add_options();
option_add('N', "nmt-system", 1);
option_add('T', "channel-type", 1);
option_add('P', "ms-power", 1);
option_add('Y', "traffic-area", 1);
option_add('A', "area-number", 1);
option_add('C', "compandor", 1);
option_add('0', "supervisory", 1);
option_add('S', "smsc-number", 1);
option_add('I', "caller-id", 1);
}
static int handle_options(int short_option, int argi, char **argv)
{
int rc;
char *p;
int super;
int skip_args = 0;
static struct option long_options_special[] = {
{"nmt-system", 1, 0, 'N'},
{"channel-type", 1, 0, 'T'},
{"ms-power", 1, 0, 'P'},
{"traffic-area", 1, 0, 'Y'},
{"area-number", 1, 0, 'A'},
{"compandor", 1, 0, 'C'},
{"supervisory", 1, 0, '0'},
{"smsc-number", 1, 0, 'S'},
{"caller-id", 1, 0, 'I'},
{0, 0, 0, 0}
};
main_mobile_set_options("N:T:P:Y:A:C:0:S:I:", long_options_special);
while (1) {
int option_index = 0, c, rc;
static int first_option = 1;
c = getopt_long(argc, argv, optstring, long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'N':
nmt_system = atoi(optarg);
if (nmt_system != 450 && nmt_system != 900) {
fprintf(stderr, "Error, NMT system type '%s' unknown. Please use '-N 450' for NMT-450 or '-N 900' for NMT-900.\n", optarg);
exit(0);
}
if (nmt_system == 900)
ms_power = 0;
if (!first_option) {
fprintf(stderr, "Please specify the NMT system (-N) as first command line option!\n");
exit(0);
}
skip_args += 2;
break;
case 'T':
if (!strcmp(optarg, "list")) {
nmt_channel_list(nmt_system);
exit(0);
}
rc = nmt_channel_by_short_name(nmt_system, optarg);
if (rc < 0) {
fprintf(stderr, "Error, channel type '%s' unknown. Please use '-t list' to get a list. I suggest to use the default.\n", optarg);
exit(0);
}
OPT_ARRAY(num_chan_type, chan_type, rc)
skip_args += 2;
break;
case 'P':
ms_power = atoi(optarg);
if (ms_power > 3)
ms_power = 3;
if (ms_power < 0)
ms_power = 0;
skip_args += 2;
break;
case 'Y':
if (!strcmp(optarg, "list")) {
nmt_country_list(nmt_system);
exit(0);
}
/* digits */
strncpy(country, optarg, sizeof(country) - 1);
country[sizeof(country) - 1] = '\0';
p = strchr(country, ',');
if (!p) {
fprintf(stderr, "Illegal traffic area '%s', see '-h' for help\n", optarg);
exit(0);
}
*p++ = '\0';
rc = nmt_country_by_short_name(nmt_system, country);
if (rc < 0) {
error_ta:
fprintf(stderr, "Invalid traffic area '%s', use '-Y list' for a list of valid areas\n", optarg);
exit(0);
}
traffic_area[0] = rc + '0';
if (p[strlen(p) - 1] != '!') {
rc = nmt_ta_by_short_name(nmt_system, country, atoi(p));
if (rc < 0)
goto error_ta;
}
nmt_value2digits(atoi(p), traffic_area + 1, 1);
traffic_area[2] = '\0';
skip_args += 2;
break;
case 'A':
area_no = optarg[0] - '0';
if (area_no > 4) {
fprintf(stderr, "Area number '%s' out of range, please use 1..4 or 0 for no area\n", optarg);
exit(0);
}
skip_args += 2;
break;
case 'C':
compandor = atoi(optarg);
skip_args += 2;
break;
case '0':
super = atoi(optarg);
if (super < 0 || super > 4) {
fprintf(stderr, "Given supervisory signal is wrong, use '-h' for help!\n");
exit(0);
}
OPT_ARRAY(num_supervisory, supervisory, super)
skip_args += 2;
break;
case 'S':
smsc_number = strdup(optarg);
skip_args += 2;
break;
case 'I':
send_callerid = atoi(optarg);
skip_args += 2;
break;
default:
main_mobile_opt_switch(c, argv[0], &skip_args);
switch (short_option) {
case 'N':
nmt_system = atoi(argv[argi]);
if (nmt_system != 450 && nmt_system != 900) {
fprintf(stderr, "Error, NMT system type '%s' unknown. Please use '-N 450' for NMT-450 or '-N 900' for NMT-900.\n", argv[argi]);
return -EINVAL;
}
first_option = 0;
if (nmt_system == 900)
ms_power = 0;
if (!option_is_first()) {
fprintf(stderr, "Please specify the NMT system (-N) as first command line option!\n");
return -EINVAL;
}
break;
case 'T':
if (!strcmp(argv[argi], "list")) {
nmt_channel_list(nmt_system);
return 0;
}
rc = nmt_channel_by_short_name(nmt_system, argv[argi]);
if (rc < 0) {
fprintf(stderr, "Error, channel type '%s' unknown. Please use '-t list' to get a list. I suggest to use the default.\n", argv[argi]);
return -EINVAL;
}
OPT_ARRAY(num_chan_type, chan_type, rc)
break;
case 'P':
ms_power = atoi(argv[argi]);
if (ms_power > 3)
ms_power = 3;
if (ms_power < 0)
ms_power = 0;
break;
case 'Y':
if (!strcmp(argv[argi], "list")) {
nmt_country_list(nmt_system);
return 0;
}
/* digits */
strncpy(country, argv[argi], sizeof(country) - 1);
country[sizeof(country) - 1] = '\0';
p = strchr(country, ',');
if (!p) {
fprintf(stderr, "Illegal traffic area '%s', see '-h' for help\n", argv[argi]);
return -EINVAL;
}
*p++ = '\0';
rc = nmt_country_by_short_name(nmt_system, country);
if (rc < 0) {
error_ta:
fprintf(stderr, "Invalid traffic area '%s', use '-Y list' for a list of valid areas\n", argv[argi]);
return -EINVAL;
}
traffic_area[0] = rc + '0';
if (p[strlen(p) - 1] != '!') {
rc = nmt_ta_by_short_name(nmt_system, country, atoi(p));
if (rc < 0)
goto error_ta;
}
nmt_value2digits(atoi(p), traffic_area + 1, 1);
traffic_area[2] = '\0';
break;
case 'A':
area_no = argv[argi][0] - '0';
if (area_no > 4) {
fprintf(stderr, "Area number '%s' out of range, please use 1..4 or 0 for no area\n", argv[argi]);
return -EINVAL;
}
break;
case 'C':
compandor = atoi(argv[argi]);
break;
case '0':
super = atoi(argv[argi]);
if (super < 0 || super > 4) {
fprintf(stderr, "Given supervisory signal is wrong, use '-h' for help!\n");
return -EINVAL;
}
OPT_ARRAY(num_supervisory, supervisory, super)
break;
case 'S':
smsc_number = strdup(argv[argi]);
break;
case 'I':
send_callerid = atoi(argv[argi]);
break;
default:
return main_mobile_handle_options(short_option, argi, argv);
}
free(long_options);
return skip_args;
return 1;
}
static void myhandler(void)
@ -280,8 +258,7 @@ int submit_sms(const char *sms)
int main(int argc, char *argv[])
{
int rc;
int skip_args;
int rc, argi;
const char *station_id = "";
int mandatory = 0;
int i;
@ -292,12 +269,17 @@ int main(int argc, char *argv[])
main_mobile_init();
skip_args = handle_options(argc, argv);
argc -= skip_args;
argv += skip_args;
/* handle options / config file */
add_options();
rc = options_config_file("~/.osmocom/analog/nmt.conf", handle_options);
if (rc < 0)
return 0;
argi = options_command_line(argc, argv, handle_options);
if (argi <= 0)
return argi;
if (argc > 1) {
station_id = argv[1];
if (argi < argc) {
station_id = argv[argi];
if (strlen(station_id) != 7) {
printf("Given station ID '%s' does not have 7 digits\n", station_id);
return 0;
@ -338,7 +320,7 @@ int main(int argc, char *argv[])
num_audiodev = 1; /* use default */
if (num_kanal != num_audiodev) {
fprintf(stderr, "You need to specify as many sound devices as you have channels.\n");
exit(0);
return -EINVAL;
}
if (num_kanal == 1 && num_chan_type == 0) {
num_chan_type = 1; /* use default */
@ -347,14 +329,14 @@ int main(int argc, char *argv[])
}
if (num_kanal != num_chan_type) {
fprintf(stderr, "You need to specify as many channel types as you have channels.\n");
exit(0);
return -EINVAL;
}
if (num_kanal == 1 && num_supervisory == 0)
num_supervisory = 1; /* use default */
if (num_kanal != num_supervisory) {
fprintf(stderr, "You need to specify as many supervisory signals as you have channels.\n");
fprintf(stderr, "They shall be different at channels that are close to each other.\n");
exit(0);
return -EINVAL;
}
if (num_kanal) {
uint8_t super[5] = { 0, 0, 0, 0, 0 };
@ -378,7 +360,7 @@ int main(int argc, char *argv[])
}
if (mandatory) {
print_help(argv[-skip_args]);
print_help(argv[0]);
return 0;
}

View File

@ -12,6 +12,7 @@ radiocom2000_SOURCES = \
main.c
radiocom2000_LDADD = \
$(COMMON_LA) \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libdebug/libdebug.a \
$(top_builddir)/src/libmobile/libmobile.a \
$(top_builddir)/src/libdisplay/libdisplay.a \

View File

@ -19,16 +19,17 @@
#include <stdio.h>
#include <stdint.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "../libsample/sample.h"
#include "../libmobile/main_mobile.h"
#include "../libdebug/debug.h"
#include "../liboptions/options.h"
#include "r2000.h"
#include "dsp.h"
#include "frame.h"
@ -102,179 +103,154 @@ void print_help(const char *arg0)
#define OPT_TAXE 258
#define OPT_DESTRUCTION 259
static int handle_options(int argc, char **argv)
static void add_options(void)
{
int skip_args = 0;
main_mobile_add_options();
option_add('B', "band", 1);
option_add(OPT_BANDE, "bande", 1);
option_add('T', "channel-type", 1);
option_add('R', "relais", 1);
option_add(OPT_DEPORT, "deport", 1);
option_add('I', "agi", 1);
option_add('P', "sm-power", 1);
option_add(OPT_TAXE, "taxe", 1);
option_add('C', "crins", 1);
option_add(OPT_DESTRUCTION, "destruction", 1);
option_add('N', "nconv", 1);
option_add('S', "recall", 1);
}
static struct option long_options_special[] = {
{"band", 1, 0, 'B'},
{"bande", 1, 0, OPT_BANDE},
{"channel-type", 1, 0, 'T'},
{"relais", 1, 0, 'R'},
{"deport", 1, 0, OPT_DEPORT},
{"agi", 1, 0, 'I'},
{"sm-power", 1, 0, 'P'},
{"taxe", 1, 0, OPT_TAXE},
{"crins", 1, 0, 'C'},
{"destruction", 1, 0, OPT_DESTRUCTION},
{"nconv", 1, 0, 'N'},
{"recall", 1, 0, 'S'},
{0, 0, 0, 0}
};
static int handle_options(int short_option, int argi, char **argv)
{
int rc;
main_mobile_set_options("B:T:R:I:P:C:N:S", long_options_special);
while (1) {
int option_index = 0, c, rc;
c = getopt_long(argc, argv, optstring, long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'B':
case OPT_BANDE:
if (!strcmp(optarg, "list")) {
r2000_band_list();
exit(0);
}
band = atoi(optarg);
skip_args += 2;
break;
case 'T':
if (!strcmp(optarg, "list")) {
r2000_channel_list();
exit(0);
}
rc = r2000_channel_by_short_name(optarg);
if (rc < 0) {
fprintf(stderr, "Error, channel type '%s' unknown. Please use '-t list' to get a list. I suggest to use the default.\n", optarg);
exit(0);
}
OPT_ARRAY(num_chan_type, chan_type, rc)
skip_args += 2;
break;
case 'R':
relais = atoi(optarg);
if (relais > 511)
relais = 511;
if (relais < 1)
relais = 1;
skip_args += 2;
break;
case OPT_DEPORT:
deport = atoi(optarg);
if (deport > 7)
deport = 7;
if (deport < 0)
deport = 0;
skip_args += 2;
break;
case 'I':
if (!strcmp(optarg, "list")) {
int i;
printf("\nList of possible AGI (inscription permission) codes:\n\n");
printf("Value\tDescription\n");
printf("------------------------------------------------------------------------\n");
for (i = 0; i < 8; i++)
printf("%d\t%s\n", i, param_agi(i));
exit(0);
}
agi = atoi(optarg);
if (agi < 0 || agi > 7) {
fprintf(stderr, "Error, given inscription permission (AGI) %d is invalid, use 'list' to get a list of values!\n", agi);
exit(0);
}
skip_args += 2;
break;
case 'P':
sm_power = atoi(optarg);
if (sm_power > 1)
sm_power = 1;
if (sm_power < 0)
sm_power = 0;
skip_args += 2;
break;
case OPT_TAXE:
taxe = atoi(optarg);
if (taxe > 1)
taxe = 1;
if (taxe < 0)
taxe = 0;
skip_args += 2;
break;
#if 0
case 'A':
if (!strcmp(optarg, "list")) {
int i;
printf("\nList of possible AGA (call permission) codes:\n\n");
printf("Value\tDescription\n");
printf("------------------------------------------------------------------------\n");
for (i = 0; i < 4; i++)
printf("%d\t%s\n", i, param_aga(i));
exit(0);
}
aga = atoi(optarg);
if (aga < 0 || aga > 3) {
fprintf(stderr, "Error, given call permission (AGA) %d is invalid, use 'list' to get a list of values!\n", aga);
exit(0);
}
skip_args += 2;
break;
#endif
case 'C':
if (!strcmp(optarg, "list")) {
int i;
printf("\nList of possible CRINS (inscription response) codes:\n\n");
printf("Value\tDescription\n");
printf("------------------------------------------------------------------------\n");
for (i = 0; i < 8; i++)
printf("%d\t%s\n", i, param_crins(i));
exit(0);
}
crins = atoi(optarg);
if (crins < 0 || crins > 7) {
fprintf(stderr, "Error, given inscription response (CRINS) %d is invalid, use 'list' to get a list of values!\n", crins);
exit(0);
}
skip_args += 2;
break;
case OPT_DESTRUCTION:
if (!strcmp(optarg, "YES")) {
destruction = 2342;
}
skip_args += 2;
break;
case 'N':
nconv = atoi(optarg);
if (nconv > 7)
nconv = 7;
if (nconv < 0)
nconv = 0;
skip_args += 2;
break;
case 'S':
recall = 1;
skip_args += 1;
break;
default:
main_mobile_opt_switch(c, argv[0], &skip_args);
switch (short_option) {
case 'B':
case OPT_BANDE:
if (!strcmp(argv[argi], "list")) {
r2000_band_list();
return 0;
}
band = atoi(argv[argi]);
break;
case 'T':
if (!strcmp(argv[argi], "list")) {
r2000_channel_list();
return 0;
}
rc = r2000_channel_by_short_name(argv[argi]);
if (rc < 0) {
fprintf(stderr, "Error, channel type '%s' unknown. Please use '-t list' to get a list. I suggest to use the default.\n", argv[argi]);
return -EINVAL;
}
OPT_ARRAY(num_chan_type, chan_type, rc)
break;
case 'R':
relais = atoi(argv[argi]);
if (relais > 511)
relais = 511;
if (relais < 1)
relais = 1;
break;
case OPT_DEPORT:
deport = atoi(argv[argi]);
if (deport > 7)
deport = 7;
if (deport < 0)
deport = 0;
break;
case 'I':
if (!strcmp(argv[argi], "list")) {
int i;
printf("\nList of possible AGI (inscription permission) codes:\n\n");
printf("Value\tDescription\n");
printf("------------------------------------------------------------------------\n");
for (i = 0; i < 8; i++)
printf("%d\t%s\n", i, param_agi(i));
return 0;
}
agi = atoi(argv[argi]);
if (agi < 0 || agi > 7) {
fprintf(stderr, "Error, given inscription permission (AGI) %d is invalid, use 'list' to get a list of values!\n", agi);
return -EINVAL;
}
break;
case 'P':
sm_power = atoi(argv[argi]);
if (sm_power > 1)
sm_power = 1;
if (sm_power < 0)
sm_power = 0;
break;
case OPT_TAXE:
taxe = atoi(argv[argi]);
if (taxe > 1)
taxe = 1;
if (taxe < 0)
taxe = 0;
break;
#if 0
case 'A':
if (!strcmp(argv[argi], "list")) {
int i;
printf("\nList of possible AGA (call permission) codes:\n\n");
printf("Value\tDescription\n");
printf("------------------------------------------------------------------------\n");
for (i = 0; i < 4; i++)
printf("%d\t%s\n", i, param_aga(i));
return 0;
}
aga = atoi(argv[argi]);
if (aga < 0 || aga > 3) {
fprintf(stderr, "Error, given call permission (AGA) %d is invalid, use 'list' to get a list of values!\n", aga);
return -EINVAL;
}
break;
#endif
case 'C':
if (!strcmp(argv[argi], "list")) {
int i;
printf("\nList of possible CRINS (inscription response) codes:\n\n");
printf("Value\tDescription\n");
printf("------------------------------------------------------------------------\n");
for (i = 0; i < 8; i++)
printf("%d\t%s\n", i, param_crins(i));
return 0;
}
crins = atoi(argv[argi]);
if (crins < 0 || crins > 7) {
fprintf(stderr, "Error, given inscription response (CRINS) %d is invalid, use 'list' to get a list of values!\n", crins);
return -EINVAL;
}
break;
case OPT_DESTRUCTION:
if (!strcmp(argv[argi], "YES")) {
destruction = 2342;
}
break;
case 'N':
nconv = atoi(argv[argi]);
if (nconv > 7)
nconv = 7;
if (nconv < 0)
nconv = 0;
break;
case 'S':
recall = 1;
break;
default:
return main_mobile_handle_options(short_option, argi, argv);
}
free(long_options);
return skip_args;
return 1;
}
int main(int argc, char *argv[])
{
int rc;
int skip_args;
int rc, argi;
const char *station_id = "";
int mandatory = 0;
int i;
@ -284,12 +260,17 @@ int main(int argc, char *argv[])
main_mobile_init();
skip_args = handle_options(argc, argv);
argc -= skip_args;
argv += skip_args;
/* handle options / config file */
add_options();
rc = options_config_file("~/.osmocom/analog/radiocom2000.conf", handle_options);
if (rc < 0)
return 0;
argi = options_command_line(argc, argv, handle_options);
if (argi <= 0)
return argi;
if (argc > 1) {
station_id = argv[1];
if (argi < argc) {
station_id = argv[argi];
if (strlen(station_id) != 9) {
printf("Given station ID '%s' does not have 9 digits\n", station_id);
return 0;
@ -328,7 +309,7 @@ int main(int argc, char *argv[])
}
if (mandatory) {
print_help(argv[-skip_args]);
print_help(argv[0]);
return 0;
}

View File

@ -10,6 +10,7 @@ osmoradio_SOURCES = \
main.c
osmoradio_LDADD = \
$(COMMON_LA) \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libdebug/libdebug.a \
$(top_builddir)/src/libwave/libwave.a \
$(top_builddir)/src/libsample/libsample.a \

View File

@ -1,4 +1,4 @@
/* main function
/* Radio main function
*
* (C) 2018 by Andreas Eversberg <jolly@eversberg.eu>
* All Rights Reserved
@ -24,8 +24,8 @@ enum paging_signal;
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <getopt.h>
#include <signal.h>
#include <errno.h>
#include <math.h>
#include <termios.h>
#include <unistd.h>
@ -34,6 +34,7 @@ enum paging_signal;
#include "../libsdr/sdr_config.h"
#include "../libsdr/sdr.h"
#include "../libdisplay/display.h"
#include "../liboptions/options.h"
#include "radio.h"
#define DEFAULT_LO_OFFSET -1000000.0
@ -137,170 +138,121 @@ void print_help(const char *arg0)
printf(" -S --stereo\n");
printf(" Enables stereo carrier for frequency modulated UHF broadcast.\n");
printf(" It uses the 'Pilot-tone' system.\n");
printf(" --limesdr\n");
printf(" Auto-select several required options for LimeSDR\n");
sdr_config_print_help();
}
static struct option long_options_common[] = {
{"help", 0, 0, 'h'},
{"frequency", 1, 0, 'f'},
{"samplerate", 1, 0, 's'},
{"tx-wave-file", 1, 0, 'r'},
{"rx-wave-file", 1, 0, 'w'},
{"audio-device", 1, 0, 'a'},
{"modulation", 1, 0, 'M'},
{"rx", 0, 0, 'R'},
{"tx", 0, 0, 'T'},
{"bandwidth", 1, 0, 'B'},
{"deviation", 1, 0, 'D'},
{"modulation-index", 1, 0, 'I'},
{"emphasis", 1, 0, 'E'},
{"stereo", 0, 0, 'S'},
{0, 0, 0, 0}
};
#define OPT_LIMESDR 1100
static const char *optstring_common = "hf:s:r:w:a:M:RTB:D:I:E:S";
struct option *long_options;
char *optstring;
static void check_duplicate_option(int num, struct option *option)
static void add_options(void)
{
int i;
for (i = 0; i < num; i++) {
if (long_options[i].val == option->val) {
fprintf(stderr, "Duplicate option %d. Please fix!\n", option->val);
abort();
}
}
option_add('h', "help", 0);
option_add('f', "frequency", 1);
option_add('s', "samplerate", 1);
option_add('r', "tx-wave-file", 1);
option_add('w', "rx-wave-file", 1);
option_add('a', "audio-device", 1);
option_add('M', "modulation", 1);
option_add('R', "rx", 0);
option_add('T', "tx", 0);
option_add('B', "bandwidth", 1);
option_add('D', "deviation", 1);
option_add('I', "modulation-index", 1);
option_add('E', "emphasis", 1);
option_add('S', "stereo", 0);
option_add(OPT_LIMESDR, "limesdr", 0);
sdr_config_add_options();
}
void set_options_common(void)
static int handle_options(int short_option, int argi, char **argv)
{
int i = 0, j;
long_options = calloc(sizeof(*long_options), 256);
for (j = 0; long_options_common[i].name; i++, j++) {
check_duplicate_option(i, &long_options_common[j]);
memcpy(&long_options[i], &long_options_common[j], sizeof(*long_options));
}
for (j = 0; sdr_config_long_options[j].name; i++, j++) {
check_duplicate_option(i, &sdr_config_long_options[j]);
memcpy(&long_options[i], &sdr_config_long_options[j], sizeof(*long_options));
}
optstring = calloc(256, 2);
strcpy(optstring, optstring_common);
strcat(optstring, sdr_config_optstring);
}
static int handle_options(int argc, char **argv)
{
int skip_args = 0;
int rc;
set_options_common();
while (1) {
int option_index = 0, c;
c = getopt_long(argc, argv, optstring, long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'h':
print_help(argv[0]);
exit(0);
case 'f':
frequency = atof(optarg);
skip_args += 2;
break;
case 's':
samplerate = atof(optarg);
skip_args += 2;
break;
case 'r':
tx_wave_file = strdup(optarg);
skip_args += 2;
break;
case 'w':
rx_wave_file = strdup(optarg);
skip_args += 2;
break;
case 'a':
tx_audiodev = strdup(optarg);
rx_audiodev = strdup(optarg);
skip_args += 2;
break;
case 'M':
if (!strcasecmp(optarg, "fm"))
modulation = MODULATION_FM;
else
if (!strcasecmp(optarg, "am"))
modulation = MODULATION_AM_DSB;
else
if (!strcasecmp(optarg, "usb"))
modulation = MODULATION_AM_USB;
else
if (!strcasecmp(optarg, "lsb"))
modulation = MODULATION_AM_LSB;
else
{
fprintf(stderr, "Invalid modulation option, see help!\n");
exit(0);
}
skip_args += 2;
break;
case 'R':
rx = 1;
skip_args += 1;
break;
case 'T':
tx = 1;
skip_args += 1;
break;
case 'B':
bandwidth = atof(optarg);
skip_args += 2;
break;
case 'D':
deviation = atof(optarg);
skip_args += 2;
break;
case 'I':
modulation_index = atof(optarg);
if (modulation_index < 0.0 || modulation_index > 1.0) {
fprintf(stderr, "Invalid modulation index, see help!\n");
exit(0);
}
skip_args += 2;
break;
case 'E':
time_constant_us = atof(optarg);
skip_args += 2;
break;
case 'S':
stereo = 1;
skip_args += 1;
break;
default:
rc = sdr_config_opt_switch(c, &skip_args);
if (rc < 0)
exit(0);
break;
switch (short_option) {
case 'h':
print_help(argv[0]);
return 0;
case 'f':
frequency = atof(argv[argi]);
break;
case 's':
samplerate = atof(argv[argi]);
break;
case 'r':
tx_wave_file = strdup(argv[argi]);
break;
case 'w':
rx_wave_file = strdup(argv[argi]);
break;
case 'a':
tx_audiodev = strdup(argv[argi]);
rx_audiodev = strdup(argv[argi]);
break;
case 'M':
if (!strcasecmp(argv[argi], "fm"))
modulation = MODULATION_FM;
else
if (!strcasecmp(argv[argi], "am"))
modulation = MODULATION_AM_DSB;
else
if (!strcasecmp(argv[argi], "usb"))
modulation = MODULATION_AM_USB;
else
if (!strcasecmp(argv[argi], "lsb"))
modulation = MODULATION_AM_LSB;
else
{
fprintf(stderr, "Invalid modulation option, use '-h' for help!\n");
return -EINVAL;
}
break;
case 'R':
rx = 1;
break;
case 'T':
tx = 1;
break;
case 'B':
bandwidth = atof(argv[argi]);
break;
case 'D':
deviation = atof(argv[argi]);
break;
case 'I':
modulation_index = atof(argv[argi]);
if (modulation_index < 0.0 || modulation_index > 1.0) {
fprintf(stderr, "Invalid modulation index, use '-h' for help!\n");
return -EINVAL;
}
break;
case 'E':
time_constant_us = atof(argv[argi]);
break;
case 'S':
stereo = 1;
break;
case OPT_LIMESDR:
{
char *argv_lime[] = { argv[0],
"--sdr-soapy",
"--sdr-rx-antenna", "LNAL",
"--sdr-rx-gain", "50",
"--sdr-tx-gain", "50",
"--sdr-samplerate", "5000000",
"--sdr-bandwidth", "15000000",
};
int argc_lime = sizeof(argv_lime) / sizeof (*argv_lime);
return options_command_line(argc_lime, argv_lime, handle_options);
}
default:
return sdr_config_handle_options(short_option, argi, argv);
}
return skip_args;
return 1;
}
int main(int argc, char *argv[])
{
int skip_args;
int rc;
const char *arg0 = argv[0];
int rc, argi;
radio_t radio;
struct termios term, term_orig;
int c;
@ -310,13 +262,18 @@ int main(int argc, char *argv[])
sdr_config_init(DEFAULT_LO_OFFSET);
skip_args = handle_options(argc, argv);
argc -= skip_args + 1;
argv += skip_args + 1;
/* handle options / config file */
add_options();
rc = options_config_file("~/.osmocom/analog/radio.conf", handle_options);
if (rc < 0)
return 0;
argi = options_command_line(argc, argv, handle_options);
if (argi <= 0)
return argi;
if (frequency == 0.0) {
printf("No frequency given, I suggest to use 100000000 (100 MHz) and FM\n\n");
print_help(arg0);
print_help(argv[0]);
exit(0);
}
@ -324,12 +281,12 @@ int main(int argc, char *argv[])
if (rc < 0)
return rc;
if (rc == 0) {
fprintf(stderr, "Please select SDR, see help!\n");
fprintf(stderr, "Please select SDR, use '-h' for help!\n");
exit(0);
}
if (modulation == MODULATION_NONE) {
fprintf(stderr, "Please select modulation, see help!\n");
fprintf(stderr, "Please select modulation, use '-h' for help!\n");
exit(0);
}
@ -341,18 +298,18 @@ int main(int argc, char *argv[])
}
if (stereo && modulation != MODULATION_FM) {
fprintf(stderr, "Stereo works with FM only, see help!\n");
fprintf(stderr, "Stereo works with FM only, use '-h' for help!\n");
exit(0);
}
if (!rx && !tx) {
fprintf(stderr, "You need to specify --rx (receiver) and/or --tx (transmitter), see help!\n");
fprintf(stderr, "You need to specify --rx (receiver) and/or --tx (transmitter), use '-h' for help!\n");
exit(0);
}
if (stereo && bandwidth != 15000.0) {
fprintf(stderr, "Warning: Stereo works with bandwidth of 15 KHz only, using this bandwidth!\n");
}
if (stereo && time_constant_us != 75.0 && time_constant_us != 50.0) {
fprintf(stderr, "Stereo works with time constant of 50 uS or 75 uS only, see help!\n");
fprintf(stderr, "Stereo works with time constant of 50 uS or 75 uS only, use '-h' for help!\n");
exit(0);
}

View File

@ -13,6 +13,7 @@ tacs_SOURCES = \
tacs_LDADD = \
$(COMMON_LA) \
../amps/libamps.a \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libdebug/libdebug.a \
$(top_builddir)/src/libmobile/libmobile.a \
$(top_builddir)/src/libdisplay/libdisplay.a \

View File

@ -57,6 +57,7 @@ test_dms_LDADD = \
$(COMMON_LA) \
$(top_builddir)/src/libdebug/libdebug.a \
$(top_builddir)/src/libmobile/libmobile.a \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libdisplay/libdisplay.a \
$(top_builddir)/src/nmt/libdmssms.a \
$(top_builddir)/src/libjitter/libjitter.a \
@ -90,6 +91,7 @@ test_sms_LDADD = \
$(COMMON_LA) \
$(top_builddir)/src/libdebug/libdebug.a \
$(top_builddir)/src/libmobile/libmobile.a \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libdisplay/libdisplay.a \
$(top_builddir)/src/nmt/libdmssms.a \
$(top_builddir)/src/libjitter/libjitter.a \

View File

@ -43,7 +43,7 @@ void dms_receive(nmt_t *nmt, const uint8_t *data, int length, int eight_bits)
{
printf("(getting %d digits from DMS layer)\n", length);
assert(!memcmp((const char *)data, check_sequence, length), "Expecting received data to macht");
assert(!memcmp((const char *)data, check_sequence, length), "Expecting received data to match");
check_sequence += length;
check_length = length;

View File

@ -14,6 +14,7 @@ osmotv_SOURCES = \
main.c
osmotv_LDADD = \
$(COMMON_LA) \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libdebug/libdebug.a \
$(top_builddir)/src/libimage/libimage.a \
$(top_builddir)/src/libfm/libfm.a \

View File

@ -1,4 +1,4 @@
/* main function
/* JollyTV main function
*
* (C) 2017 by Andreas Eversberg <jolly@eversberg.eu>
* All Rights Reserved
@ -24,8 +24,8 @@ enum paging_signal;
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <getopt.h>
#include <signal.h>
#include <errno.h>
#include <math.h>
#include "../libsample/sample.h"
#include "../libfilter/iir_filter.h"
@ -37,6 +37,7 @@ enum paging_signal;
#include "../libsdr/sdr_config.h"
#include "../libsdr/sdr.h"
#endif
#include "../liboptions/options.h"
#include "bas.h"
#include "tv_modulate.h"
#include "channels.h"
@ -114,149 +115,104 @@ void print_help(const char *arg0)
printf(" Give exactly 12 characters to display as Station ID.\n");
printf(" (default = \"%s\")\n", station_id);
#ifdef HAVE_SDR
printf(" --limesdr\n");
printf(" Auto-select several required options for LimeSDR\n");
sdr_config_print_help();
#endif
}
static struct option long_options_common[] = {
{"help", 0, 0, 'h'},
{"frequency", 1, 0, 'f'},
{"channel", 1, 0, 'c'},
{"samplerate", 1, 0, 'r'},
{"wave-file", 1, 0, 'w'},
{"fbas", 1, 0, 'F'},
{"tone", 1, 0, 'T'},
{"circle-radius", 1, 0, 'R'},
{"color-bar", 1, 0, 'C'},
{"grid-only", 1, 0, 'G'},
{"station-id", 1, 0, 'I'},
{0, 0, 0, 0}
};
#define OPT_LIMESDR 1100
static const char *optstring_common = "hf:c:r:w:F:T:R:C:G:I:";
struct option *long_options;
char *optstring;
static void check_duplicate_option(int num, struct option *option)
static void add_options(void)
{
int i;
for (i = 0; i < num; i++) {
if (long_options[i].val == option->val) {
fprintf(stderr, "Duplicate option %d. Please fix!\n", option->val);
abort();
}
}
}
void set_options_common(void)
{
int i = 0, j;
long_options = calloc(sizeof(*long_options), 256);
for (j = 0; long_options_common[i].name; i++, j++) {
check_duplicate_option(i, &long_options_common[j]);
memcpy(&long_options[i], &long_options_common[j], sizeof(*long_options));
}
option_add('h', "help", 0);
option_add('f', "frequency", 1);
option_add('c', "channel", 1);
option_add('r', "samplerate", 1);
option_add('w', "wave-file", 1);
option_add('F', "fbas", 1);
option_add('T', "tone", 1);
option_add('R', "circle-radius", 1);
option_add('C', "color-bar", 1);
option_add('G', "grid-only", 1);
option_add('I', "station-id", 1);
#ifdef HAVE_SDR
for (j = 0; sdr_config_long_options[j].name; i++, j++) {
check_duplicate_option(i, &sdr_config_long_options[j]);
memcpy(&long_options[i], &sdr_config_long_options[j], sizeof(*long_options));
}
#endif
optstring = calloc(256, 2);
strcpy(optstring, optstring_common);
#ifdef HAVE_SDR
strcat(optstring, sdr_config_optstring);
option_add(OPT_LIMESDR, "limesdr", 0);
sdr_config_add_options();
#endif
}
static int handle_options(int argc, char **argv)
static int handle_options(int short_option, int argi, char **argv)
{
int skip_args = 0;
#ifdef HAVE_SDR
int rc;
#endif
set_options_common();
while (1) {
int option_index = 0, c;
c = getopt_long(argc, argv, optstring, long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'h':
print_help(argv[0]);
exit(0);
case 'f':
frequency = atof(optarg);
skip_args += 2;
break;
case 'c':
if (!strcmp(optarg, "list")) {
list_tv_channels();
exit(0);
}
frequency = get_tv_video_frequency(atoi(optarg));
if (frequency == 0.0) {
fprintf(stderr, "Given channel number unknown, use \"-c list\" to get a list.\n");
exit(0);
}
skip_args += 2;
break;
case 'r':
samplerate = atof(optarg);
skip_args += 2;
break;
case 'w':
wave_file = strdup(optarg);
skip_args += 2;
break;
case 'F':
fbas = atoi(optarg);
skip_args += 2;
break;
case 'T':
tone = atoi(optarg);
skip_args += 2;
break;
case 'R':
circle_radius = atof(optarg);
skip_args += 2;
break;
case 'C':
color_bar = atoi(optarg);
skip_args += 2;
break;
case 'G':
grid_only = atoi(optarg);
skip_args += 2;
break;
case 'I':
station_id = strdup(optarg);
if (strlen(station_id) != 12) {
fprintf(stderr, "Given station ID must be exactly 12 charaters long. (Use spaces to fill it.)\n");
exit(0);
}
skip_args += 2;
break;
default:
#ifdef HAVE_SDR
rc = sdr_config_opt_switch(c, &skip_args);
if (rc < 0)
exit(0);
#endif
break;
switch (short_option) {
case 'h':
print_help(argv[0]);
return 0;
case 'f':
frequency = atof(argv[argi]);
break;
case 'c':
if (!strcmp(argv[argi], "list")) {
list_tv_channels();
return 0;
}
frequency = get_tv_video_frequency(atoi(argv[argi]));
if (frequency == 0.0) {
fprintf(stderr, "Given channel number unknown, use \"-c list\" to get a list.\n");
return -EINVAL;
}
break;
case 'r':
samplerate = atof(argv[argi]);
break;
case 'w':
wave_file = strdup(argv[argi]);
break;
case 'F':
fbas = atoi(argv[argi]);
break;
case 'T':
tone = atoi(argv[argi]);
break;
case 'R':
circle_radius = atof(argv[argi]);
break;
case 'C':
color_bar = atoi(argv[argi]);
break;
case 'G':
grid_only = atoi(argv[argi]);
break;
case 'I':
station_id = strdup(argv[argi]);
if (strlen(station_id) != 12) {
fprintf(stderr, "Given station ID must be exactly 12 charaters long. (Use spaces to fill it.)\n");
return -EINVAL;
}
break;
#ifdef HAVE_SDR
case OPT_LIMESDR:
{
char *argv_lime[] = { argv[0],
"--sdr-soapy",
"--sdr-tx-gain", "50",
"--sdr-lo-offset", "-3000000",
"--sdr-bandwidth", "60000000",
"-r", "13750000",
};
int argc_lime = sizeof(argv_lime) / sizeof (*argv_lime);
return options_command_line(argc_lime, argv_lime, handle_options);
}
#endif
default:
#ifdef HAVE_SDR
return sdr_config_handle_options(short_option, argi, argv);
#else
return -EINVAL;
#endif
}
return skip_args;
return 1;
}
static void tx_bas(sample_t *sample_bas, __attribute__((__unused__)) sample_t *sample_tone, __attribute__((__unused__)) uint8_t *power_tone, int samples)
@ -448,9 +404,7 @@ error:
int main(int argc, char *argv[])
{
int skip_args;
int __attribute__((__unused__)) rc;
const char *arg0 = argv[0];
int __attribute__((__unused__)) rc, argi;
debuglevel = 0;
@ -458,12 +412,17 @@ int main(int argc, char *argv[])
sdr_config_init(DEFAULT_LO_OFFSET);
#endif
skip_args = handle_options(argc, argv);
argc -= skip_args + 1;
argv += skip_args + 1;
/* handle options / config file */
add_options();
rc = options_config_file("~/.osmocom/analog/osmotv.conf", handle_options);
if (rc < 0)
return 0;
argi = options_command_line(argc, argv, handle_options);
if (argi <= 0)
return argi;
if (frequency == 0.0 && !wave_file) {
print_help(arg0);
print_help(argv[0]);
exit(0);
}
@ -475,22 +434,22 @@ int main(int argc, char *argv[])
#endif
}
if (argc < 1) {
fprintf(stderr, "Expecting command, see help!\n");
if (argi >= argc) {
fprintf(stderr, "Expecting command, use '-h' for help!\n");
exit(0);
} else if (!strcmp(argv[0], "tx-fubk")) {
} else if (!strcmp(argv[argi], "tx-fubk")) {
tx_test_picture(BAS_FUBK);
} else if (!strcmp(argv[0], "tx-vcr")) {
} else if (!strcmp(argv[argi], "tx-vcr")) {
tx_test_picture(BAS_VCR);
} else if (!strcmp(argv[0], "tx-img")) {
if (argc < 2) {
fprintf(stderr, "Expecting image file, see help!\n");
exit(0);
} else if (!strcmp(argv[argi], "tx-img")) {
if (argi + 1 >= argc) {
fprintf(stderr, "Expecting image file, use '-h' for help!\n");
return -EINVAL;
}
tx_img(argv[1]);
tx_img(argv[argi + 1]);
} else {
fprintf(stderr, "Unknown command '%s', see help!\n", argv[0]);
exit(0);
fprintf(stderr, "Unknown command '%s', use '-h' for help!\n", argv[argi]);
return -EINVAL;
}
return 0;