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

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;