diff --git a/macros/libxml.m4 b/macros/libxml.m4 new file mode 100644 index 000000000..4655dcab2 --- /dev/null +++ b/macros/libxml.m4 @@ -0,0 +1,381 @@ +# Configure paths for LIBXML2 +# Toshio Kuratomi 2001-04-21 +# Adapted from: +# Configure paths for GLIB +# Owen Taylor 97-11-3 + +dnl AM_PATH_XML([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for XML, and define XML_CFLAGS and XML_LIBS +dnl +AC_DEFUN([AM_PATH_XML],[ +AC_ARG_WITH(xml-prefix, + [ --with-xml-prefix=PFX Prefix where libxml is installed (optional)], + xml_config_prefix="$withval", xml_config_prefix="") +AC_ARG_WITH(xml-exec-prefix, + [ --with-xml-exec-prefix=PFX Exec prefix where libxml is installed (optional)], + xml_config_exec_prefix="$withval", xml_config_exec_prefix="") +AC_ARG_ENABLE(xmltest, + [ --disable-xmltest Do not try to compile and run a test LIBXML program],, + enable_xmltest=yes) + + if test x$xml_config_exec_prefix != x ; then + xml_config_args="$xml_config_args --exec-prefix=$xml_config_exec_prefix" + if test x${XML_CONFIG+set} != xset ; then + XML_CONFIG=$xml_config_exec_prefix/bin/xml-config + fi + fi + if test x$xml_config_prefix != x ; then + xml_config_args="$xml_config_args --prefix=$xml_config_prefix" + if test x${XML_CONFIG+set} != xset ; then + XML_CONFIG=$xml_config_prefix/bin/xml-config + fi + fi + + AC_PATH_PROG(XML_CONFIG, xml-config, no) + min_xml_version=ifelse([$1], ,1.0.0,[$1]) + AC_MSG_CHECKING(for libxml - version >= $min_xml_version) + no_xml="" + if test "$XML_CONFIG" = "no" ; then + no_xml=yes + else + XML_CFLAGS=`$XML_CONFIG $xml_config_args --cflags` + XML_LIBS=`$XML_CONFIG $xml_config_args --libs` + xml_config_major_version=`$XML_CONFIG $xml_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + xml_config_minor_version=`$XML_CONFIG $xml_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + xml_config_micro_version=`$XML_CONFIG $xml_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_xmltest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $XML_CFLAGS" + LIBS="$XML_LIBS $LIBS" +dnl +dnl Now check if the installed libxml is sufficiently new. +dnl (Also sanity checks the results of xml-config to some extent) +dnl + rm -f conf.xmltest + AC_TRY_RUN([ +#include +#include +#include +#include + +int +main() +{ + int xml_major_version, xml_minor_version, xml_micro_version; + int major, minor, micro; + char *tmp_version; + int tmp_int_version; + + system("touch conf.xmltest"); + + /* Capture xml-config output via autoconf/configure variables */ + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = (char *)strdup("$min_xml_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string from xml-config\n", "$min_xml_version"); + exit(1); + } + free(tmp_version); + + /* Capture the version information from the header files */ + tmp_int_version = LIBXML_VERSION; + xml_major_version=tmp_int_version / 10000; + xml_minor_version=(tmp_int_version - xml_major_version * 10000) / 100; + xml_micro_version=(tmp_int_version - xml_minor_version * 100 - xml_major_version * 10000); + + /* Compare xml-config output to the libxml headers */ + if ((xml_major_version != $xml_config_major_version) || + (xml_minor_version != $xml_config_minor_version) +#if 0 + || +/* The last released version of libxml-1.x has an incorrect micro version in + * the header file so neither the includes nor the library will match the + * micro_version to the output of xml-config + */ + (xml_micro_version != $xml_config_micro_version) +#endif + ) + + { + printf("*** libxml header files (version %d.%d.%d) do not match\n", + xml_major_version, xml_minor_version, xml_micro_version); + printf("*** xml-config (version %d.%d.%d)\n", + $xml_config_major_version, $xml_config_minor_version, $xml_config_micro_version); + return 1; + } +/* Compare the headers to the library to make sure we match */ + /* Less than ideal -- doesn't provide us with return value feedback, + * only exits if there's a serious mismatch between header and library. + */ + LIBXML_TEST_VERSION; + + /* Test that the library is greater than our minimum version */ + if (($xml_config_major_version > major) || + (($xml_config_major_version == major) && ($xml_config_minor_version > minor)) || + (($xml_config_major_version == major) && ($xml_config_minor_version == minor) && + ($xml_config_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of libxml (%d.%d.%d) was found.\n", + xml_major_version, xml_minor_version, xml_micro_version); + printf("*** You need a version of libxml newer than %d.%d.%d. The latest version of\n", + major, minor, micro); + printf("*** libxml is always available from ftp://ftp.xmlsoft.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the xml-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of LIBXML, but you can also set the XML_CONFIG environment to point to the\n"); + printf("*** correct copy of xml-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + return 1; +} +],, no_xml=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + + if test "x$no_xml" = x ; then + AC_MSG_RESULT(yes (version $xml_config_major_version.$xml_config_minor_version.$xml_config_micro_version)) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$XML_CONFIG" = "no" ; then + echo "*** The xml-config script installed by LIBXML could not be found" + echo "*** If libxml was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the XML_CONFIG environment variable to the" + echo "*** full path to xml-config." + else + if test -f conf.xmltest ; then + : + else + echo "*** Could not run libxml test program, checking why..." + CFLAGS="$CFLAGS $XML_CFLAGS" + LIBS="$LIBS $XML_LIBS" + AC_TRY_LINK([ +#include +#include +], [ LIBXML_TEST_VERSION; return 0;], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding LIBXML or finding the wrong" + echo "*** version of LIBXML. If it is not finding LIBXML, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means LIBXML was incorrectly installed" + echo "*** or that you have moved LIBXML since it was installed. In the latter case, you" + echo "*** may want to edit the xml-config script: $XML_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + + XML_CFLAGS="" + XML_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(XML_CFLAGS) + AC_SUBST(XML_LIBS) + rm -f conf.xmltest +]) + +# Configure paths for LIBXML2 +# Toshio Kuratomi 2001-04-21 +# Adapted from: +# Configure paths for GLIB +# Owen Taylor 97-11-3 + +dnl AM_PATH_XML2([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for XML, and define XML_CFLAGS and XML_LIBS +dnl +AC_DEFUN([AM_PATH_XML2],[ +AC_ARG_WITH(xml-prefix, + [ --with-xml-prefix=PFX Prefix where libxml is installed (optional)], + xml_config_prefix="$withval", xml_config_prefix="") +AC_ARG_WITH(xml-exec-prefix, + [ --with-xml-exec-prefix=PFX Exec prefix where libxml is installed (optional)], + xml_config_exec_prefix="$withval", xml_config_exec_prefix="") +AC_ARG_ENABLE(xmltest, + [ --disable-xmltest Do not try to compile and run a test LIBXML program],, + enable_xmltest=yes) + + if test x$xml_config_exec_prefix != x ; then + xml_config_args="$xml_config_args --exec-prefix=$xml_config_exec_prefix" + if test x${XML2_CONFIG+set} != xset ; then + XML2_CONFIG=$xml_config_exec_prefix/bin/xml2-config + fi + fi + if test x$xml_config_prefix != x ; then + xml_config_args="$xml_config_args --prefix=$xml_config_prefix" + if test x${XML2_CONFIG+set} != xset ; then + XML2_CONFIG=$xml_config_prefix/bin/xml2-config + fi + fi + + AC_PATH_PROG(XML2_CONFIG, xml2-config, no) + min_xml_version=ifelse([$1], ,2.0.0,[$1]) + AC_MSG_CHECKING(for libxml - version >= $min_xml_version) + no_xml="" + if test "$XML2_CONFIG" = "no" ; then + no_xml=yes + else + XML_CFLAGS=`$XML2_CONFIG $xml_config_args --cflags` + XML_LIBS=`$XML2_CONFIG $xml_config_args --libs` + xml_config_major_version=`$XML2_CONFIG $xml_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + xml_config_minor_version=`$XML2_CONFIG $xml_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + xml_config_micro_version=`$XML2_CONFIG $xml_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_xmltest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $XML_CFLAGS" + LIBS="$XML_LIBS $LIBS" +dnl +dnl Now check if the installed libxml is sufficiently new. +dnl (Also sanity checks the results of xml2-config to some extent) +dnl + rm -f conf.xmltest + AC_TRY_RUN([ +#include +#include +#include +#include + +int +main() +{ + int xml_major_version, xml_minor_version, xml_micro_version; + int major, minor, micro; + char *tmp_version; + + system("touch conf.xmltest"); + + /* Capture xml2-config output via autoconf/configure variables */ + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = (char *)strdup("$min_xml_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string from xml2-config\n", "$min_xml_version"); + exit(1); + } + free(tmp_version); + + /* Capture the version information from the header files */ + tmp_version = (char *)strdup(LIBXML_DOTTED_VERSION); + if (sscanf(tmp_version, "%d.%d.%d", &xml_major_version, &xml_minor_version, &xml_micro_version) != 3) { + printf("%s, bad version string from libxml includes\n", "LIBXML_DOTTED_VERSION"); + exit(1); + } + free(tmp_version); + + /* Compare xml2-config output to the libxml headers */ + if ((xml_major_version != $xml_config_major_version) || + (xml_minor_version != $xml_config_minor_version) || + (xml_micro_version != $xml_config_micro_version)) + { + printf("*** libxml header files (version %d.%d.%d) do not match\n", + xml_major_version, xml_minor_version, xml_micro_version); + printf("*** xml2-config (version %d.%d.%d)\n", + $xml_config_major_version, $xml_config_minor_version, $xml_config_micro_version); + return 1; + } +/* Compare the headers to the library to make sure we match */ + /* Less than ideal -- doesn't provide us with return value feedback, + * only exits if there's a serious mismatch between header and library. + */ + LIBXML_TEST_VERSION; + + /* Test that the library is greater than our minimum version */ + if ((xml_major_version > major) || + ((xml_major_version == major) && (xml_minor_version > minor)) || + ((xml_major_version == major) && (xml_minor_version == minor) && + (xml_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of libxml (%d.%d.%d) was found.\n", + xml_major_version, xml_minor_version, xml_micro_version); + printf("*** You need a version of libxml newer than %d.%d.%d. The latest version of\n", + major, minor, micro); + printf("*** libxml is always available from ftp://ftp.xmlsoft.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the xml2-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of LIBXML, but you can also set the XML2_CONFIG environment to point to the\n"); + printf("*** correct copy of xml2-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + return 1; +} +],, no_xml=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + + if test "x$no_xml" = x ; then + AC_MSG_RESULT(yes (version $xml_config_major_version.$xml_config_minor_version.$xml_config_micro_version)) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$XML2_CONFIG" = "no" ; then + echo "*** The xml2-config script installed by LIBXML could not be found" + echo "*** If libxml was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the XML2_CONFIG environment variable to the" + echo "*** full path to xml2-config." + else + if test -f conf.xmltest ; then + : + else + echo "*** Could not run libxml test program, checking why..." + CFLAGS="$CFLAGS $XML_CFLAGS" + LIBS="$LIBS $XML_LIBS" + AC_TRY_LINK([ +#include +#include +], [ LIBXML_TEST_VERSION; return 0;], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding LIBXML or finding the wrong" + echo "*** version of LIBXML. If it is not finding LIBXML, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means LIBXML was incorrectly installed" + echo "*** or that you have moved LIBXML since it was installed. In the latter case, you" + echo "*** may want to edit the xml2-config script: $XML2_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + + XML_CFLAGS="" + XML_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(XML_CFLAGS) + AC_SUBST(XML_LIBS) + rm -f conf.xmltest +]) diff --git a/tests/memcsv.c b/tests/memcsv.c new file mode 100644 index 000000000..54e39cbea --- /dev/null +++ b/tests/memcsv.c @@ -0,0 +1,348 @@ +/* + * memcsv.c - (C) Stephane Fillod 2003 + * + * This program exercises the backup and restore of a radio + * using Hamlib. CSV primitives + * + * $Id: memcsv.c,v 1.1 2003-12-04 23:15:02 fillods Exp $ + * + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include "misc.h" +#include "sprintflst.h" + + +/* + * external prototype + */ + +extern int all; + +/* + * Prototypes + */ +static void dump_csv_chan(const channel_cap_t *mem_caps, const channel_t *chan, FILE *f); +static void dump_csv_name(const channel_cap_t *mem_caps, FILE *f); + +int csv_save (RIG *rig, const char *outfilename); +int csv_load (RIG *rig, const char *infilename); +int csv_parm_save (RIG *rig, const char *outfilename); +int csv_parm_load (RIG *rig, const char *infilename); + + + +int csv_save (RIG *rig, const char *outfilename) +{ + int i,j,status; + FILE *f; + channel_t chan; + + f = fopen(outfilename, "w"); + if (!f) + return -1; + + + for (i=0; rig->state.chan_list[i].type && i < CHANLSTSIZ; i++) { + + dump_csv_name(&rig->state.chan_list[i].mem_caps, f); + + for (j = rig->state.chan_list[i].start; + j <= rig->state.chan_list[i].end; j++) { + chan.vfo = RIG_VFO_MEM; + chan.channel_num = j; + status=rig_get_channel(rig, &chan); + + if (status != RIG_OK ) { + printf("rig_get_channel: error = %s \n", rigerror(status)); + return status; + } + + dump_csv_chan(&rig->state.chan_list[i].mem_caps, &chan, f); + } + } + + + fclose(f); + return 0; +} + +int csv_load (RIG *rig, const char *infilename) +{ + return -RIG_ENIMPL; + /* for every channel, fscanf, parse, set_chan */ +} + +static int print_parm_name(RIG *rig, const struct confparams *cfp, rig_ptr_t ptr) +{ + fprintf((FILE*)ptr, "%s;", cfp->name); + + return 1; /* process them all */ +} + +static int print_parm_val(RIG *rig, const struct confparams *cfp, rig_ptr_t ptr) +{ + value_t val; + FILE *f=(FILE*)ptr; + rig_get_ext_parm(rig, cfp->token, &val); + + switch (cfp->type) { + case RIG_CONF_CHECKBUTTON: + case RIG_CONF_COMBO: + fprintf(f,"%d;", val.i); + break; + case RIG_CONF_NUMERIC: + fprintf(f,"%f;", val.f); + break; + case RIG_CONF_STRING: + fprintf(f,"%s;", val.s); + break; + default: + fprintf(f,"unknown;"); + } + + return 1; /* process them all */ +} + + +int csv_parm_save (RIG *rig, const char *outfilename) +{ + int i, ret; + FILE *f; + setting_t parm, get_parm = all ? 0x7fffffff : rig->state.has_get_parm; + + f = fopen(outfilename, "w"); + if (!f) + return -1; + + for (i = 0; i < RIG_SETTING_MAX; i++) { + const char *ms = strparm(get_parm & rig_idx2setting(i)); + if (!ms || !ms[0]) + continue; + fprintf(f, "%s;", ms); + } + + rig_ext_parm_foreach(rig, print_parm_name, f); + fprintf(f, "\n"); + + for (i = 0; i < RIG_SETTING_MAX; i++) { + parm = get_parm & rig_idx2setting(i); + const char *ms = strparm(parm); + value_t val; + + if (!ms || !ms[0]) + continue; + ret = rig_get_parm(rig, parm, &val); + if (RIG_PARM_IS_FLOAT(parm)) + fprintf(f, "%f;", val.f); + else + fprintf(f, "%d;", val.i); + } + + + rig_ext_parm_foreach(rig, print_parm_val, f); + fprintf(f, "\n"); + fclose(f); + + return 0; +} + +int csv_parm_load (RIG *rig, const char *infilename) +{ + return -RIG_ENIMPL; + /* for every parm/ext_parm, fscanf, parse, set_parm's */ +} + + +/* *********************** */ + + +void dump_csv_name(const channel_cap_t *mem_caps, FILE *f) +{ + fprintf(f, "num;"); + + if (mem_caps->bank_num) { + fprintf(f, "bank_num;"); + } + + if (mem_caps->channel_desc) { + fprintf(f, "channel_desc;"); + } + if (mem_caps->vfo) { + fprintf(f, "vfo;"); + } + if (mem_caps->ant) { + fprintf(f, "ant;"); + } + if (mem_caps->freq) { + fprintf(f, "freq;"); + } + if (mem_caps->mode) { + fprintf(f, "mode;"); + } + if (mem_caps->width) { + fprintf(f, "width;"); + } + if (mem_caps->tx_freq) { + fprintf(f, "tx_freq;"); + } + if (mem_caps->tx_mode) { + fprintf(f, "tx_mode;"); + } + if (mem_caps->tx_width) { + fprintf(f, "tx_width;"); + } + if (mem_caps->split) { + fprintf(f, "split;"); + } + if (mem_caps->tx_vfo) { + fprintf(f, "tx_vfo;"); + } + if (mem_caps->rptr_shift) { + fprintf(f, "rptr_shift;"); + } + if (mem_caps->rptr_offs) { + fprintf(f, "rptr_offs;"); + } + if (mem_caps->tuning_step) { + fprintf(f, "tuning_step;"); + } + if (mem_caps->rit) { + fprintf(f, "rit;"); + } + if (mem_caps->xit) { + fprintf(f, "xit;"); + } + if (mem_caps->funcs) { + fprintf(f, "funcs;"); + } + if (mem_caps->ctcss_tone) { + fprintf(f, "ctcss_tone;"); + } + if (mem_caps->ctcss_sql) { + fprintf(f, "ctcss_sql;"); + } + if (mem_caps->dcs_code) { + fprintf(f, "dcs_code;"); + } + if (mem_caps->dcs_sql) { + fprintf(f, "dcs_sql;"); + } + if (mem_caps->scan_group) { + fprintf(f, "scan_group;"); + } + if (mem_caps->flags) { + fprintf(f, "flags;"); + } + fprintf(f, "\n"); +} + + +void dump_csv_chan(const channel_cap_t *mem_caps, const channel_t *chan, FILE *f) +{ + fprintf(f,"%d;",chan->channel_num); + + if (mem_caps->bank_num) { + fprintf(f,"%d;",chan->bank_num); + } + + if (mem_caps->channel_desc) { + fprintf(f, "%s;", chan->channel_desc); + } + if (mem_caps->vfo) { + fprintf(f,"%s;",strvfo(chan->vfo)); + } + if (mem_caps->ant) { + fprintf(f,"%d;",chan->ant); + } + if (mem_caps->freq) { + fprintf(f,"%"FREQFMT";",chan->freq); + } + if (mem_caps->mode) { + fprintf(f, "%s;", strrmode(chan->mode)); + } + if (mem_caps->width) { + fprintf(f,"%d;",(int)chan->width); + } + if (mem_caps->tx_freq) { + fprintf(f,"%"FREQFMT";",chan->tx_freq); + } + if (mem_caps->tx_mode) { + fprintf(f, "%s;", strrmode(chan->tx_mode)); + } + if (mem_caps->tx_width) { + fprintf(f,"%d;",(int)chan->tx_width); + } + if (mem_caps->split) { + fprintf(f, "%s;", chan->split==RIG_SPLIT_ON?"on":"off"); + } + if (mem_caps->tx_vfo) { + fprintf(f,"%s;",strvfo(chan->tx_vfo)); + } + if (mem_caps->rptr_shift) { + fprintf(f, "%s;", strptrshift(chan->rptr_shift)); + } + if (mem_caps->rptr_offs) { + fprintf(f,"%d",(int)chan->rptr_offs); + } + if (mem_caps->tuning_step) { + fprintf(f,"%d;",(int)chan->tuning_step); + } + if (mem_caps->rit) { + fprintf(f,"%d;",(int)chan->rit); + } + if (mem_caps->xit) { + fprintf(f,"%d;",(int)chan->xit); + } + if (mem_caps->funcs) { + fprintf(f,"%llx;",chan->funcs); + } + if (mem_caps->ctcss_tone) { + fprintf(f,"%d;",chan->ctcss_tone); + } + if (mem_caps->ctcss_sql) { + fprintf(f,"%d;",chan->ctcss_sql); + } + if (mem_caps->dcs_code) { + fprintf(f,"%d;",chan->dcs_code); + } + if (mem_caps->dcs_sql) { + fprintf(f,"%d;",chan->dcs_sql); + } + if (mem_caps->scan_group) { + fprintf(f,"%d;",chan->scan_group); + } + if (mem_caps->flags) { + fprintf(f,"%x;",chan->flags); + } + fprintf(f,"\n"); +} + diff --git a/tests/memload.c b/tests/memload.c new file mode 100644 index 000000000..adce866d0 --- /dev/null +++ b/tests/memload.c @@ -0,0 +1,262 @@ +/* + * memload.c - Copyright (C) 2003 Thierry Leconte + * + * + * $Id: memload.c,v 1.1 2003-12-04 23:15:02 fillods Exp $ + * + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include "misc.h" + +#ifdef HAVE_XML2 +#include +#include + +static int set_chan(RIG *rig, channel_t *chan ,xmlNodePtr node); +#endif + + +int xml_load (RIG *my_rig, const char *infilename) +{ +#ifdef HAVE_XML2 + int c,m=0; + xmlDocPtr Doc; + xmlNodePtr node; + + /* load xlm Doc */ + Doc=xmlParseFile(infilename); + if(Doc==NULL) { + fprintf(stderr,"xmlParse failed\n"); + exit(2); + } + + node=xmlDocGetRootElement(Doc); + if (node == NULL) { + fprintf(stderr,"get root failed\n"); + exit(2); + } + if(strcmp(node->name, (const xmlChar *) "hamlib")) { + fprintf(stderr,"no hamlib tag found\n"); + exit(2); + } + for(node=node->xmlChildrenNode;node!=NULL;node=node->next) { + if(xmlNodeIsText(node)) continue; + if(strcmp(node->name, (const xmlChar *) "channels")==0) + break; + } + if(node==NULL) { + fprintf(stderr,"no channels\n"); + exit(2); + } + for(node=node->xmlChildrenNode;node!=NULL;node=node->next) { + channel_t chan; + int status; + + if(xmlNodeIsText(node)) continue; + + set_chan(my_rig,&chan,node); + + status=rig_set_channel(my_rig, &chan); + + if (status != RIG_OK ) { + printf("rig_get_channel: error = %s \n", rigerror(status)); + return status; + } + } + + xmlFreeDoc(Doc); + xmlCleanupParser(); + + return 0; +#else + return -RIG_ENAVAIL; +#endif +} + +int xml_parm_load (RIG *my_rig, const char *infilename) +{ + return -RIG_ENIMPL; +} + +#ifdef HAVE_XML2 +int set_chan(RIG *rig, channel_t *chan, xmlNodePtr node) +{ + xmlChar *prop; + int i,n; + + memset(chan,0,sizeof(channel_t)); + chan->vfo = RIG_VFO_MEM; + + + prop=xmlGetProp(node,"num"); + if(prop==NULL) { + fprintf(stderr,"no num\n"); + return -1; + } + n=chan->channel_num = atoi(prop); + + /* find chanel caps */ + for(i=0;istate.chan_list[i].start<=n && rig->state.chan_list[i].end>=n) + break; + + fprintf(stderr,"node %d %d\n",n,i); + + if (rig->state.chan_list[i].mem_caps.bank_num) { + prop=xmlGetProp(node, "bank_num"); + if(prop!=NULL) + chan->bank_num = atoi(prop); + } + + if (rig->state.chan_list[i].mem_caps.channel_desc) { + prop=xmlGetProp(node, "channel_desc"); + if(prop!=NULL) + strncpy(chan->channel_desc,prop,7); + } + + if (rig->state.chan_list[i].mem_caps.ant) { + prop=xmlGetProp(node, "ant"); + if(prop!=NULL) + chan->ant = atoi(prop); + } + if (rig->state.chan_list[i].mem_caps.freq) { + prop=xmlGetProp(node, "freq"); + if(prop!=NULL) + sscanf(prop,"%"FREQFMT,&chan->freq); + } + if (rig->state.chan_list[i].mem_caps.mode) { + prop=xmlGetProp(node, "mode"); + if(prop!=NULL) + chan->mode = parse_mode(prop); + } + if (rig->state.chan_list[i].mem_caps.width) { + prop=xmlGetProp(node, "width"); + if(prop!=NULL) + chan->width = atoi(prop); + } + if (rig->state.chan_list[i].mem_caps.tx_freq) { + prop=xmlGetProp(node, "tx_freq"); + if(prop!=NULL) + sscanf(prop,"%"FREQFMT,&chan->tx_freq); + } + if (rig->state.chan_list[i].mem_caps.tx_mode) { + prop=xmlGetProp(node, "tx_mode"); + if(prop!=NULL) + chan->tx_mode = parse_mode(prop); + } + if (rig->state.chan_list[i].mem_caps.tx_width) { + prop=xmlGetProp(node, "tx_width"); + if(prop!=NULL) + chan->tx_width = atoi(prop); + } + if (rig->state.chan_list[i].mem_caps.split) { + prop=xmlGetProp(node, "split"); + if(strcmp(prop,"off")==0) chan->split=RIG_SPLIT_OFF; + if(strcmp(prop,"on")==0) { + chan->split=RIG_SPLIT_ON; + if (rig->state.chan_list[i].mem_caps.tx_vfo) { + prop=xmlGetProp(node, "tx_vfo"); + if(prop!=NULL) + sscanf(prop,"%x",&chan->tx_vfo); + } + } + } + if (rig->state.chan_list[i].mem_caps.rptr_shift) { + prop=xmlGetProp(node, "rptr_shift"); + if(prop) + switch(prop[0]) { + case '=': chan->rptr_shift=RIG_RPT_SHIFT_NONE; + break; + case '+': chan->rptr_shift=RIG_RPT_SHIFT_PLUS; + break; + case '-': chan->rptr_shift=RIG_RPT_SHIFT_MINUS; + break; + } + if (rig->state.chan_list[i].mem_caps.rptr_offs && chan->rptr_shift!=RIG_RPT_SHIFT_NONE) { + prop=xmlGetProp(node, "rptr_offs"); + if(prop!=NULL) + chan->rptr_offs = atoi(prop); + } + } + if (rig->state.chan_list[i].mem_caps.tuning_step) { + prop=xmlGetProp(node, "tuning_step"); + if(prop!=NULL) + chan->tuning_step = atoi(prop); + } + if (rig->state.chan_list[i].mem_caps.rit) { + prop=xmlGetProp(node, "rit"); + if(prop!=NULL) + chan->rit = atoi(prop); + } + if (rig->state.chan_list[i].mem_caps.xit) { + prop=xmlGetProp(node, "xit"); + if(prop!=NULL) + chan->xit = atoi(prop); + } + if (rig->state.chan_list[i].mem_caps.funcs) { + prop=xmlGetProp(node, "funcs"); + if(prop!=NULL) + sscanf(prop,"%llx",&chan->funcs); + } + if (rig->state.chan_list[i].mem_caps.ctcss_tone) { + prop=xmlGetProp(node, "ctcss_tone"); + if(prop!=NULL) + chan->ctcss_tone = atoi(prop); + } + if (rig->state.chan_list[i].mem_caps.ctcss_sql) { + prop=xmlGetProp(node, "ctcss_sql"); + if(prop!=NULL) + chan->ctcss_sql = atoi(prop); + } + if (rig->state.chan_list[i].mem_caps.dcs_code) { + prop=xmlGetProp(node, "dcs_code"); + if(prop!=NULL) + chan->dcs_code = atoi(prop); + } + if (rig->state.chan_list[i].mem_caps.dcs_sql) { + prop=xmlGetProp(node, "dcs_sql"); + if(prop!=NULL) + chan->dcs_sql = atoi(prop); + } + if (rig->state.chan_list[i].mem_caps.scan_group) { + prop=xmlGetProp(node, "scan_group"); + if(prop!=NULL) + chan->scan_group = atoi(prop); + } + if (rig->state.chan_list[i].mem_caps.flags) { + prop=xmlGetProp(node, "flags"); + if(prop!=NULL) + sscanf(prop,"%x",&chan->flags); + } + + + return 0; +} +#endif + diff --git a/tests/memsave.c b/tests/memsave.c new file mode 100644 index 000000000..67acbd47f --- /dev/null +++ b/tests/memsave.c @@ -0,0 +1,239 @@ +/* + * memsave.c - Copyright (C) 2003 Thierry Leconte + * + * + * $Id: memsave.c,v 1.1 2003-12-04 23:15:02 fillods Exp $ + * + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include "misc.h" + +#ifdef HAVE_XML2 +#include +#include + +static int dump_xml_chan(RIG *rig, xmlNodePtr root ,int chn, int chan_num); +#endif + +int xml_save (RIG *my_rig, const char *outfilename) +{ +#ifdef HAVE_XML2 + int status,i,j; + int c,m=0; + xmlDocPtr Doc; + xmlNodePtr root; + + /* create xlm Doc */ + Doc=xmlNewDoc("1.0"); + root=xmlNewNode(NULL,"hamlib"); + xmlDocSetRootElement(Doc, root); + root=xmlNewChild(root,NULL,"channels",NULL); + + + for (i=0; my_rig->state.chan_list[i].type && i < CHANLSTSIZ; i++) { + for (j = my_rig->state.chan_list[i].start; + j <= my_rig->state.chan_list[i].end; j++) { + dump_xml_chan(my_rig, root, i,j); + } + } + + /* write xml File */ + + xmlSaveFormatFileEnc(outfilename, Doc, "UTF-8", 1); + + xmlFreeDoc(Doc); + xmlCleanupParser(); + + return 0; +#else + return -RIG_ENAVAIL; +#endif +} + +int xml_parm_save (RIG *my_rig, const char *outfilename) +{ + return -RIG_ENIMPL; +} + + + +#ifdef HAVE_XML2 +int dump_xml_chan(RIG *rig, xmlNodePtr root, int i, int chan_num) +{ + channel_t chan; + int status; + char attrbuf[20]; + xmlNodePtr node; + + chan.vfo = RIG_VFO_MEM; + chan.channel_num = chan_num; + status=rig_get_channel(rig, &chan); + + if (status != RIG_OK ) { + printf("rig_get_channel: error = %s \n", rigerror(status)); + return status; + } + + switch (rig->state.chan_list[i].type) { + case RIG_MTYPE_NONE : + return RIG_OK; + case RIG_MTYPE_MEM: + node=xmlNewChild(root,NULL,"mem",NULL); + break; + case RIG_MTYPE_EDGE: + node=xmlNewChild(root,NULL,"edge",NULL); + break; + case RIG_MTYPE_CALL: + node=xmlNewChild(root,NULL,"call",NULL); + break; + case RIG_MTYPE_MEMOPAD: + node=xmlNewChild(root,NULL,"memopad",NULL); + break; + case RIG_MTYPE_SAT: + node=xmlNewChild(root,NULL,"sat",NULL); + break; + } + + if (rig->state.chan_list[i].mem_caps.bank_num) { + sprintf(attrbuf,"%d",chan.bank_num); + xmlNewProp(node, "bank_num", attrbuf); + } + + sprintf(attrbuf,"%d",chan.channel_num); + xmlNewProp(node, "num", attrbuf); + + if (rig->state.chan_list[i].mem_caps.channel_desc && chan.channel_desc[0]!='\0') { + xmlNewProp(node, "channel_desc", chan.channel_desc); + } + if (rig->state.chan_list[i].mem_caps.vfo) { + sprintf(attrbuf,"%d",chan.vfo); + xmlNewProp(node, "vfo", attrbuf); + } + if (rig->state.chan_list[i].mem_caps.ant) { + sprintf(attrbuf,"%d",chan.ant); + xmlNewProp(node, "ant", attrbuf); + } + if (rig->state.chan_list[i].mem_caps.freq) { + sprintf(attrbuf,"%lld",chan.freq); + xmlNewProp(node, "freq", attrbuf); + } + if (rig->state.chan_list[i].mem_caps.mode) { + xmlNewProp(node, "mode", strrmode(chan.mode)); + } + if (rig->state.chan_list[i].mem_caps.width) { + sprintf(attrbuf,"%d",(int)chan.width); + xmlNewProp(node, "width", attrbuf); + } + if (rig->state.chan_list[i].mem_caps.tx_freq) { + sprintf(attrbuf,"%lld",chan.tx_freq); + xmlNewProp(node, "tx_freq", attrbuf); + } + if (rig->state.chan_list[i].mem_caps.tx_mode) { + xmlNewProp(node, "tx_mode", strrmode(chan.tx_mode)); + } + if (rig->state.chan_list[i].mem_caps.tx_width) { + sprintf(attrbuf,"%d",(int)chan.tx_width); + xmlNewProp(node, "tx_width", attrbuf); + } + if (rig->state.chan_list[i].mem_caps.split) { + switch(chan.split) { + case RIG_SPLIT_OFF: + xmlNewProp(node, "split", "off"); + break; + case RIG_SPLIT_ON: + xmlNewProp(node, "split", "on"); + if (rig->state.chan_list[i].mem_caps.tx_vfo) { + sprintf(attrbuf,"%x",chan.tx_vfo); + xmlNewProp(node, "tx_vfo", attrbuf); + } + break; + } + } + if (rig->state.chan_list[i].mem_caps.rptr_shift) { + switch(chan.rptr_shift) { + case RIG_RPT_SHIFT_NONE: + xmlNewProp(node, "rptr_shift", "="); + break; + case RIG_RPT_SHIFT_PLUS: + xmlNewProp(node, "rptr_shift", "+"); + break; + case RIG_RPT_SHIFT_MINUS: + xmlNewProp(node, "rptr_shift", "-"); + break; + } + if (rig->state.chan_list[i].mem_caps.rptr_offs && chan.rptr_shift!=RIG_RPT_SHIFT_NONE) { + sprintf(attrbuf,"%d",(int)chan.rptr_offs); + xmlNewProp(node, "rptr_offs", attrbuf); + } + } + if (rig->state.chan_list[i].mem_caps.tuning_step) { + sprintf(attrbuf,"%d",(int)chan.tuning_step); + xmlNewProp(node, "tuning_step", attrbuf); + } + if (rig->state.chan_list[i].mem_caps.rit) { + sprintf(attrbuf,"%d",(int)chan.rit); + xmlNewProp(node, "rit", attrbuf); + } + if (rig->state.chan_list[i].mem_caps.xit) { + sprintf(attrbuf,"%d",(int)chan.xit); + xmlNewProp(node, "xit", attrbuf); + } + if (rig->state.chan_list[i].mem_caps.funcs) { + sprintf(attrbuf,"%llx",chan.funcs); + xmlNewProp(node, "funcs", attrbuf); + } + if (rig->state.chan_list[i].mem_caps.ctcss_tone) { + sprintf(attrbuf,"%d",chan.ctcss_tone); + xmlNewProp(node, "ctcss_tone", attrbuf); + } + if (rig->state.chan_list[i].mem_caps.ctcss_sql) { + sprintf(attrbuf,"%d",chan.ctcss_sql); + xmlNewProp(node, "ctcss_sql", attrbuf); + } + if (rig->state.chan_list[i].mem_caps.dcs_code) { + sprintf(attrbuf,"%d",chan.dcs_code); + xmlNewProp(node, "dcs_code", attrbuf); + } + if (rig->state.chan_list[i].mem_caps.dcs_sql) { + sprintf(attrbuf,"%d",chan.dcs_sql); + xmlNewProp(node, "dcs_sql", attrbuf); + } + if (rig->state.chan_list[i].mem_caps.scan_group) { + sprintf(attrbuf,"%d",chan.scan_group); + xmlNewProp(node, "scan_group", attrbuf); + } + if (rig->state.chan_list[i].mem_caps.flags) { + sprintf(attrbuf,"%x",chan.flags); + xmlNewProp(node, "flags", attrbuf); + } + + + return 0; +} +#endif + diff --git a/tests/rigmem.1 b/tests/rigmem.1 new file mode 100644 index 000000000..adfd30c4b --- /dev/null +++ b/tests/rigmem.1 @@ -0,0 +1,116 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" First parameter, NAME, should be all caps +.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection +.\" other parameters are allowed: see man(7), man(1) +.TH RIGCTL "1" "December 03, 2003" "Hamlib" +.\" Please adjust this date whenever revising the manpage. +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +rigmem \- backup and restore memory of radio transcievers and receivers +.SH SYNOPSIS +.B rigmem +[\fIOPTION\fR]... [\fICOMMAND\fR]... +.SH DESCRIPTION +Backup and restore memory of radio transcievers and receivers. +\fBrigmem\fP accepts \fBcommands\fP from command line only. +.PP +.\" TeX users may be more comfortable with the \fB\fP and +.\" \fI\fP escape sequences to invode bold face and italics, +.\" respectively. +Keep in mind that \fBHamlib\fP is still BETA level software. +A lof of stuff hasn't been tested thoroughly, and the API may change +without publicised notice. Please report bugs and feedback at +the e-mail address given in the REPORTING BUGS section. +.SH OPTIONS +This program follow the usual GNU command line syntax, with long +options starting with two dashes (`-'). +A summary of options is included below. +.TP +.B \-m, \-\-model=id +Select radio model number. See model list. +.TP +.B \-r, --rig-file=device +Use \fBdevice\fP as the file name of the radio to operate on. +.TP +.B \-s, --serial-speed=baud +Set serial speed to \fBbaud\fP rate. Uses maximal rig speed as default. +.TP +.B \-c, --civaddr=id +Use \fBid\fP as the CI-V address to communicate with the rig. +Only for Icom rigs. NB: the id is in decimal, unless prefixed by \fB0x\fP, +in which case it is hexadecimal. +.TP +.B \-C, \-\-set\-conf=parm=val[,parm=val]* +Set config parameter. +.TP +.B \-x, \-\-xml +Use XML format instead of CSV, if libxml2 is available. +.TP +.B \-v, \-\-verbose +Set verbose mode, cumulative (BUG, ERR, WARN, VERBOSE, TRACE). +.TP +.B \-h, \-\-help +Show summary of options and exit. +.TP +.B \-V, \-\-version +Show version of program and exit. + +.SH COMMANDS +Backup and restore are supported for basic CSV file and XML format where available. +.PP +Please note that the backend for the radio to be controlled, +or the radio itself may not support some commands. In that case, +the operation will fail with a standard error message. +.PP +A summary of commands is included below. +.TP +.B save +Save all the content of memory in a CSV (or XML) file given as argument to the command. +.TP +.B load +Load the content into all the memory from a CSV (or XML) file given as argument to the command. + +.TP +.B save_parm +Save all the parameters of the radio in a CSV (or XML) file given as argument to the command. +.TP +.B load_parm +Load the parameters of the radio from a CSV (or XML) file given as argument to the command. + +.TP +.B clear +Very DANGEROUS command, as it will completly clear out everything you have programmed +in the memory of you radio. ALL DATA WILL BE LOST. Use at your own risks! + +.SH RETURN VALUE +rigmem exits with: +0 if all operations went fine; 1 if there was an invalid command line +option or arg; or 2 if an error was returned by Hamlib. + +.SH AUTHOR +Man page written by Stephane Fillod. +.SH BUGS +This almost empty section... +.SH REPORTING BUGS +Report bugs to . +.br +I'm already aware of the bug in the previous section :-) +.SH COPYRIGHT +Copyright \(co 2000-2003 Stephane Fillod. +.br +This is free software; see the source for copying conditions. +There is NO warranty; not even for MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. +.SH SEE ALSO +.BR hamlib (3), rigctl(1) + diff --git a/tests/rigmem.c b/tests/rigmem.c new file mode 100644 index 000000000..417019334 --- /dev/null +++ b/tests/rigmem.c @@ -0,0 +1,364 @@ +/* + * rigmem.c - (C) Stephane Fillod and Thierry Leconte 2003 + * + * This program exercises the backup and restore of a radio + * using Hamlib. + * + * $Id: rigmem.c,v 1.1 2003-12-04 23:15:02 fillods Exp $ + * + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include "misc.h" +#include "sprintflst.h" + +#ifdef _WIN32 +#define LLFMT "L" +#else +#define LLFMT "ll" +#endif + +#define MAXNAMSIZ 32 +#define MAXNBOPT 100 /* max number of different options */ + + +/* + * external prototype + */ + +extern int xml_save (RIG *rig, const char *outfilename); +extern int xml_load (RIG *rig, const char *infilename); +extern int xml_parm_save (RIG *rig, const char *outfilename); +extern int xml_parm_load (RIG *rig, const char *infilename); + +extern int csv_save (RIG *rig, const char *outfilename); +extern int csv_load (RIG *rig, const char *infilename); +extern int csv_parm_save (RIG *rig, const char *outfilename); +extern int csv_parm_load (RIG *rig, const char *infilename); + +/* + * Prototypes + */ +void usage(); +void version(); +int set_conf(RIG *rig, char *conf_parms); + +int clear_chans (RIG *rig, const char *infilename); + +/* + * Reminder: when adding long options, + * keep up to date SHORT_OPTIONS, usage()'s output and man page. thanks. + * NB: do NOT use -W since it's reserved by POSIX. + */ +#define SHORT_OPTIONS "m:r:s:c:C:axvhV" +static struct option long_options[] = +{ + {"model", 1, 0, 'm'}, + {"rig-file", 1, 0, 'r'}, + {"serial-speed", 1, 0, 's'}, + {"civaddr", 1, 0, 'c'}, + {"set-conf", 1, 0, 'C'}, + {"all", 0, 0, 'a'}, + {"xml", 0, 0, 'x'}, + {"verbose", 0, 0, 'v'}, + {"help", 0, 0, 'h'}, + {"version", 0, 0, 'V'}, + {0, 0, 0, 0} +}; + +#define MAXCONFLEN 128 + +int all; + +int main (int argc, char *argv[]) +{ + RIG *rig; /* handle to rig (nstance) */ + rig_model_t my_model = RIG_MODEL_DUMMY; + + int retcode; /* generic return code from functions */ + + int verbose = 0, xml = 0; + const char *rig_file=NULL; + int serial_rate = 0; + char *civaddr = NULL; /* NULL means no need to set conf */ + char conf_parms[MAXCONFLEN] = ""; + + while(1) { + int c; + int option_index = 0; + + c = getopt_long (argc, argv, SHORT_OPTIONS, + long_options, &option_index); + if (c == -1) + break; + + switch(c) { + case 'h': + usage(); + exit(0); + case 'V': + version(); + exit(0); + case 'm': + if (!optarg) { + usage(); /* wrong arg count */ + exit(1); + } + my_model = atoi(optarg); + break; + case 'r': + if (!optarg) { + usage(); /* wrong arg count */ + exit(1); + } + rig_file = optarg; + break; + case 'c': + if (!optarg) { + usage(); /* wrong arg count */ + exit(1); + } + civaddr = optarg; + break; + case 's': + if (!optarg) { + usage(); /* wrong arg count */ + exit(1); + } + serial_rate = atoi(optarg); + break; + case 'C': + if (!optarg) { + usage(); /* wrong arg count */ + exit(1); + } + if (*conf_parms != '\0') + strcat(conf_parms, ","); + strncat(conf_parms, optarg, MAXCONFLEN-strlen(conf_parms)); + break; + case 'a': + all++; + break; + case 'x': + xml++; + break; + case 'v': + verbose++; + break; + default: + usage(); /* unknown option? */ + exit(1); + } + } + + rig_set_debug(verbose<2 ? RIG_DEBUG_WARN: verbose); + + rig_debug(RIG_DEBUG_VERBOSE, "rigmem, %s\n", hamlib_version); + rig_debug(RIG_DEBUG_VERBOSE, "Report bugs to " + "\n\n"); + + if (optind+1 >= argc) { + usage(); + exit(1); + } + + rig = rig_init(my_model); + + if (!rig) { + fprintf(stderr, "Unknown rig num %d, or initialization error.\n", + my_model); + fprintf(stderr, "Please check with --list option.\n"); + exit(2); + } + + retcode = set_conf(rig, conf_parms); + if (retcode != RIG_OK) { + fprintf(stderr, "Config parameter error: %s\n", rigerror(retcode)); + exit(2); + } + + if (rig_file) + strncpy(rig->state.rigport.pathname, rig_file, FILPATHLEN); + + /* FIXME: bound checking and port type == serial */ + if (serial_rate != 0) + rig->state.rigport.parm.serial.rate = serial_rate; + if (civaddr) + rig_set_conf(rig, rig_token_lookup(rig, "civaddr"), civaddr); + + retcode = rig_open(rig); + if (retcode != RIG_OK) { + fprintf(stderr,"rig_open: error = %s \n", rigerror(retcode)); + exit(2); + } + + if (verbose > 0) + printf("Opened rig model %d, '%s'\n", rig->caps->rig_model, + rig->caps->model_name); + rig_debug(RIG_DEBUG_VERBOSE, "Backend version: %s, Status: %s\n", + rig->caps->version, strstatus(rig->caps->status)); + + /* on some rigs, this accelerates the backup/restore */ + rig_set_vfo(rig, RIG_VFO_MEM); + + if (!strcmp(argv[optind], "save")) { + if (xml) + retcode = xml_save(rig, argv[optind+1]); + else + retcode = csv_save(rig, argv[optind+1]); + } else + if (!strcmp(argv[optind], "load")) { + if (xml) + retcode = xml_load(rig, argv[optind+1]); + else + retcode = csv_load(rig, argv[optind+1]); + } else + if (!strcmp(argv[optind], "save_parm")) { + if (xml) + retcode = xml_parm_save(rig, argv[optind+1]); + else + retcode = csv_parm_save(rig, argv[optind+1]); + } else + if (!strcmp(argv[optind], "load_parm")) { + if (xml) + retcode = xml_parm_load(rig, argv[optind+1]); + else + retcode = csv_parm_load(rig, argv[optind+1]); + } else + if (!strcmp(argv[optind], "clear")) { + retcode = clear_chans(rig, argv[optind+1]); + } else { + usage(); + exit(1); + } + + rig_close(rig); /* close port */ + rig_cleanup(rig); /* if you care about memory */ + + if (retcode != 0) { + fprintf(stderr, "Hamlib error: %s\n", rigerror(retcode)); + exit(2); + } + + return 0; +} + + + +void version() +{ + printf("rigmem, %s\n\n", hamlib_version); + printf("%s\n", hamlib_copyright); +} + +void usage() +{ + printf("Usage: rigmem [OPTION]... COMMAND...FILE\n" + "Backup/restore COMMANDs to a connected radio transceiver or receiver.\n\n"); + + + printf( + " -m, --model=ID select radio model number. See model list\n" + " -r, --rig-file=DEVICE set device of the radio to operate on\n" + " -s, --serial-speed=BAUD set serial speed of the serial port\n" + " -c, --civaddr=ID set CI-V address, decimal (for Icom rigs only)\n" + " -C, --set-conf=PARM=VAL set config parameters\n" + " -a, --all bypass mem_caps, apply to all fields of channel_t\n" + " -x, --xml use XML format instead of CSV\n" + " -v, --verbose set verbose mode, cumulative\n" + " -h, --help display this help and exit\n" + " -V, --version output version information and exit\n\n" + ); + + printf( + "COMMANDs:\n" + " load\n" + " save\n" + " load_parm\n" + " save_parm\n" + " clear\n\n" + ); + + printf("\nReport bugs to .\n"); + +} + +int set_conf(RIG *rig, char *conf_parms) +{ + char *p, *q, *n; + int ret; + + p = conf_parms; + while (p && *p != '\0') { + /* FIXME: left hand value of = cannot be null */ + q = strchr(p, '='); + if (q) *q++ = '\0'; + n = strchr(q, ','); + if (n) *n++ = '\0'; + + ret = rig_set_conf(rig, rig_token_lookup(rig, p), q); + if (ret != RIG_OK) + return ret; + p = n; + } + return RIG_OK; +} + + +/* + * Pretty nasty, clears everything you have in rig memory + */ +int clear_chans (RIG *rig, const char *infilename) +{ + int i,j,ret; + channel_t chan; + + memset(&chan, 0, sizeof(chan)); + chan.freq = RIG_FREQ_NONE; + chan.tx_freq = RIG_FREQ_NONE; + chan.mode = RIG_MODE_NONE; + chan.tx_mode = RIG_MODE_NONE; + chan.vfo = RIG_VFO_MEM; + + for (i=0; rig->state.chan_list[i].type && i < CHANLSTSIZ; i++) { + for (j = rig->state.chan_list[i].start; + j <= rig->state.chan_list[i].end; j++) { + chan.channel_num = j; + ret = rig_set_channel(rig, &chan); + if (ret != RIG_OK) { + return ret; + } + } + } + + return 0; +} +