Add first cut at amplifier control

pull/115/head
Michael Black 2019-06-12 15:52:35 -05:00
rodzic c61a62bec5
commit 7e9c566944
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6599353EC683404D
37 zmienionych plików z 8159 dodań i 23 usunięć

Wyświetl plik

@ -15,6 +15,7 @@ doc_DATA = ChangeLog COPYING COPYING.LIB LICENSE \
SUBDIRS = macros include lib \
$(BACKEND_LIST) \
$(ROT_BACKEND_LIST) \
$(AMP_BACKEND_LIST) \
src \
$(BINDINGS) \
tests doc
@ -25,7 +26,8 @@ DIST_SUBDIRS = macros include lib src c++ bindings tests doc android scripts\
adat alinco aor barrett drake dorji dummy elad flexradio icom icmarine jrc\
kachina kenwood kit lowe pcr prm80 racal rft rs skanti tapr tentec\
tuner uniden wj yaesu winradio\
$(ROT_BACKEND_LIST)
amplifiers/elecraft
$(ROT_BACKEND_LIST) $(AMP_BACKEND_LIST)
# Install any third party macros into our tree for distribution
ACLOCAL_AMFLAGS = -I macros --install

Wyświetl plik

@ -9,14 +9,14 @@ See README for frontend/backend outline.
See README.betatester for background on testing Hamlib.
The library provides functions for both radio and rotator control,
and data retrieval from the radio or rotator. A number of functions useful
The library provides functions for both radio, rotator, and amplifier control,
and data retrieval from the radio, rotator, or amplifier. A number of functions useful
for calculating distance and bearing and grid square conversion are included.
libhamlib.so - library that provides generic API for all RIG types.
This is what Application programmers will "see". Will have different
names on other platforms, e.g. libhamlib-2.dll on MS windows. Also
contains all radio and rotator "backends" (formerly in their own
contains all radio, rotator, and amplifier "backends" (formerly in their own
dlopen'ed libraries) provided by Hamlib.
Backend Examples are:
@ -401,7 +401,8 @@ So far, Hamlib has been tested successfully under the following systems:
Makefile.am (not needed for rotators)
2.3. Add the backend name to the BACKEND_LIST variable (add to
ROT_BACKEND_LIST for a new rotor backend) in configure.ac.
ROT_BACKEND_LIST for a new rotor backend or to AMP_BACKEND_LIST for
a new amplifier) in configure.ac.
2.4. Add "mybackend/Makefile" in the AC_CONFIG_FILES macro at the bottom
of configure.ac.
@ -414,8 +415,10 @@ So far, Hamlib has been tested successfully under the following systems:
the rig_backend_list structure in src/register.c or, add
{ ROT_MYROTBACKEND, ROT_BACKEND_MYROTBACKEND, ROT_FUNCNAMA(myrotbackend) },
to the rot_backend_list structure in src/rot_reg.c.
{ AMP_MYAMPBACKEND, AMP_BACKEND_MYAMPBACKEND, AMP_FUNCNAMA(myaotbackend) },
to the aot_backend_list structure in src/amp_reg.c.
2.7. Add the new backend to include/hamlib/riglist.h or include/hamlib/rotlist.h
2.7. Add the new backend to include/hamlib/riglist.h or include/hamlib/rotlist.h or include/hamlib/amplist.h
by selecting the next higher backend ID number.
2.8. Create mybackend/Makefile.am, mybackend.c mybackend.h
@ -465,7 +468,7 @@ So far, Hamlib has been tested successfully under the following systems:
3. How to add a new model to an existing backend
3.1. make sure there's already a (unique) ID for the model to be added
in include/hamlib/riglist.h or include/hamlib/rotlist.h
in include/hamlib/riglist.h or include/hamlib/rotlist.h or include/hamlib/amplist.h
3.2. locate the existing backend
3.3. Clone the most similar model in the backend
@ -539,7 +542,7 @@ Contributed code to the Hamlib frontend must be released under the LGPL.
Contributed code to Hamlib backends must follow backend current license.
Needless to say, the LGPL is the license of choice.
End user applications like rigctl, rotctl and networked daemons should be
End user applications like rigctl, rotctl, ampctl and networked daemons should be
released under the GPL, so any contributed code must follow the license.
@ -577,7 +580,7 @@ Hamlib should also compile with the following common compilers:
* gcc-3.0 and gcc-3.2+ (nearly deprecated?)
* gcc-4.x and newer
* in shared and static
* C++ compiler against rig.h, riglist.h, rotator.h
* C++ compiler against rig.h, riglist.h, rotator.h, amplifier.h
* clang compiler
Portability issues to watch:

Wyświetl plik

@ -0,0 +1,12 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := elecraft.c kpa.c kpa1500.c
LOCAL_MODULE := elecraft
LOCAL_CFLAGS := -DHAVE_CONFIG_H
LOCAL_C_INCLUDES := android include src
LOCAL_LDLIBS := -lhamlib
include $(BUILD_STATIC_LIBRARY)

Wyświetl plik

@ -0,0 +1,8 @@
SRC = kpa1500.c
ELECRAFTSRC = kpa.c kpa.h
noinst_LTLIBRARIES = libhamlib-elecraft.la
libhamlib_elecraft_la_SOURCES = $(SRC) $(ELECRAFTSRC)
EXTRA_DIST = README.elecraft Android.mk

Wyświetl plik

@ -0,0 +1,593 @@
/*
* Hamlib Elecraft amplifier backend - low level communication routines
* Copyright (c) 2019 by Michael Black W9MDB
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdlib.h>
#include <string.h>
#include "kpa.h"
struct fault_list
{
int code;
char *errmsg;
};
const struct fault_list kpa_fault_list [] =
{
{0, "No fault condition"},
{0x10, "Watchdog Timer was reset"},
{0x20, "PA Current is too high"},
{0x40, "Temperature is too high"},
{0x60, "Input power is too high"},
{0x61, "Gain is too low"},
{0x70, "Invalid frequency"},
{0x80, "50V supply voltage too low or too high"},
{0x81, "5V supply voltage too low or too high"},
{0x82, "10V supply voltage too low or too high"},
{0x83, "12V supply voltage too low or too high"},
{0x84, "-12V supply voltage too low or too high"},
{0x85, "5V or 400V LPF board supply voltages not detected"},
{0x90, "Reflected power is too high"},
{0x91, "SWR very high"},
{0x92, "ATU no match"},
{0xB0, "Dissipated power too high"},
{0xC0, "Forward power too high"},
{0xE0, "Forward power too high for current setting"},
{0xF0, "Gain is too high"},
{0, NULL}
};
/*
* Initialize data structures
*/
int kpa_init(AMP *amp)
{
struct kpa_priv_data *priv;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp)
{
return -RIG_EINVAL;
}
priv = (struct kpa_priv_data *)
malloc(sizeof(struct kpa_priv_data));
if (!priv)
{
return -RIG_ENOMEM;
}
amp->state.priv = (void *)priv;
amp->state.ampport.type.rig = RIG_PORT_SERIAL;
return RIG_OK;
}
int kpa_flushbuffer(AMP *amp)
{
struct amp_state *rs;
rig_debug(RIG_DEBUG_VERBOSE, "%s called, cmd=%s\n", __func__);
rs = &amp->state;
return serial_flush(&rs->ampport);
}
int kpa_transaction(AMP *amp, const char *cmd, char *response, int response_len)
{
struct amp_state *rs;
int err;
int len = 0;
char responsebuf[KPABUFSZ];
rig_debug(RIG_DEBUG_VERBOSE, "%s called, cmd=%s\n", __func__, cmd);
if (!amp) { return -RIG_EINVAL; }
kpa_flushbuffer(amp);
rs = &amp->state;
int loop = 3;
do // wake up the amp by sending ; until we receive ;
{
rig_debug(RIG_DEBUG_VERBOSE, "%s waiting for ;\n", __func__);
char c = ';';
err = write_block(&rs->ampport, &c, 1);
if (err != RIG_OK) { return err; }
int len = read_string(&rs->ampport, responsebuf, KPABUFSZ, ";", 1);
if (len < 0) { return len; }
}
while (--loop > 0 && (len != 1 || responsebuf[0] != ';'));
// Now send our command
err = write_block(&rs->ampport, cmd, strlen(cmd));
if (err != RIG_OK) { return err; }
if (response) // if response expected get it
{
responsebuf[0] = 0;
int len = read_string(&rs->ampport, responsebuf, KPABUFSZ, ";", 1);
if (len < 0)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called, error=%s\n", __func__,
rigerror(len));
return len;
}
rig_debug(RIG_DEBUG_VERBOSE, "%s called, response='%s'\n", __func__,
responsebuf);
}
else // if no response expected try to get one
{
loop = 3;
do
{
rig_debug(RIG_DEBUG_VERBOSE, "%s waiting for ;\n", __func__);
char c = ';';
err = write_block(&rs->ampport, &c, 1);
if (err != RIG_OK) { return err; }
int len = read_string(&rs->ampport, responsebuf, KPABUFSZ, ";", 1);
if (len < 0) { return len; }
}
while (--loop > 0 && (len != 1 || responsebuf[0] != ';'));
}
return RIG_OK;
}
/*
* Get Info
* returns the model name string
*/
const char *kpa_get_info(AMP *amp)
{
const struct amp_caps *rc;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp) { return (const char *) - RIG_EINVAL; }
rc = amp->caps;
return rc->model_name;
}
int kpa_get_freq(AMP *amp, freq_t *freq)
{
char responsebuf[KPABUFSZ];
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp) { return -RIG_EINVAL; }
int retval = kpa_transaction(amp, "^FR;", responsebuf, sizeof(responsebuf));
if (retval != RIG_OK) { return retval; }
unsigned long tfreq;
int nargs = sscanf(responsebuf, "^FR%ld", &tfreq);
if (nargs != 1)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s Error: ^FR response='%s'\n", __func__,
responsebuf);
return -RIG_EPROTO;
}
*freq = tfreq * 1000;
return RIG_OK;
}
int kpa_set_freq(AMP *amp, freq_t freq)
{
char responsebuf[KPABUFSZ];
rig_debug(RIG_DEBUG_VERBOSE, "%s called, freq=%ld\n", __func__, freq);
if (!amp) { return -RIG_EINVAL; }
char cmd[KPABUFSZ];
sprintf(cmd, "^FR%05ld;", (long)freq / 1000);
int retval = kpa_transaction(amp, cmd, NULL, 0);
if (retval != RIG_OK) { return retval; }
unsigned long tfreq;
int nargs = sscanf(responsebuf, "^FR%ld", &tfreq);
if (nargs != 1)
{
rig_debug(RIG_DEBUG_ERR, "%s Error: ^FR response='%s'\n", __func__,
responsebuf);
return -RIG_EPROTO;
}
if (tfreq * 1000 != freq)
{
rig_debug(RIG_DEBUG_ERR,
"%s Error setting freq: ^FR freq!=freq2, %ld!=%ld '%s'\n", __func__,
freq, tfreq * 1000);
return -RIG_EPROTO;
}
return RIG_OK;
}
int kpa_get_level(AMP *amp, setting_t level, value_t *val)
{
char responsebuf[KPABUFSZ];
char *cmd;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp) { return -RIG_EINVAL; }
// get the current antenna selected
cmd = "^AE;";
int retval = kpa_transaction(amp, cmd, responsebuf, sizeof(responsebuf));
if (retval != RIG_OK) { return retval; }
int antenna = 0;
int nargs = sscanf(responsebuf, "^AE%d", &antenna);
if (nargs != 1)
{
rig_debug(RIG_DEBUG_ERR, "%s invalid value %s='%s'\n", __func__, cmd,
responsebuf);
return -RIG_EPROTO;
}
rig_debug(RIG_DEBUG_VERBOSE, "%s antenna=%d\n", __func__, cmd, antenna);
switch (level)
{
case AMP_LEVEL_SWR:
cmd = "^SW;";
break;
case AMP_LEVEL_NH:
cmd = "^DF;";
break;
case AMP_LEVEL_PF:
cmd = "^DF;";
break;
case AMP_LEVEL_PWR_INPUT:
cmd = "^PWI;";
break;
case AMP_LEVEL_PWR_FWD:
cmd = "^PWF;";
break;
case AMP_LEVEL_PWR_REFLECTED:
cmd = "^PWR;";
break;
case AMP_LEVEL_PWR_PEAK:
cmd = "^PWK;";
break;
case AMP_LEVEL_FAULT:
cmd = "^SF;";
break;
}
retval = kpa_transaction(amp, cmd, responsebuf, sizeof(responsebuf));
if (retval != RIG_OK) { return retval; }
float float_value = 0;
int int_value = 0, int_value2 = 0;
struct amp_state *rs = &amp->state;
switch (level)
{
case AMP_LEVEL_SWR:
nargs = sscanf(responsebuf, "^SW%f", &float_value);
if (nargs != 1)
{
rig_debug(RIG_DEBUG_ERR, "%s invalid value %s='%s'\n", __func__, cmd,
responsebuf);
return -RIG_EPROTO;
}
val->f = float_value / 10.0f;
return RIG_OK;
case AMP_LEVEL_NH:
case AMP_LEVEL_PF:
nargs = sscanf(responsebuf, "^DF%d,%d", &int_value, &int_value2);
if (nargs != 2)
{
rig_debug(RIG_DEBUG_ERR, "%s invalid value %s='%s'\n", __func__, cmd,
responsebuf);
return -RIG_EPROTO;
}
rig_debug(RIG_DEBUG_VERBOSE, "%s freq range=%dKHz,%dKHz\n", __func__, cmd,
int_value, int_value2);
//
do
{
retval = read_string(&rs->ampport, responsebuf, sizeof(responsebuf), ";", 1);
if (retval != RIG_OK) { return retval; }
if (strstr(responsebuf, "BYPASS") != 0)
{
int antenna2 = 0;
nargs = sscanf(responsebuf, "AN%d Side TX %d %*s %*s %d", &antenna2, &int_value,
&int_value2);
rig_debug(RIG_DEBUG_VERBOSE, "%s response='%s'\n", __func__, responsebuf);
if (nargs != 3)
{
rig_debug(RIG_DEBUG_ERR, "%s invalid value %s='%s'\n", __func__, cmd,
responsebuf);
return -RIG_EPROTO;
}
rig_debug(RIG_DEBUG_VERBOSE, "%s antenna=%d,nH=%d\n", __func__, antenna2,
int_value);
val->i = level == AMP_LEVEL_NH ? int_value : int_value2;
return RIG_OK;
}
}
while (strstr(responsebuf, "BYPASS"));
break;
case AMP_LEVEL_PWR_INPUT:
cmd = "^PWI;";
int pwrinput;
nargs = sscanf(responsebuf, "^SW%d", &pwrinput);
if (nargs != 1)
{
rig_debug(RIG_DEBUG_ERR, "%s invalid value %s='%s'\n", __func__, cmd,
responsebuf);
return -RIG_EPROTO;
}
val->i = pwrinput;
return RIG_OK;
break;
case AMP_LEVEL_PWR_FWD:
cmd = "^PWF;";
int pwrfwd;
nargs = sscanf(responsebuf, "^SW%d", &pwrfwd);
if (nargs != 1)
{
rig_debug(RIG_DEBUG_ERR, "%s invalid value %s='%s'\n", __func__, cmd,
responsebuf);
return -RIG_EPROTO;
}
val->i = pwrfwd;
return RIG_OK;
break;
case AMP_LEVEL_PWR_REFLECTED:
cmd = "^PWR;";
int pwrref;
nargs = sscanf(responsebuf, "^SW%d", &pwrref);
if (nargs != 1)
{
rig_debug(RIG_DEBUG_ERR, "%s invalid value %s='%s'\n", __func__, cmd,
responsebuf);
return -RIG_EPROTO;
}
val->i = pwrref;
return RIG_OK;
break;
case AMP_LEVEL_PWR_PEAK:
cmd = "^PWK;";
int pwrpeak;
nargs = sscanf(responsebuf, "^SW%d", &pwrpeak);
if (nargs != 1)
{
rig_debug(RIG_DEBUG_ERR, "%s invalid value %s='%s'\n", __func__, cmd,
responsebuf);
return -RIG_EPROTO;
}
val->i = pwrpeak;
return RIG_OK;
break;
case AMP_LEVEL_FAULT:
cmd = "^SF;";
int fault;
nargs = sscanf(responsebuf, "^SW%d", &fault);
if (nargs != 1)
{
rig_debug(RIG_DEBUG_ERR, "%s invalid value %s='%s'\n", __func__, cmd,
responsebuf);
return -RIG_EPROTO;
}
int i;
for (i = 0; kpa_fault_list[i].errmsg != NULL; ++i)
{
if (kpa_fault_list[i].code == fault)
{
val->s = kpa_fault_list[i].errmsg;
return RIG_OK;
}
}
rig_debug(RIG_DEBUG_ERR, "%s unknown fault=%s\n", __func__, cmd, responsebuf);
struct kpa_priv_data *priv = amp->state.priv;
sprintf(priv->tmpbuf, "Unknown fault code=0x%02x", fault);
val->s = priv->tmpbuf;
return RIG_OK;
break;
default:
rig_debug(RIG_DEBUG_ERR, "%s unknown level=%s\n", __func__, cmd, level);
}
return -RIG_EINVAL;
}
int kpa_get_powerstat(AMP *amp, powerstat_t *status)
{
char responsebuf[KPABUFSZ];
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
*status = RIG_POWER_UNKNOWN;
if (!amp) { return -RIG_EINVAL; }
int retval = kpa_transaction(amp, "^ON;", responsebuf, sizeof(responsebuf));
if (retval != RIG_OK) { return retval; }
int ampon;
int nargs = sscanf(responsebuf, "^ON%d", &ampon);
if (nargs != 1)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s Error: ^ON response='%s'\n", __func__,
responsebuf);
return -RIG_EPROTO;
}
switch (ampon)
{
case 0: *status = RIG_POWER_OFF; return RIG_OK;
case 1: *status = RIG_POWER_ON; break;
default:
rig_debug(RIG_DEBUG_VERBOSE, "%s Error: ^ON unknown response='%s'\n", __func__,
responsebuf);
return -RIG_EPROTO;
}
retval = kpa_transaction(amp, "^OP;", responsebuf, sizeof(responsebuf));
if (retval != RIG_OK) { return retval; }
int operate;
nargs = sscanf(responsebuf, "^ON%d", &operate);
if (nargs != 1)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s Error: ^ON response='%s'\n", __func__,
responsebuf);
return -RIG_EPROTO;
}
*status = operate == 1 ? RIG_POWER_OPERATE : RIG_POWER_STANDBY;
return RIG_OK;
}
int kpa_set_powerstat(AMP *amp, powerstat_t status)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp) { return -RIG_EINVAL; }
char *cmd = NULL;
switch (status)
{
case RIG_POWER_UNKNOWN: break;
case RIG_POWER_OFF: cmd = "^ON0;"; break;
case RIG_POWER_ON: cmd = "^ON1;"; break;
case RIG_POWER_OPERATE: cmd = "^OS1;"; break;
case RIG_POWER_STANDBY: cmd = "^OS0;"; break;
default:
rig_debug(RIG_DEBUG_ERR, "%s invalid status=%d\n", __func__, status);
}
int retval = kpa_transaction(amp, cmd, NULL, 0);
if (retval != RIG_OK) { return retval; }
return RIG_OK;
}
int kpa_reset(AMP *amp, amp_reset_t reset)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
// toggling from standby to operate supposed to reset
int retval = kpa_set_powerstat(amp, RIG_POWER_STANDBY);
if (retval != RIG_OK)
{
rig_debug(RIG_DEBUG_ERR, "%s error setting RIG_POWER_STANDBY\n", __func__,
strerror(retval));
}
return kpa_set_powerstat(amp, RIG_POWER_OPERATE);
}

Wyświetl plik

@ -0,0 +1,60 @@
/*
* Hamlib backend library for the Elecraft amplifier set.
*
* elecraft.h - (C) Michael Black W9MDB 2019
*
* This shared library provides an API for communicating
* via serial interface to Elecraft amplifiers.
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef _AMP_ELECRAFT_H
#define _AMP_ELECRAFT_H 1
#include <hamlib/amplifier.h>
#include <iofunc.h>
#include <serial.h>
// Is this big enough?
#define KPABUFSZ 100
extern const struct amp_caps kpa1500_rot_caps;
/*
* Private data structure
*/
struct kpa_priv_data
{
char tmpbuf[256]; // for unknown error msg
};
int kpa_init(AMP *amp);
int kpa_reset(AMP *amp, amp_reset_t reset);
int kpa_flush_buffer(AMP *amp);
int kpa_transaction(AMP *amp, const char *cmd, char *reponse, int reponse_len);
const char *kpa_get_info (AMP *amp);
int kpa_get_freq (AMP *amp, freq_t *freq);
int kpa_set_freq (AMP *amp, freq_t freq);
int kpa_get_level (AMP *amp, setting_t level, value_t *val);
int kpa_get_powerstat (AMP *amp, powerstat_t *status);
int kpa_set_powerstat (AMP *amp, powerstat_t status);
#endif /* _AMP_ELECRAFT_H */

Wyświetl plik

@ -0,0 +1,207 @@
/*
* Hamlib backend library for the Elecraft KPA1500 command set.
*
* kpa1500.c - (C) Michael Black W9MDB 2019
*
* This shared library provides an API for communicating
* to an Elecraft KPA1500 amplifier.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h> /* Standard library definitions */
#include <string.h> /* String function definitions */
#include "register.h"
#include "kpa.h"
struct kpa_priv_data *kpa1500_priv;
/*
* API local implementation
*
*/
static int kpa1500_init(AMP *amp);
static int kpa1500_cleanup(AMP *amp);
/*
* Private helper function prototypes
*/
//static int kpa1500_send_priv_cmd(AMP *amp, const char *cmd);
//static int kpa1500_flush_buffer(AMP *amp);
/* *************************************
*
* Separate model capabilities
*
* *************************************
*/
/*
* Elecraft KPA1500
*/
const struct amp_caps kpa1500_amp_caps =
{
.amp_model = AMP_MODEL_ELECRAFT_KPA1500,
.model_name = "KPA1500",
.mfg_name = "Elecraft",
.version = "2019-05-26",
.copyright = "LGPL",
.status = RIG_STATUS_ALPHA,
.amp_type = AMP_TYPE_OTHER,
.port_type = RIG_PORT_SERIAL,
.serial_rate_min = 4800,
.serial_rate_max = 230400,
.serial_data_bits = 8,
.serial_stop_bits = 1,
.serial_parity = RIG_PARITY_NONE,
.serial_handshake = RIG_HANDSHAKE_NONE,
.write_delay = 0,
.post_write_delay = 0,
.timeout = 2000,
.retry = 2,
.amp_open = amp_open,
.amp_init = kpa1500_init,
.amp_cleanup = kpa1500_cleanup,
.reset = kpa_reset,
.get_info = kpa_get_info,
.get_powerstat = kpa_get_powerstat,
.set_powerstat = kpa_set_powerstat,
.set_freq = kpa_set_freq,
.get_freq = kpa_get_freq,
.get_level = kpa_get_level,
};
/* ************************************
*
* API functions
*
* ************************************
*/
/*
* Initialize data structures
*/
static int kpa1500_init(AMP *amp)
{
struct kpa_priv_data *priv;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp)
{
return -RIG_EINVAL;
}
priv = (struct kpa_priv_data *)
malloc(sizeof(struct kpa_priv_data));
if (!priv)
{
return -RIG_ENOMEM;
}
amp->state.priv = (void *)priv;
amp->state.ampport.type.rig = RIG_PORT_SERIAL;
return RIG_OK;
}
/*
* Clean up allocated memory structures
*/
static int kpa1500_cleanup(AMP *amp)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp)
{
return -RIG_EINVAL;
}
if (amp->state.priv)
{
free(amp->state.priv);
}
amp->state.priv = NULL;
return RIG_OK;
}
/*
*
*/
#if 0
/*
* Send command string to amplifier
*/
static int kpa1500_send_priv_cmd(AMP *amp, const char *cmdstr)
{
struct amp_state *rs;
int err;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp)
{
return -RIG_EINVAL;
}
rs = &amp->state;
err = write_block(&rs->ampport, cmdstr, strlen(cmdstr));
if (err != RIG_OK)
{
return err;
}
return RIG_OK;
}
#endif
/*
* Initialize backend
*/
DECLARE_INITAMP_BACKEND(kpa1500)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
amp_register(&kpa1500_amp_caps);
return RIG_OK;
}

Wyświetl plik

@ -0,0 +1,34 @@
CC kpa.lo
kpa.c: In function kpa_get_freq:
kpa.c:150:12: warning: returning const char * from a function with return type int makes integer from pointer without a cast [-Wint-conversion]
return (const char *) - RIG_EINVAL;
^
kpa.c:153:3: error: rs undeclared (first use in this function)
rs = &amp->state;
^~
kpa.c:153:3: note: each undeclared identifier is reported only once for each function it appears in
kpa.c:156:45: warning: passing argument 3 of kpa_transaction makes integer from pointer without a cast [-Wint-conversion]
int retval = kpa_transaction(amp, "^FR;", reponsebuf, sizeof(reponsebuf));
^~~~~~~~~~
kpa.c:68:52: note: expected int but argument is of type char *
int kpa_transaction(AMP *amp, const char *cmd, int cmd_len, char *response,
~~~~^~~~~~~
kpa.c:156:57: warning: passing argument 4 of kpa_transaction makes pointer from integer without a cast [-Wint-conversion]
int retval = kpa_transaction(amp, "^FR;", reponsebuf, sizeof(reponsebuf));
^~~~~~~~~~~~~~~~~~
kpa.c:68:67: note: expected char * but argument is of type long unsigned int
int kpa_transaction(AMP *amp, const char *cmd, int cmd_len, char *response,
~~~~~~^~~~~~~~
kpa.c:156:16: error: too few arguments to function kpa_transaction
int retval = kpa_transaction(amp, "^FR;", reponsebuf, sizeof(reponsebuf));
^~~~~~~~~~~~~~~
kpa.c:68:5: note: declared here
int kpa_transaction(AMP *amp, const char *cmd, int cmd_len, char *response,
^~~~~~~~~~~~~~~
kpa.c:160:12: error: err undeclared (first use in this function)
return err;
^~~
kpa.c:167:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
make: *** [Makefile:479: kpa.lo] Error 1

Wyświetl plik

@ -51,6 +51,8 @@ dnl rotor definitions, e.g. "dummy". Optional backends will not be listed
dnl here but will be added later, e.g. "winradio".
BACKEND_LIST="adat alinco aor barrett dorji drake dummy elad flexradio icom icmarine jrc kachina kenwood kit lowe pcr prm80 racal rft rs skanti tapr tentec tuner uniden wj yaesu"
ROT_BACKEND_LIST="amsat ars celestron cnctrk easycomm ether6 fodtrack gs232a heathkit m2 meade rotorez sartek spid ts7400 prosistel ioptron"
# Amplifiers are all in the amplifiers directory
AMP_BACKEND_LIST="amplifiers/elecraft"
dnl See README.release on setting these values
# Values given to -version-info when linking. See libtool documentation.
@ -721,6 +723,21 @@ done
AC_SUBST([ROT_BACKEND_LIST])
AC_SUBST([ROT_BACKENDEPS])
## ---------------------------------- ##
## Prepare amplifier backend dependencies ##
## ---------------------------------- ##
# otherwise parallel 'make -jn' will fail
for be in ${AMP_BACKEND_LIST} ; do
AMPDIR=`echo $be | awk -F "/" '{print $2}'`
AMP_BACKENDEPS="${AMP_BACKENDEPS} \$(top_builddir)/amplifiers/${AMPDIR}/libhamlib-${AMPDIR}.la"
done
AC_SUBST([AMP_BACKEND_LIST])
AC_SUBST([AMP_BACKENDEPS])
## ------------ ##
## Final output ##
@ -790,6 +807,7 @@ dorji/Makefile
barrett/Makefile
meade/Makefile
ioptron/Makefile
amplifiers/elecraft/Makefile
hamlib.pc
])

Wyświetl plik

@ -1,4 +1,4 @@
DUMMYSRC = dummy.c dummy.h rot_dummy.c rot_dummy.h netrigctl.c netrotctl.c flrig.c flrig.h trxmanager.c trxmanager.h
DUMMYSRC = dummy.c dummy.h rot_dummy.c rot_dummy.h netrigctl.c netrotctl.c flrig.c flrig.h trxmanager.c trxmanager.h amp_dummy.c amp_dummy.h netampctl.c
noinst_LTLIBRARIES = libhamlib-dummy.la
libhamlib_dummy_la_SOURCES = $(DUMMYSRC)

374
dummy/amp_dummy.c 100644
Wyświetl plik

@ -0,0 +1,374 @@
/*
* Hamlib Dummy backend - main file
* Copyright (c) 2001-2009 by Stephane Fillod
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <math.h>
#include <sys/time.h>
#include <time.h>
#include "hamlib/amplifier.h"
#include "serial.h"
#include "misc.h"
#include "register.h"
#include "amp_dummy.h"
#if 0
static const struct confparams dummy_amp_ext_levels[] =
{
{
AMP_LEVEL_SWR, "SWR", "SWR", "SWR",
NULL, RIG_CONF_NUMERIC, { .n = { 1, 99, .1 } }
}
};
#endif
#define AMP_LEVELS (AMP_LEVEL_SWR|AMP_LEVEL_PF|AMP_LEVEL_NH|AMP_LEVEL_PWR_INPUT|AMP_LEVEL_PWR_FWD|AMP_LEVEL_PWR_REFLECTED|AMP_LEVEL_PWR_PEAK|AMP_LEVEL_FAULT)
struct dummy_amp_priv_data
{
freq_t freq;
powerstat_t powerstat;
};
static int dummy_amp_init(AMP *amp)
{
struct dummy_amp_priv_data *priv;
priv = (struct dummy_amp_priv_data *)
malloc(sizeof(struct dummy_amp_priv_data));
if (!priv)
{
return -RIG_ENOMEM;
}
amp->state.priv = (void *)priv;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
amp->state.ampport.type.rig = RIG_PORT_NONE;
priv->freq = 0;
return RIG_OK;
}
static int dummy_amp_cleanup(AMP *amp)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (amp->state.priv)
{
free(amp->state.priv);
}
amp->state.priv = NULL;
return RIG_OK;
}
static int dummy_amp_open(AMP *amp)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return RIG_OK;
}
static int dummy_amp_close(AMP *amp)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return RIG_OK;
}
static int dummy_amp_reset(AMP *amp, amp_reset_t reset)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
switch (reset)
{
case AMP_RESET_MEM:
rig_debug(RIG_DEBUG_VERBOSE, "Reset memory\n");
break;
case AMP_RESET_FAULT:
rig_debug(RIG_DEBUG_VERBOSE, "Reset fault\n");
break;
case AMP_RESET_AMP:
rig_debug(RIG_DEBUG_VERBOSE, "Reset amplifier\n");
break;
default:
rig_debug(RIG_DEBUG_VERBOSE, "Reset unknown=%d\n", reset);
return -RIG_EINVAL;
}
return RIG_OK;
}
/*
^ON1 turns amp on
^ON0 turns amp off
^OP0 amp in standby
^OP1 amp in operate
^PWF which gets forward power from amp. Reply would be ^PWFnnnn format
^PWK which gets peak forward power. Response is ^PWKnnnn
^PWR peak reflected power. Response is ^PWRnnnn
^SW gets SWR. Response is ^SWnnn. Example return of ^SW025 would be 2.5:1
Also a way to display faults (there are commands)
*/
static int dummy_amp_get_freq(AMP *amp, freq_t *freq)
{
struct dummy_amp_priv_data *priv = (struct dummy_amp_priv_data *)
amp->state.priv;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
*freq = priv->freq;
return RIG_OK;
}
static int dummy_amp_set_freq(AMP *amp, freq_t freq)
{
struct dummy_amp_priv_data *priv = (struct dummy_amp_priv_data *)
amp->state.priv;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
priv->freq = freq;
return RIG_OK;
}
static const char *dummy_amp_get_info(AMP *amp)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return "Dummy amplifier";
}
static int dummy_amp_get_level(AMP *amp, setting_t level, value_t *val)
{
static int flag = 1;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
flag = !flag;
// values toggle between two expected min/~max values for dev purposes
switch (level)
{
case AMP_LEVEL_SWR:
rig_debug(RIG_DEBUG_VERBOSE, "%s AMP_LEVEL_SWR\n", __func__);
val->f = flag == 0 ? 1.0 : 99.0;
return RIG_OK;
case AMP_LEVEL_PF:
rig_debug(RIG_DEBUG_VERBOSE, "%s AMP_LEVEL_PF\n", __func__);
val->f = flag == 0 ? 0 : 2701.2;
return RIG_OK;
case AMP_LEVEL_NH:
rig_debug(RIG_DEBUG_VERBOSE, "%s AMP_LEVEL_UH\n", __func__);
val->i = flag == 0 ? 0 : 8370;
return RIG_OK;
case AMP_LEVEL_PWR_INPUT:
rig_debug(RIG_DEBUG_VERBOSE, "%s AMP_LEVEL_PWRINPUT\n", __func__);
val->i = flag == 0 ? 0 : 1499 ;
return RIG_OK;
case AMP_LEVEL_PWR_FWD:
rig_debug(RIG_DEBUG_VERBOSE, "%s AMP_LEVEL_PWRFWD\n", __func__);
val->i = flag == 0 ? 0 : 1499 ;
return RIG_OK;
case AMP_LEVEL_PWR_REFLECTED:
rig_debug(RIG_DEBUG_VERBOSE, "%s AMP_LEVEL_PWRREFLECTED\n", __func__);
val->i = flag == 0 ? 0 : 1499 ;
return RIG_OK;
case AMP_LEVEL_PWR_PEAK:
rig_debug(RIG_DEBUG_VERBOSE, "%s AMP_LEVEL_PWRPEAK\n", __func__);
val->i = flag == 0 ? 0 : 1500 ;
return RIG_OK;
case AMP_LEVEL_FAULT:
rig_debug(RIG_DEBUG_VERBOSE, "%s AMP_LEVEL_FAULT\n", __func__);
val->s = flag == 0 ? "No Fault" : "SWR too high"; // SWR too high for KPA1500
return RIG_OK;
default:
rig_debug(RIG_DEBUG_VERBOSE, "%s Unknownd AMP_LEVEL=%d\n", __func__, level);
}
rig_debug(RIG_DEBUG_VERBOSE, "%s flag=%d\n", __func__, flag);
return -RIG_EINVAL;
}
static int dummy_amp_set_powerstat(AMP *amp, powerstat_t status)
{
struct dummy_amp_priv_data *priv = (struct dummy_amp_priv_data *)
amp->state.priv;
switch (status)
{
case RIG_POWER_OFF:
rig_debug(RIG_DEBUG_VERBOSE, "%s called POWER_OFF\n", __FUNCTION__);
break;
case RIG_POWER_ON:
rig_debug(RIG_DEBUG_VERBOSE, "%s called POWER_ON\n", __FUNCTION__);
break;
case RIG_POWER_STANDBY:
rig_debug(RIG_DEBUG_VERBOSE, "%s called POWER_STANDBY\n", __FUNCTION__);
break;
case RIG_POWER_OPERATE:
rig_debug(RIG_DEBUG_VERBOSE, "%s called POWER_OPERATE\n", __FUNCTION__);
break;
case RIG_POWER_UNKNOWN:
rig_debug(RIG_DEBUG_VERBOSE, "%s called POWER_UNKNOWN\n", __FUNCTION__);
break;
default:
rig_debug(RIG_DEBUG_VERBOSE, "%s called invalid power status=%d\n",
__FUNCTION__, status);
return -RIG_EINVAL;
break;
}
priv->powerstat = status;
return RIG_OK;
}
static int dummy_amp_get_powerstat(AMP *amp, powerstat_t *status)
{
struct dummy_amp_priv_data *priv = (struct dummy_amp_priv_data *)
amp->state.priv;
*status = priv->powerstat;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __FUNCTION__);
return RIG_OK;
}
#if 0
static int dummy_amp_get_ext_level(AMP *amp, token_t token, value_t *val)
{
struct dummy_amp_priv_data *priv = (struct dummy_amp_priv_data *)
amp->state.priv;
const struct confparams *cfp;
struct ext_list *elp;
cfp = amp_ext_lookup_tok(amp, token);
if (!cfp)
{
return -RIG_EINVAL;
}
switch (token)
{
case AMP_LEVEL_SWR:
break;
default:
return -RIG_EINVAL;
}
elp = find_ext(curr->ext_levels, token);
if (!elp)
{
return -RIG_EINTERNAL;
}
/* load value */
*val = elp->val;
rig_debug(RIG_DEBUG_VERBOSE, "%s called: %s\n", __FUNCTION__,
cfp->name);
return RIG_OK;
}
#endif
/*
* Dummy amplifier capabilities.
*/
const struct amp_caps dummy_amp_caps =
{
.amp_model = AMP_MODEL_DUMMY,
.model_name = "Dummy",
.mfg_name = "Hamlib",
.version = "0.1",
.copyright = "LGPL",
.status = RIG_STATUS_ALPHA,
.amp_type = AMP_TYPE_OTHER,
.port_type = RIG_PORT_NONE,
.has_get_level = AMP_LEVELS,
.has_set_level = RIG_LEVEL_SET(AMP_LEVELS),
.priv = NULL, /* priv */
.amp_init = dummy_amp_init,
.amp_cleanup = dummy_amp_cleanup,
.amp_open = dummy_amp_open,
.amp_close = dummy_amp_close,
.get_freq = dummy_amp_get_freq,
.set_freq = dummy_amp_set_freq,
.get_info = dummy_amp_get_info,
.get_level = dummy_amp_get_level,
.set_powerstat = dummy_amp_set_powerstat,
.get_powerstat = dummy_amp_get_powerstat,
.reset = dummy_amp_reset,
};
DECLARE_INITAMP_BACKEND(dummy)
{
rig_debug(RIG_DEBUG_VERBOSE, "dummy: _init called\n");
amp_register(&dummy_amp_caps);
amp_register(&netampctl_caps);
return RIG_OK;
}

29
dummy/amp_dummy.h 100644
Wyświetl plik

@ -0,0 +1,29 @@
/*
* Hamlib Dummy backend - main header
* Copyright (c) 2001-2008 by Stephane Fillod
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef _AMP_DUMMY_H
#define _AMP_DUMMY_H 1
extern const struct amp_caps dummy_amp_caps;
extern const struct amp_caps netampctl_caps;
#endif /* _AMP_DUMMY_H */

221
dummy/netampctl.c 100644
Wyświetl plik

@ -0,0 +1,221 @@
/*
* Hamlib Netampctl backend - main file
* Copyright (c) 2001-2009 by Stephane Fillod
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <math.h>
#include <errno.h>
#include "hamlib/amplifier.h"
#include "iofunc.h"
#include "misc.h"
#include "amp_dummy.h"
#define CMD_MAX 32
#define BUF_MAX 64
/*
* Helper function with protocol return code parsing
*/
static int netampctl_transaction(AMP *amp, char *cmd, int len, char *buf)
{
int ret;
ret = write_block(&amp->state.ampport, cmd, len);
if (ret != RIG_OK)
{
return ret;
}
ret = read_string(&amp->state.ampport, buf, BUF_MAX, "\n", sizeof("\n"));
if (ret < 0)
{
return ret;
}
if (!memcmp(buf, NETAMPCTL_RET, strlen(NETAMPCTL_RET)))
{
return atoi(buf + strlen(NETAMPCTL_RET));
}
return ret;
}
static int netampctl_open(AMP *amp)
{
int ret, len;
//struct amp_state *rs = &amp->state;
int pamp_ver;
char cmd[CMD_MAX];
char buf[BUF_MAX];
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __FUNCTION__);
len = sprintf(cmd, "\\dump_state\n");
ret = netampctl_transaction(amp, cmd, len, buf);
if (ret <= 0)
{
return (ret < 0) ? ret : -RIG_EPROTO;
}
pamp_ver = atoi(buf);
#define AMPCTLD_PAMP_VER 0
if (pamp_ver < AMPCTLD_PAMP_VER)
{
return -RIG_EPROTO;
}
ret = read_string(&amp->state.ampport, buf, BUF_MAX, "\n", sizeof("\n"));
if (ret <= 0)
{
return (ret < 0) ? ret : -RIG_EPROTO;
}
do
{
ret = read_string(&amp->state.ampport, buf, BUF_MAX, "\n", sizeof("\n"));
if (ret <= 0)
{
return (ret < 0) ? ret : -RIG_EPROTO;
}
rig_debug(RIG_DEBUG_VERBOSE, "%s called, string=%s\n", __FUNCTION__, buf);
}
while (ret > 0);
return RIG_OK;
}
static int netampctl_close(AMP *amp)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __FUNCTION__);
/* clean signoff, no read back */
write_block(&amp->state.ampport, "q\n", 2);
return RIG_OK;
}
static int netampctl_set_freq(AMP *amp, freq_t freq)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __FUNCTION__);
return -RIG_ENIMPL;
}
static int netampctl_get_freq(AMP *amp, freq_t *freq)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __FUNCTION__);
*freq = 12345;
return -RIG_ENIMPL;
}
#if 0
static int netampctl_reset(AMP *amp, amp_reset_t reset)
{
int ret, len;
char cmd[CMD_MAX];
char buf[BUF_MAX];
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __FUNCTION__);
len = sprintf(cmd, "R %d\n", reset);
ret = netampctl_transaction(amp, cmd, len, buf);
if (ret > 0)
{
return -RIG_EPROTO;
}
else
{
return ret;
}
}
#endif
static const char *netampctl_get_info(AMP *amp)
{
int ret, len;
char cmd[CMD_MAX];
static char buf[BUF_MAX];
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __FUNCTION__);
len = sprintf(cmd, "_\n");
ret = netampctl_transaction(amp, cmd, len, buf);
if (ret < 0)
{
return NULL;
}
buf [ret] = '\0';
return buf;
}
/*
* NET ampctl capabilities.
*/
const struct amp_caps netampctl_caps =
{
.amp_model = AMP_MODEL_NETAMPCTL,
.model_name = "NET ampctl",
.mfg_name = "Hamlib",
.version = "0.1",
.copyright = "LGPL",
.status = RIG_STATUS_ALPHA,
.amp_type = AMP_TYPE_OTHER,
.port_type = RIG_PORT_NETWORK,
.timeout = 2000,
.retry = 3,
.priv = NULL, /* priv */
/* .amp_init = netampctl_init, */
/* .amp_cleanup = netampctl_cleanup, */
.amp_open = netampctl_open,
.amp_close = netampctl_close,
.get_freq = netampctl_get_freq,
.set_freq = netampctl_set_freq,
.get_info = netampctl_get_info
};

Wyświetl plik

@ -0,0 +1,65 @@
/*
* Hamlib C++ bindings - rotator API header
* Copyright (c) 2002 by Stephane Fillod
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef _ROTCLASS_H
#define _ROTCLASS_H 1
#include <hamlib/rotator.h>
class BACKEND_IMPEXP Rotator
{
private:
ROT *theRot; // Global ref. to the rot
protected:
public:
Rotator(rot_model_t rot_model);
virtual ~Rotator();
const struct rot_caps *caps;
// This method opens the communication port to the rot
void open(void);
// This method closes the communication port to the rot
void close(void);
void setConf(token_t token, const char *val);
void setConf(const char *name, const char *val);
void getConf(token_t token, char *val);
void getConf(const char *name, char *val);
token_t tokenLookup(const char *name);
void setPosition(azimuth_t az, elevation_t el);
void getPosition(azimuth_t& az, elevation_t& el);
void stop();
void park();
void reset(rot_reset_t reset);
void move(int direction, int speed);
};
#endif // _ROTCLASS_H

Wyświetl plik

@ -0,0 +1,475 @@
/*
* Hamlib Interface - Amplifier API header
* Copyright (c) 2000-2005 by Stephane Fillod
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef _AMPLIFIER_H
#define _AMPLIFIER_H 1
#include <hamlib/rig.h>
#include <hamlib/amplist.h>
/**
* \addtogroup amp
* @{
*/
/**
* \file amp.h
* \brief Hamlib amplifier data structures.
*
* This file contains the data structures and declarations for the Hamlib
* amplifier API. see the amplifier.c file for more details on the amplifier API.
*/
__BEGIN_DECLS
/* Forward struct references */
struct amp;
struct amp_state;
/**
* \typedef typedef struct amp AMP
* \brief Amplifier structure definition (see amp for details).
*/
typedef struct amp AMP;
/**
* \typedef typedef float swr_t
* \brief Type definition for SWR.
*
* The swr_t type is used as a parameter for the amp_get_swr() function.
*
* Unless specified otherwise, the unit of swr_t is 1.0 to max reported by tuner
*/
typedef float swr_t;
/**
* \typedef typedef float tune_value_t
* \brief Type definition for tuning values capacitance and resistance.
*
* The tune_value_t type is used as a parameter for the amp_get_level()
*
* Unless specified otherwise, the units of tune_value_t is pF and nH
*/
typedef int tune_value_t;
/**
* \brief Token in the netampctl protocol for returning error code
*/
#define NETAMPCTL_RET "RPRT "
typedef enum
{
AMP_RESET_MEM, // erase tuner memory
AMP_RESET_FAULT, // reset any fault
AMP_RESET_AMP // for kpa1500
} amp_reset_t;
/**
* \brief Amplifier type flags
*/
typedef enum
{
AMP_FLAG_1 = (1 << 1), /*!< TBD */
AMP_FLAG_2 = (1 << 2) /*!< TBD */
} amp_type_t;
// TBD AMP_TYPE
#define AMP_TYPE_MASK (AMP_FLAG_1|AMP_FLAG_2)
#define AMP_TYPE_OTHER 0
#define AMP_TYPE_1 AMP_FLAG_1
#define AMP_TYPE_2 AMP_FLAG_2
#define AMP_TYPE_ALL (AMP_FLAG_1|AMP_FLAG_2)
enum amp_level_e
{
AMP_LEVEL_NONE = 0, /*!< '' -- No Level */
AMP_LEVEL_SWR = (1 << 0), /*!< \c SWR 1.0 or greater */
AMP_LEVEL_NH = (1 << 1), /*!< \c Tune setting nanohenries */
AMP_LEVEL_PF = (1 << 2), /*!< \c Tune setting picofarads */
AMP_LEVEL_PWR_INPUT = (1 << 3), /*!< \c Power reading from amp */
AMP_LEVEL_PWR_FWD = (1 << 4), /*!< \c Power reading forward */
AMP_LEVEL_PWR_REFLECTED = (1 << 5), /*!< \c Power reading reverse */
AMP_LEVEL_PWR_PEAK = (1 << 6), /*!< \c Power reading peak */
AMP_LEVEL_FAULT = (1 << 7) /*!< \c Fault code */
};
#define AMP_LEVEL_FLOAT_LIST (AMP_LEVEL_SWR)
#define AMP_LEVEL_STRING_LIST (AMP_LEVEL_FAULT)
#define AMP_LEVEL_IS_FLOAT(l) ((l)&AMP_LEVEL_FLOAT_LIST)
#define AMP_LEVEL_IS_STRING(l) ((l)&AMP_LEVEL_STRING_LIST)
/**
* \def AMP_MOVE_UP
* \brief A macro that returns the flag for the \b UP direction.
*
* This macro defines the value of the \b UP direction which can be
* used with the amp_move() function.
*
* \sa amp_move(), AMP_MOVE_DOWN, AMP_MOVE_LEFT, AMP_MOVE_CCW,
* AMP_MOVE_RIGHT, AMP_MOVE_CW
*/
#define AMP_MOVE_UP (1<<1)
/**
* \def AMP_MOVE_DOWN
* \brief A macro that returns the flag for the \b DOWN direction.
*
* This macro defines the value of the \b DOWN direction which can be
* used with the amp_move() function.
*
* \sa amp_move(), AMP_MOVE_UP, AMP_MOVE_LEFT, AMP_MOVE_CCW, AMP_MOVE_RIGHT,
* AMP_MOVE_CW
*/
#define AMP_MOVE_DOWN (1<<2)
/**
* \def AMP_MOVE_LEFT
* \brief A macro that returns the flag for the \b LEFT direction.
*
* This macro defines the value of the \b LEFT direction which can be
* used with the amp_move function.
*
* \sa amp_move(), AMP_MOVE_UP, AMP_MOVE_DOWN, AMP_MOVE_CCW, AMP_MOVE_RIGHT,
* AMP_MOVE_CW
*/
#define AMP_MOVE_LEFT (1<<3)
/**
* \def AMP_MOVE_CCW
* \brief A macro that returns the flag for the \b counterclockwise direction.
*
* This macro defines the value of the \b counterclockwise direction which
* can be used with the amp_move() function. This value is equivalent to
* AMP_MOVE_LEFT .
*
* \sa amp_move(), AMP_MOVE_UP, AMP_MOVE_DOWN, AMP_MOVE_LEFT, AMP_MOVE_RIGHT,
* AMP_MOVE_CW
*/
#define AMP_MOVE_CCW AMP_MOVE_LEFT
/**
* \def AMP_MOVE_RIGHT
* \brief A macro that returns the flag for the \b RIGHT direction.
*
* This macro defines the value of the \b RIGHT direction which can be used
* with the amp_move() function.
*
* \sa amp_move(), AMP_MOVE_UP, AMP_MOVE_DOWN, AMP_MOVE_LEFT, AMP_MOVE_CCW,
* AMP_MOVE_CW
*/
#define AMP_MOVE_RIGHT (1<<4)
/**
* \def AMP_MOVE_CW
* \brief A macro that returns the flag for the \b clockwise direction.
*
* This macro defines the value of the \b clockwise direction wich can be
* used with the amp_move() function. This value is equivalent to
* AMP_MOVE_RIGHT .
*
* \sa amp_move(), AMP_MOVE_UP, AMP_MOVE_DOWN, AMP_MOVE_LEFT, AMP_MOVE_CCW,
* AMP_MOVE_RIGHT
*/
#define AMP_MOVE_CW AMP_MOVE_RIGHT
/* Basic amp type, can store some useful info about different amplifiers. Each
* lib must be able to populate this structure, so we can make useful
* enquiries about capablilities.
*/
/**
* Amplifier Caps
* \struct amp_caps
* \brief Amplifier data structure.
*
* The main idea of this struct is that it will be defined by the backend
* amplifier driver, and will remain readonly for the application. Fields that
* need to be modifiable by the application are copied into the struct
* amp_state, which is a kind of private of the AMP instance.
*
* This way, you can have several rigs running within the same application,
* sharing the struct amp_caps of the backend, while keeping their own
* customized data.
*
* n.b.: Don't move fields around, as the backends depend on it when
* initializing their caps.
*/
struct amp_caps
{
amp_model_t amp_model; /*!< Amplifier model. */
const char *model_name; /*!< Model name. */
const char *mfg_name; /*!< Manufacturer. */
const char *version; /*!< Driver version. */
const char *copyright; /*!< Copyright info. */
enum rig_status_e status; /*!< Driver status. */
int amp_type; /*!< Amplifier type. */
enum rig_port_e port_type; /*!< Type of communication port. */
int serial_rate_min; /*!< Minimal serial speed. */
int serial_rate_max; /*!< Maximal serial speed. */
int serial_data_bits; /*!< Number of data bits. */
int serial_stop_bits; /*!< Number of stop bits. */
enum serial_parity_e serial_parity; /*!< Parity. */
enum serial_handshake_e serial_handshake; /*!< Handshake. */
int write_delay; /*!< Write delay. */
int post_write_delay; /*!< Post-write delay. */
int timeout; /*!< Timeout. */
int retry; /*!< Number of retry if command fails. */
const struct confparams *cfgparams; /*!< Configuration parametres. */
const rig_ptr_t priv; /*!< Private data. */
setting_t has_get_level;
setting_t has_set_level;
gran_t level_gran[RIG_SETTING_MAX]; /*!< level granularity */
gran_t parm_gran[RIG_SETTING_MAX]; /*!< level granularity */
/*
* Amp Admin API
*
*/
int (*amp_init)(AMP *amp);
int (*amp_cleanup)(AMP *amp);
int (*amp_open)(AMP *amp);
int (*amp_close)(AMP *amp);
int (*set_freq)(AMP *amp, freq_t val);
int (*get_freq)(AMP *amp, freq_t *val);
int (*set_conf)(AMP *amp, token_t token, const char *val);
int (*get_conf)(AMP *amp, token_t token, char *val);
/*
* General API commands, from most primitive to least.. :()
* List Set/Get functions pairs
*/
int (*reset)(AMP *amp, amp_reset_t reset);
int (*get_level)(AMP *amp, setting_t level, value_t *val);
int (*get_ext_level)(AMP *amp, token_t level, value_t *val);
int (*set_powerstat)(AMP *amp, powerstat_t status);
int (*get_powerstat)(AMP *amp, powerstat_t *status);
/* get firmware info, etc. */
const char *(*get_info)(AMP *amp);
setting_t levels;
unsigned ext_levels;
const struct confparams *extlevels;
const struct confparams *extparms;
};
/**
* Amplifier state
* \struct amp_state
* \brief Live data and customized fields.
*
* This struct contains live data, as well as a copy of capability fields
* that may be updated (ie. customized)
*
* It is fine to move fields around, as this kind of struct should
* not be initialized like caps are.
*/
struct amp_state
{
/*
* overridable fields
*/
/*
* non overridable fields, internal use
*/
hamlib_port_t ampport; /*!< Amplifier port (internal use). */
int comm_state; /*!< Comm port state, opened/closed. */
rig_ptr_t priv; /*!< Pointer to private amplifier state data. */
rig_ptr_t obj; /*!< Internal use by hamlib++ for event handling. */
setting_t has_get_level;
gran_t level_gran[RIG_SETTING_MAX]; /*!< level granularity */
gran_t parm_gran[RIG_SETTING_MAX]; /*!< level granularity */
};
/**
* Amplifier structure
* \struct amp
* \brief This is the master data structure,
* acting as a handle for the controlled amplifier.
*
* This is the master data structure, acting as a handle for the controlled
* amplifier. A pointer to this structure is returned by the amp_init() API
* function and is passed as a parameter to every amplifier specific API call.
*
* \sa amp_init(), amp_caps(), amp_state()
*/
struct amp
{
struct amp_caps *caps; /*!< Amplifier caps. */
struct amp_state state; /*!< Amplifier state. */
};
/* --------------- API function prototypes -----------------*/
extern HAMLIB_EXPORT(AMP *)
amp_init HAMLIB_PARAMS((amp_model_t amp_model));
extern HAMLIB_EXPORT(int)
amp_open HAMLIB_PARAMS((AMP *amp));
extern HAMLIB_EXPORT(int)
amp_close HAMLIB_PARAMS((AMP *amp));
extern HAMLIB_EXPORT(int)
amp_cleanup HAMLIB_PARAMS((AMP *amp));
extern HAMLIB_EXPORT(int)
amp_set_conf HAMLIB_PARAMS((AMP *amp,
token_t token,
const char *val));
extern HAMLIB_EXPORT(int)
amp_get_conf HAMLIB_PARAMS((AMP *amp,
token_t token,
char *val));
extern HAMLIB_EXPORT(int)
amp_set_powerstat HAMLIB_PARAMS((AMP *amp,
powerstat_t status));
extern HAMLIB_EXPORT(int)
amp_get_powerstat HAMLIB_PARAMS((AMP *amp,
powerstat_t *status));
/*
* General API commands, from most primitive to least.. )
* List Set/Get functions pairs
*/
extern HAMLIB_EXPORT(int)
amp_get_freq HAMLIB_PARAMS((AMP *amp,
freq_t *freq));
extern HAMLIB_EXPORT(int)
amp_set_freq HAMLIB_PARAMS((AMP *amp,
freq_t freq));
extern HAMLIB_EXPORT(int)
amp_reset HAMLIB_PARAMS((AMP *amp,
amp_reset_t reset));
extern HAMLIB_EXPORT(const char *)
amp_get_info HAMLIB_PARAMS((AMP *amp));
extern HAMLIB_EXPORT(int)
amp_get_level HAMLIB_PARAMS((AMP *amp, setting_t level, value_t *val));
extern HAMLIB_EXPORT(int)
amp_register HAMLIB_PARAMS((const struct amp_caps *caps));
extern HAMLIB_EXPORT(int)
amp_unregister HAMLIB_PARAMS((amp_model_t amp_model));
extern HAMLIB_EXPORT(int)
amp_list_foreach HAMLIB_PARAMS((int (*cfunc)(const struct amp_caps *,
rig_ptr_t),
rig_ptr_t data));
extern HAMLIB_EXPORT(int)
amp_load_backend HAMLIB_PARAMS((const char *be_name));
extern HAMLIB_EXPORT(int)
amp_check_backend HAMLIB_PARAMS((amp_model_t amp_model));
extern HAMLIB_EXPORT(int)
amp_load_all_backends HAMLIB_PARAMS((void));
extern HAMLIB_EXPORT(amp_model_t)
amp_probe_all HAMLIB_PARAMS((hamlib_port_t *p));
extern HAMLIB_EXPORT(int)
amp_token_foreach HAMLIB_PARAMS((AMP *amp,
int (*cfunc)(const struct confparams *,
rig_ptr_t),
rig_ptr_t data));
extern HAMLIB_EXPORT(const struct confparams *)
amp_confparam_lookup HAMLIB_PARAMS((AMP *amp,
const char *name));
extern HAMLIB_EXPORT(token_t)
amp_token_lookup HAMLIB_PARAMS((AMP *amp,
const char *name));
extern HAMLIB_EXPORT(const struct amp_caps *)
amp_get_caps HAMLIB_PARAMS((amp_model_t amp_model));
extern HAMLIB_EXPORT(setting_t)
amp_has_get_level HAMLIB_PARAMS((AMP *amp,
setting_t level));
extern HAMLIB_EXPORT(const struct confparams *)
amp_ext_lookup HAMLIB_PARAMS((AMP *amp,
const char *name));
extern HAMLIB_EXPORT(int)
amp_get_ext_level HAMLIB_PARAMS((AMP *amp,
token_t token,
value_t *val));
extern HAMLIB_EXPORT(const char *) amp_strlevel(setting_t);
extern HAMLIB_EXPORT(const struct confparams *)
rig_ext_lookup HAMLIB_PARAMS((RIG *rig,
const char *name));
/**
* \def amp_debug
* \brief Convenience definition for debug level.
*
* This is just as convenience definition of the amplifier debug level,
* and is the same as for the rig debug level.
*
* \sa rig_debug()
*/
#define amp_debug rig_debug
__END_DECLS
#endif /* _AMPLIFIER_H */
/** @} */

Wyświetl plik

@ -0,0 +1,104 @@
/*
* Hamlib Interface - list of known amplifiers
* Copyright (c) 2000-2011 by Stephane Fillod
* Copyright (c) 2000-2002 by Frank Singleton
* Copyright (C) 2019 by Michael Black W9MDB. Derived from rotlist.h
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef _AMPLIST_H
#define _AMPLIST_H 1
#define AMP_MAKE_MODEL(a,b) ((a)*100+(b))
#define AMP_BACKEND_NUM(a) ((a)/100)
/**
* \addtogroup amplifier
* @{
*/
/**
* \file rotlist.h
* \brief Hamlib amplifier model definitions.
*
* This file contains amplifier model definitions for the Hamlib amplifier API.
* Each distinct amplifier type has a unique model number (ID) and is used by
* hamlib to identify and distinguish between the different hardware drivers.
* The exact model numbers can be acquired using the macros in this file. To
* obtain a list of supported amplifier branches, one can use the statically
* defined AMP_BACKEND_LIST macro. To obtain a full list of supported
* amplifier (including each model in every branch), the foreach_opened_rot()
* API function can be used.
*
* The model number, or ID, is used to tell Hamlib which amplifier the client
* whishes to use. It is done with the amp_init() API call.
*/
#define AMP_MODEL_NONE 0
/**
* \def AMP_MODEL_DUMMY
* \brief A macro that returns the model number for the dummy backend.
*
* The dummy backend, as the name suggests, is a backend which performs
* no hardware operations and always behaves as one would expect. It can
* be thought of as a hardware simulator and is very usefull for testing
* client applications.
*/
/**
* \def AMP_MODEL_NETAMPCTL
* \brief A macro that returns the model number for the Network backend.
*
* This backend allows use of the rotctld daemon through the normal
* Hamlib API.
*/
#define AMP_DUMMY 0
#define AMP_BACKEND_DUMMY "dummy"
#define AMP_MODEL_DUMMY AMP_MAKE_MODEL(AMP_DUMMY, 1)
#define AMP_MODEL_NETAMPCTL AMP_MAKE_MODEL(AMP_DUMMY, 2)
/*
* Elecraft
*/
/**
* \def AMP_MODEL_ELECRAFT1
* \brief A macro that returns the model number of the EasyComm 1 backend.
*
* The Elecraft 1 backend can be used with amplifiers that support the
* KPA1500 protocol.
*/
#define AMP_ELECRAFT 2
#define AMP_BACKEND_ELECRAFT "elecraft"
#define AMP_MODEL_ELECRAFT_KPA1500 AMP_MAKE_MODEL(AMP_ELECRAFT, 1)
//#define AMP_MODEL_ELECRAFT_KPA500 AMP_MAKE_MODEL(AMP_ELECRAFT, 2)
/**
* \typedef typedef int amp_model_t
* \brief Convenience type definition for amplifier model.
*/
typedef int amp_model_t;
#endif /* _AMPLIST_H */
/** @} */

Wyświetl plik

@ -69,9 +69,11 @@
|| defined(__cplusplus)
# define HAMLIB_PARAMS(protos) protos
# define rig_ptr_t void *
# define amp_ptr_t void *
#else
# define HAMLIB_PARAMS(protos) ()
# define rig_ptr_t char *
# define amp_ptr_t char *
#endif
#include <hamlib/rig_dll.h>
@ -482,7 +484,9 @@ typedef enum {
typedef enum {
RIG_POWER_OFF = 0, /*!< Power off */
RIG_POWER_ON = (1 << 0), /*!< Power on */
RIG_POWER_STANDBY = (1 << 1) /*!< Standby */
RIG_POWER_STANDBY = (1 << 1), /*!< Standby */
RIG_POWER_OPERATE = (1 << 2), /*!< Operate (from Standby) */
RIG_POWER_UNKNOWN = (1 << 3) /*!< Unknown power status */
} powerstat_t;
@ -728,6 +732,7 @@ enum rig_level_e {
/* RIG_LEVEL_BWC = (1<<31) */ /*!< Bandwidth Control, arg int (Hz) */
};
#define RIG_LEVEL_FLOAT_LIST (RIG_LEVEL_AF|RIG_LEVEL_RF|RIG_LEVEL_SQL|RIG_LEVEL_APF|RIG_LEVEL_NR|RIG_LEVEL_PBT_IN|RIG_LEVEL_PBT_OUT|RIG_LEVEL_RFPOWER|RIG_LEVEL_MICGAIN|RIG_LEVEL_COMP|RIG_LEVEL_BALANCE|RIG_LEVEL_SWR|RIG_LEVEL_ALC|RIG_LEVEL_VOXGAIN|RIG_LEVEL_ANTIVOX)
#define RIG_LEVEL_READONLY_LIST (RIG_LEVEL_SQLSTAT|RIG_LEVEL_SWR|RIG_LEVEL_ALC|RIG_LEVEL_STRENGTH|RIG_LEVEL_RAWSTR)
@ -761,9 +766,6 @@ enum rig_parm_e {
#define RIG_PARM_IS_FLOAT(l) ((l)&RIG_PARM_FLOAT_LIST)
#define RIG_PARM_SET(l) ((l)&~RIG_PARM_READONLY_LIST)
#define RIG_SETTING_MAX 64
/**
* \brief Setting
*
@ -772,6 +774,9 @@ enum rig_parm_e {
*/
typedef uint64_t setting_t;
#define RIG_SETTING_MAX 64
/**
* \brief Tranceive mode
*
@ -2343,6 +2348,7 @@ extern HAMLIB_EXPORT(rmode_t) rig_parse_mode(const char *s);
extern HAMLIB_EXPORT(vfo_t) rig_parse_vfo(const char *s);
extern HAMLIB_EXPORT(setting_t) rig_parse_func(const char *s);
extern HAMLIB_EXPORT(setting_t) rig_parse_level(const char *s);
extern HAMLIB_EXPORT(setting_t) amp_parse_level(const char *s);
extern HAMLIB_EXPORT(setting_t) rig_parse_parm(const char *s);
extern HAMLIB_EXPORT(vfo_op_t) rig_parse_vfo_op(const char *s);
extern HAMLIB_EXPORT(scan_t) rig_parse_scan(const char *s);

Wyświetl plik

@ -4,15 +4,16 @@ RIGSRC = rig.c serial.c serial.h misc.c misc.h register.c register.h event.c \
event.h cal.c cal.h conf.c tones.c tones.h rotator.c locator.c rot_reg.c \
rot_conf.c rot_conf.h iofunc.c iofunc.h ext.c mem.c settings.c \
parallel.c parallel.h usb_port.c usb_port.h debug.c network.c network.h \
cm108.c cm108.h gpio.c gpio.h idx_builtin.h token.h par_nt.h microham.c microham.h
cm108.c cm108.h gpio.c gpio.h idx_builtin.h token.h par_nt.h microham.c microham.h \
amplifier.c amp_reg.c amp_conf.c amp_conf.h extamp.c
lib_LTLIBRARIES = libhamlib.la
libhamlib_la_SOURCES = $(RIGSRC)
libhamlib_la_LDFLAGS = $(WINLDFLAGS) $(OSXLDFLAGS) -no-undefined -version-info $(ABI_VERSION):$(ABI_REVISION):$(ABI_AGE)
libhamlib_la_LIBADD = $(top_builddir)/lib/libmisc.la \
$(BACKENDEPS) $(ROT_BACKENDEPS) $(NET_LIBS) $(MATH_LIBS) $(LIBUSB_LIBS)
$(BACKENDEPS) $(ROT_BACKENDEPS) $(AMP_BACKENDEPS) $(NET_LIBS) $(MATH_LIBS) $(LIBUSB_LIBS)
libhamlib_la_DEPENDENCIES = $(top_builddir)/lib/libmisc.la $(BACKENDEPS) $(ROT_BACKENDEPS)
libhamlib_la_DEPENDENCIES = $(top_builddir)/lib/libmisc.la $(BACKENDEPS) $(ROT_BACKENDEPS) $(AMP_BACKENDEPS)
EXTRA_DIST = Android.mk

695
src/amp_conf.c 100644
Wyświetl plik

@ -0,0 +1,695 @@
/*
* Hamlib Interface - amplifier configuration interface
* Copyright (c) 2000-2010 by Stephane Fillod
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/**
* \addtogroup amplifier
* @{
*/
/**
* \brief Amplifier Configuration Interface
* \file amp_conf.c
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <hamlib/amplifier.h>
#include "amp_conf.h"
#include "token.h"
/*
* Configuration options available in the amp->state struct.
*/
static const struct confparams ampfrontend_cfg_params[] =
{
{
TOK_PATHNAME, "amp_pathname", "Rig path name",
"Path name to the device file of the amplifier",
"/dev/amplifier", RIG_CONF_STRING,
},
{
TOK_WRITE_DELAY, "write_delay", "Write delay",
"Delay in ms between each byte sent out",
"0", RIG_CONF_NUMERIC, { .n = { 0, 1000, 1 } }
},
{
TOK_POST_WRITE_DELAY, "post_write_delay", "Post write delay",
"Delay in ms between each command sent out",
"0", RIG_CONF_NUMERIC, { .n = { 0, 1000, 1 } }
},
{
TOK_TIMEOUT, "timeout", "Timeout", "Timeout in ms",
"0", RIG_CONF_NUMERIC, { .n = { 0, 10000, 1 } }
},
{
TOK_RETRY, "retry", "Retry", "Max number of retry",
"0", RIG_CONF_NUMERIC, { .n = { 0, 10, 1 } }
},
{
TOK_MIN_AZ, "min_az", "Minimum azimuth",
"Minimum amplifier azimuth in degrees",
"-180", RIG_CONF_NUMERIC, { .n = { -360, 360, .001 } }
},
{
TOK_MAX_AZ, "max_az", "Maximum azimuth",
"Maximum amplifier azimuth in degrees",
"180", RIG_CONF_NUMERIC, { .n = { -360, 360, .001 } }
},
{
TOK_MIN_EL, "min_el", "Minimum elevation",
"Minimum amplifier elevation in degrees",
"0", RIG_CONF_NUMERIC, { .n = { -90, 180, .001 } }
},
{
TOK_MAX_EL, "max_el", "Maximum elevation",
"Maximum amplifier elevation in degrees",
"90", RIG_CONF_NUMERIC, { .n = { -90, 180, .001 } }
},
{ RIG_CONF_END, NULL, }
};
static const struct confparams ampfrontend_serial_cfg_params[] =
{
{
TOK_SERIAL_SPEED, "serial_speed", "Serial speed",
"Serial port baud rate",
"0", RIG_CONF_NUMERIC, { .n = { 300, 115200, 1 } }
},
{
TOK_DATA_BITS, "data_bits", "Serial data bits",
"Serial port data bits",
"8", RIG_CONF_NUMERIC, { .n = { 5, 8, 1 } }
},
{
TOK_STOP_BITS, "stop_bits", "Serial stop bits",
"Serial port stop bits",
"1", RIG_CONF_NUMERIC, { .n = { 0, 3, 1 } }
},
{
TOK_PARITY, "serial_parity", "Serial parity",
"Serial port parity",
"None", RIG_CONF_COMBO, { .c = {{ "None", "Odd", "Even", "Mark", "Space", NULL }} }
},
{
TOK_HANDSHAKE, "serial_handshake", "Serial handshake",
"Serial port handshake",
"None", RIG_CONF_COMBO, { .c = {{ "None", "XONXOFF", "Hardware", NULL }} }
},
{ RIG_CONF_END, NULL, }
};
/**
* \brief Set amplifier state info from alpha input
* \param amp
* \param token TOK_... specifying which info to set
* \param val input
* \return RIG_OK or < 0 error
*
* assumes amp!=NULL, val!=NULL
*/
int frontamp_set_conf(AMP *amp, token_t token, const char *val)
{
struct amp_state *rs;
int val_i;
rs = &amp->state;
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
switch (token)
{
case TOK_PATHNAME:
strncpy(rs->ampport.pathname, val, FILPATHLEN - 1);
break;
case TOK_WRITE_DELAY:
if (1 != sscanf(val, "%d", &val_i))
{
return -RIG_EINVAL;
}
rs->ampport.write_delay = val_i;
break;
case TOK_POST_WRITE_DELAY:
if (1 != sscanf(val, "%d", &val_i))
{
return -RIG_EINVAL;
}
rs->ampport.post_write_delay = val_i;
break;
case TOK_TIMEOUT:
if (1 != sscanf(val, "%d", &val_i))
{
return -RIG_EINVAL;
}
rs->ampport.timeout = val_i;
break;
case TOK_RETRY:
if (1 != sscanf(val, "%d", &val_i))
{
return -RIG_EINVAL;
}
rs->ampport.retry = val_i;
break;
case TOK_SERIAL_SPEED:
if (rs->ampport.type.rig != RIG_PORT_SERIAL)
{
return -RIG_EINVAL;
}
if (1 != sscanf(val, "%d", &val_i))
{
return -RIG_EINVAL;
}
rs->ampport.parm.serial.rate = val_i;
break;
case TOK_DATA_BITS:
if (rs->ampport.type.rig != RIG_PORT_SERIAL)
{
return -RIG_EINVAL;
}
if (1 != sscanf(val, "%d", &val_i))
{
return -RIG_EINVAL;
}
rs->ampport.parm.serial.data_bits = val_i;
break;
case TOK_STOP_BITS:
if (rs->ampport.type.rig != RIG_PORT_SERIAL)
{
return -RIG_EINVAL;
}
if (1 != sscanf(val, "%d", &val_i))
{
return -RIG_EINVAL;
}
rs->ampport.parm.serial.stop_bits = val_i;
break;
case TOK_PARITY:
if (rs->ampport.type.rig != RIG_PORT_SERIAL)
{
return -RIG_EINVAL;
}
if (!strcmp(val, "None"))
{
rs->ampport.parm.serial.parity = RIG_PARITY_NONE;
}
else if (!strcmp(val, "Odd"))
{
rs->ampport.parm.serial.parity = RIG_PARITY_ODD;
}
else if (!strcmp(val, "Even"))
{
rs->ampport.parm.serial.parity = RIG_PARITY_EVEN;
}
else if (!strcmp(val, "Mark"))
{
rs->ampport.parm.serial.parity = RIG_PARITY_MARK;
}
else if (!strcmp(val, "Space"))
{
rs->ampport.parm.serial.parity = RIG_PARITY_SPACE;
}
else
{
return -RIG_EINVAL;
}
break;
case TOK_HANDSHAKE:
if (rs->ampport.type.rig != RIG_PORT_SERIAL)
{
return -RIG_EINVAL;
}
if (!strcmp(val, "None"))
{
rs->ampport.parm.serial.handshake = RIG_HANDSHAKE_NONE;
}
else if (!strcmp(val, "XONXOFF"))
{
rs->ampport.parm.serial.handshake = RIG_HANDSHAKE_XONXOFF;
}
else if (!strcmp(val, "Hardware"))
{
rs->ampport.parm.serial.handshake = RIG_HANDSHAKE_HARDWARE;
}
else
{
return -RIG_EINVAL;
}
break;
#if 0
case TOK_MIN_AZ:
rs->min_az = atof(val);
break;
case TOK_MAX_AZ:
rs->max_az = atof(val);
break;
case TOK_MIN_EL:
rs->min_el = atof(val);
break;
case TOK_MAX_EL:
rs->max_el = atof(val);
break;
#endif
default:
return -RIG_EINVAL;
}
return RIG_OK;
}
/**
* \brief Get data from amplifier state in alpha form
* \param amp non-null
* \param token TOK_... specifying which data to get
* \param val result non-null
* \return RIG_OK or < 0 if error
*/
int frontamp_get_conf(AMP *amp, token_t token, char *val)
{
struct amp_state *rs;
const char *s;
rs = &amp->state;
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
switch (token)
{
case TOK_PATHNAME:
strcpy(val, rs->ampport.pathname);
break;
case TOK_WRITE_DELAY:
sprintf(val, "%d", rs->ampport.write_delay);
break;
case TOK_POST_WRITE_DELAY:
sprintf(val, "%d", rs->ampport.post_write_delay);
break;
case TOK_TIMEOUT:
sprintf(val, "%d", rs->ampport.timeout);
break;
case TOK_RETRY:
sprintf(val, "%d", rs->ampport.retry);
break;
case TOK_SERIAL_SPEED:
if (rs->ampport.type.rig != RIG_PORT_SERIAL)
{
return -RIG_EINVAL;
}
sprintf(val, "%d", rs->ampport.parm.serial.rate);
break;
case TOK_DATA_BITS:
if (rs->ampport.type.rig != RIG_PORT_SERIAL)
{
return -RIG_EINVAL;
}
sprintf(val, "%d", rs->ampport.parm.serial.data_bits);
break;
case TOK_STOP_BITS:
if (rs->ampport.type.rig != RIG_PORT_SERIAL)
{
return -RIG_EINVAL;
}
sprintf(val, "%d", rs->ampport.parm.serial.stop_bits);
break;
case TOK_PARITY:
if (rs->ampport.type.rig != RIG_PORT_SERIAL)
{
return -RIG_EINVAL;
}
switch (rs->ampport.parm.serial.parity)
{
case RIG_PARITY_NONE:
s = "None";
break;
case RIG_PARITY_ODD:
s = "Odd";
break;
case RIG_PARITY_EVEN:
s = "Even";
break;
case RIG_PARITY_MARK:
s = "Mark";
break;
case RIG_PARITY_SPACE:
s = "Space";
break;
default:
return -RIG_EINVAL;
}
strcpy(val, s);
break;
case TOK_HANDSHAKE:
if (rs->ampport.type.rig != RIG_PORT_SERIAL)
{
return -RIG_EINVAL;
}
switch (rs->ampport.parm.serial.handshake)
{
case RIG_HANDSHAKE_NONE:
s = "None";
break;
case RIG_HANDSHAKE_XONXOFF:
s = "XONXOFF";
break;
case RIG_HANDSHAKE_HARDWARE:
s = "Hardware";
break;
default:
return -RIG_EINVAL;
}
strcpy(val, s);
break;
#if 0
case TOK_MIN_AZ:
sprintf(val, "%f", rs->min_az);
break;
case TOK_MAX_AZ:
sprintf(val, "%f", rs->max_az);
break;
case TOK_MIN_EL:
sprintf(val, "%f", rs->min_el);
break;
case TOK_MAX_EL:
sprintf(val, "%f", rs->max_el);
break;
#endif
default:
return -RIG_EINVAL;
}
return RIG_OK;
}
/**
* \brief Executes cfunc on all the elements stored in the conf table
* \param amp non-null
* \param cfunc function(..)
* \param data
*
* start first with backend conf table, then finish with frontend table
*/
int HAMLIB_API amp_token_foreach(AMP *amp,
int (*cfunc)(const struct confparams *,
rig_ptr_t),
rig_ptr_t data)
{
const struct confparams *cfp;
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp || !amp->caps || !cfunc)
{
return -RIG_EINVAL;
}
for (cfp = ampfrontend_cfg_params; cfp->name; cfp++)
{
if ((*cfunc)(cfp, data) == 0)
{
return RIG_OK;
}
}
if (amp->caps->port_type == RIG_PORT_SERIAL)
{
for (cfp = ampfrontend_serial_cfg_params; cfp->name; cfp++)
{
if ((*cfunc)(cfp, data) == 0)
{
return RIG_OK;
}
}
}
for (cfp = amp->caps->cfgparams; cfp && cfp->name; cfp++)
{
if ((*cfunc)(cfp, data) == 0)
{
return RIG_OK;
}
}
return RIG_OK;
}
/**
* \brief lookup conf token by its name, return pointer to confparams struct.
* \param amp
* \param name
* \return confparams or NULL
*
* lookup backend config table first, then fall back to frontend.
* TODO: should use Lex to speed it up, strcmp hurts!
*/
const struct confparams *HAMLIB_API amp_confparam_lookup(AMP *amp,
const char *name)
{
const struct confparams *cfp;
token_t token;
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp || !amp->caps)
{
return NULL;
}
/* 0 returned for invalid format */
token = strtol(name, NULL, 0);
for (cfp = amp->caps->cfgparams; cfp && cfp->name; cfp++)
{
if (!strcmp(cfp->name, name) || token == cfp->token)
{
return cfp;
}
}
for (cfp = ampfrontend_cfg_params; cfp->name; cfp++)
{
if (!strcmp(cfp->name, name) || token == cfp->token)
{
return cfp;
}
}
if (amp->caps->port_type == RIG_PORT_SERIAL)
{
for (cfp = ampfrontend_serial_cfg_params; cfp->name; cfp++)
{
if (!strcmp(cfp->name, name) || token == cfp->token)
{
return cfp;
}
}
}
return NULL;
}
/**
* \brief Simple lookup returning token id associated with name
* \param amp
* \param name
* \return token enum
*/
token_t HAMLIB_API amp_token_lookup(AMP *amp, const char *name)
{
const struct confparams *cfp;
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
cfp = amp_confparam_lookup(amp, name);
if (!cfp)
{
return RIG_CONF_END;
}
return cfp->token;
}
/**
* \brief set a amplifier configuration parameter
* \param amp The amp handle
* \param token The parameter
* \param val The value to set the parameter to
*
* Sets a configuration parameter.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa amp_get_conf()
*/
int HAMLIB_API amp_set_conf(AMP *amp, token_t token, const char *val)
{
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp || !amp->caps)
{
return -RIG_EINVAL;
}
if (rig_need_debug(RIG_DEBUG_VERBOSE))
{
const struct confparams *cfp;
char tokenstr[12];
sprintf(tokenstr, "%ld", token);
cfp = amp_confparam_lookup(amp, tokenstr);
if (!cfp)
{
return -RIG_EINVAL;
}
amp_debug(RIG_DEBUG_VERBOSE, "%s: %s='%s'\n", __func__, cfp->name, val);
}
if (IS_TOKEN_FRONTEND(token))
{
return frontamp_set_conf(amp, token, val);
}
if (amp->caps->set_conf == NULL)
{
return -RIG_ENAVAIL;
}
return amp->caps->set_conf(amp, token, val);
}
/**
* \brief get the value of a configuration parameter
* \param amp The amp handle
* \param token The parameter
* \param val The location where to store the value of config \a token
*
* Retrieves the value of a configuration paramter associated with \a token.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa amp_set_conf()
*/
int HAMLIB_API amp_get_conf(AMP *amp, token_t token, char *val)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp || !amp->caps || !val)
{
return -RIG_EINVAL;
}
if (IS_TOKEN_FRONTEND(token))
{
return frontamp_get_conf(amp, token, val);
}
if (amp->caps->get_conf == NULL)
{
return -RIG_ENAVAIL;
}
return amp->caps->get_conf(amp, token, val);
}
/** @} */

31
src/amp_conf.h 100644
Wyświetl plik

@ -0,0 +1,31 @@
/*
* Hamlib Interface - configuration header
* Copyright (c) 2000,2001,2002 by Stephane Fillod and Frank Singleton
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef _AMP_CONF_H
#define _AMP_CONF_H 1
#include <hamlib/amplifier.h>
int frontamp_set_conf(AMP *amp, token_t token, const char *val);
int frontamp_get_conf(AMP *amp, token_t token, char *val);
#endif /* _AMP_CONF_H */

381
src/amp_reg.c 100644
Wyświetl plik

@ -0,0 +1,381 @@
/*
* Hamlib Interface - provides registering for dynamically loadable backends.
* Copyright (c) 2000-2004 by Stephane Fillod
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/**
* \brief Dynamic registration of amplifier backends
* \file amp_reg.c
*
* Similar to register.c
* doc todo: Let's explain what's going on here!
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <hamlib/amplifier.h>
#include "register.h"
#ifndef PATH_MAX
# define PATH_MAX 1024
#endif
#define AMP_BACKEND_MAX 32
#define DEFINE_INITAMP_BACKEND(backend) \
int MAKE_VERSIONED_FN(PREFIX_INITAMPS, \
ABI_VERSION, \
backend(void *be_handle)); \
rig_model_t MAKE_VERSIONED_FN(PREFIX_PROBEAMPS, \
ABI_VERSION, \
backend(hamlib_port_t *port, \
rig_probe_func_t cfunc, \
rig_ptr_t data))
#define AMP_FUNCNAMA(backend) MAKE_VERSIONED_FN(PREFIX_INITAMPS, ABI_VERSION, backend)
#define AMP_FUNCNAMB(backend) MAKE_VERSIONED_FN(PREFIX_PROBEAMPS, ABI_VERSION, backend)
#define AMP_FUNCNAM(backend) AMP_FUNCNAMA(backend),AMP_FUNCNAMB(backend)
DEFINE_INITAMP_BACKEND(dummy);
DEFINE_INITAMP_BACKEND(kpa1500);
/**
* \def AMP_BACKEND_LIST
* \brief Static list of amplifier models.
*
* This is a NULL terminated list of available amplifier backends. Each entry
* in the list consists of two fields: The branch number, which is an integer,
* and the branch name, which is a character string.
* An external library, loaded dynamically, could add its own functions
* pointers in this array.
*/
static struct
{
int be_num;
const char *be_name;
int (*be_init)(void *);
amp_model_t (*be_probe)(hamlib_port_t *);
} amp_backend_list[AMP_BACKEND_MAX] =
{
{ AMP_DUMMY, AMP_BACKEND_DUMMY, AMP_FUNCNAMA(dummy) },
{ AMP_ELECRAFT, AMP_BACKEND_ELECRAFT, AMP_FUNCNAMA(kpa1500) },
{ 0, NULL }, /* end */
};
// Apparently, no amplifier can be probed.
/*
* AMP_BACKEND_LIST is here, please keep it up to date,
* i.e. each time you implement a new backend.
*/
/*
* This struct to keep track of known amp models.
* It is chained, and used in a hash table, see below.
*/
struct amp_list
{
const struct amp_caps *caps;
struct amp_list *next;
};
#define AMPLSTHASHSZ 16
#define HASH_FUNC(a) ((a)%AMPLSTHASHSZ)
/*
* The amp_hash_table is a hash table pointing to a list of next==NULL
* terminated caps.
*/
static struct amp_list *amp_hash_table[AMPLSTHASHSZ] = { NULL, };
static int amp_lookup_backend(amp_model_t amp_model);
/*
* Basically, this is a hash insert function that doesn't check for dup!
*/
int HAMLIB_API amp_register(const struct amp_caps *caps)
{
int hval;
struct amp_list *p;
if (!caps)
{
return -RIG_EINVAL;
}
amp_debug(RIG_DEBUG_VERBOSE, "amp_register (%d)\n", caps->amp_model);
#ifndef DONT_WANT_DUP_CHECK
if (amp_get_caps(caps->amp_model) != NULL)
{
return -RIG_EINVAL;
}
#endif
p = (struct amp_list *)malloc(sizeof(struct amp_list));
if (!p)
{
return -RIG_ENOMEM;
}
hval = HASH_FUNC(caps->amp_model);
p->caps = caps;
// p->handle = NULL;
p->next = amp_hash_table[hval];
amp_hash_table[hval] = p;
return RIG_OK;
}
/*
* Get amp capabilities.
* i.e. amp_hash_table lookup
*/
const struct amp_caps *HAMLIB_API amp_get_caps(amp_model_t amp_model)
{
struct amp_list *p;
for (p = amp_hash_table[HASH_FUNC(amp_model)]; p; p = p->next)
{
if (p->caps->amp_model == amp_model)
{
return p->caps;
}
}
return NULL; /* sorry, caps not registered! */
}
/*
* lookup for backend index in amp_backend_list table,
* according to BACKEND_NUM
* return -1 if not found.
*/
static int amp_lookup_backend(amp_model_t amp_model)
{
int i;
for (i = 0; i < AMP_BACKEND_MAX && amp_backend_list[i].be_name; i++)
{
if (AMP_BACKEND_NUM(amp_model) ==
amp_backend_list[i].be_num)
{
return i;
}
}
return -1;
}
/*
* amp_check_backend
* check the backend declaring this model has been loaded
* and if not loaded already, load it!
* This permits seamless operation in amp_init.
*/
int HAMLIB_API amp_check_backend(amp_model_t amp_model)
{
const struct amp_caps *caps;
int be_idx;
int retval;
/* already loaded ? */
caps = amp_get_caps(amp_model);
if (caps)
{
return RIG_OK;
}
be_idx = amp_lookup_backend(amp_model);
/*
* Never heard about this backend family!
*/
if (be_idx == -1)
{
amp_debug(RIG_DEBUG_VERBOSE,
"%s: unsupported backend %d for model %d\n",
__func__,
AMP_BACKEND_NUM(amp_model),
amp_model);
return -RIG_ENAVAIL;
}
retval = amp_load_backend(amp_backend_list[be_idx].be_name);
return retval;
}
int HAMLIB_API amp_unregister(amp_model_t amp_model)
{
int hval;
struct amp_list *p, *q;
hval = HASH_FUNC(amp_model);
q = NULL;
for (p = amp_hash_table[hval]; p; p = p->next)
{
if (p->caps->amp_model == amp_model)
{
if (q == NULL)
{
amp_hash_table[hval] = p->next;
}
else
{
q->next = p->next;
}
free(p);
return RIG_OK;
}
q = p;
}
return -RIG_EINVAL; /* sorry, caps not registered! */
}
/*
* amp_list_foreach
* executes cfunc on all the elements stored in the amp hash list
*/
int HAMLIB_API amp_list_foreach(int (*cfunc)(const struct amp_caps *,
rig_ptr_t),
rig_ptr_t data)
{
struct amp_list *p;
int i;
if (!cfunc)
{
return -RIG_EINVAL;
}
for (i = 0; i < AMPLSTHASHSZ; i++)
{
for (p = amp_hash_table[i]; p; p = p->next)
if ((*cfunc)(p->caps, data) == 0)
{
return RIG_OK;
}
}
return RIG_OK;
}
/*
* amp_probe_all
* called straight by amp_probe
*/
amp_model_t HAMLIB_API amp_probe_all(hamlib_port_t *p)
{
int i;
amp_model_t amp_model;
for (i = 0; i < AMP_BACKEND_MAX && amp_backend_list[i].be_name; i++)
{
if (amp_backend_list[i].be_probe)
{
amp_model = (*amp_backend_list[i].be_probe)(p);
if (amp_model != AMP_MODEL_NONE)
{
return amp_model;
}
}
}
return AMP_MODEL_NONE;
}
int amp_load_all_backends()
{
int i;
for (i = 0; i < AMP_BACKEND_MAX && amp_backend_list[i].be_name; i++)
{
amp_load_backend(amp_backend_list[i].be_name);
}
return RIG_OK;
}
/*
* amp_load_backend
* Dynamically load a amp backend through dlopen mechanism
*/
int HAMLIB_API amp_load_backend(const char *be_name)
{
int status;
int (*be_init)(rig_ptr_t);
int i;
for (i = 0; i < AMP_BACKEND_MAX && amp_backend_list[i].be_name; i++)
{
if (!strcmp(be_name, amp_backend_list[i].be_name))
{
be_init = amp_backend_list[i].be_init;
if (be_init == NULL)
{
printf("Null\n");
return -EINVAL;
}
status = (*be_init)(NULL);
return status;
}
}
return -EINVAL;
}

708
src/amplifier.c 100644
Wyświetl plik

@ -0,0 +1,708 @@
/*
* Hamlib Interface - main file
* Copyright (c) 2000-2012 by Stephane Fillod
* Copyright (c) 2000-2003 by Frank Singleton
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/**
* \addtogroup amplifier
* @{
*/
/**
* \file src/amplifier.c
* \brief Amplifier interface
* \author Stephane Fillod
* \date 2000-2012
*
* Hamlib interface is a frontend implementing amplifier wrapper functions.
*/
/**
* \page amp Amplifier interface
*
* Amplifier can be any kind of azimuth or azimuth and elevation controlled
* antenna system.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <hamlib/amplifier.h>
#include "serial.h"
#include "parallel.h"
#include "usb_port.h"
#include "network.h"
#include "amp_conf.h"
#include "token.h"
#define CHECK_AMP_ARG(r) (!(r) || !(r)->caps || !(r)->state.comm_state)
/*
* Data structure to track the opened amp (by amp_open)
*/
struct opened_amp_l
{
AMP *amp;
struct opened_amp_l *next;
};
static struct opened_amp_l *opened_amp_list = { NULL };
/*
* track which amp is opened (with amp_open)
* needed at least for transceive mode
*/
static int add_opened_amp(AMP *amp)
{
struct opened_amp_l *p;
p = (struct opened_amp_l *)malloc(sizeof(struct opened_amp_l));
if (!p)
{
return -RIG_ENOMEM;
}
p->amp = amp;
p->next = opened_amp_list;
opened_amp_list = p;
return RIG_OK;
}
static int remove_opened_amp(AMP *amp)
{
struct opened_amp_l *p, *q;
q = NULL;
for (p = opened_amp_list; p; p = p->next)
{
if (p->amp == amp)
{
if (q == NULL)
{
opened_amp_list = opened_amp_list->next;
}
else
{
q->next = p->next;
}
free(p);
return RIG_OK;
}
q = p;
}
return -RIG_EINVAL; /* Not found in list ! */
}
/**
* \brief execs cfunc() on each opened amp
* \param cfunc The function to be executed on each amp
* \param data Data pointer to be passed to cfunc()
*
* Calls cfunc() function for each opened amp. The contents of the opened
* amp table is processed in random order according to a function pointed to
* by \a cfunc, whic is called with two arguments, the first pointing to the
* #AMP handle, the second to a data pointer \a data.
*
* If \a data is not needed, then it can be set to NULL. The processing of
* the opened amp table is stopped when cfunc() returns 0.
* \internal
*
* \return always RIG_OK.
*/
int foreach_opened_amp(int (*cfunc)(AMP *, rig_ptr_t), rig_ptr_t data)
{
struct opened_amp_l *p;
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
for (p = opened_amp_list; p; p = p->next)
{
if ((*cfunc)(p->amp, data) == 0)
{
return RIG_OK;
}
}
return RIG_OK;
}
/**
* \brief allocate a new #AMP handle
* \param amp_model The amp model for this new handle
*
* Allocates a new #AMP handle and initializes the associated data
* for \a amp_model.
*
* \return a pointer to the #AMP handle otherwise NULL if memory allocation
* failed or \a amp_model is unknown (e.g. backend autoload failed).
*
* \sa amp_cleanup(), amp_open()
*/
AMP *HAMLIB_API amp_init(amp_model_t amp_model)
{
AMP *amp;
const struct amp_caps *caps;
struct amp_state *rs;
int retcode;
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
amp_check_backend(amp_model);
caps = amp_get_caps(amp_model);
if (!caps)
{
return NULL;
}
/*
* okay, we've found it. Allocate some memory and set it to zeros,
* and especially the initialize the callbacks
*/
amp = calloc(1, sizeof(AMP));
if (amp == NULL)
{
/*
* FIXME: how can the caller know it's a memory shortage,
* and not "amp not found" ?
*/
return NULL;
}
/* caps is const, so we need to tell compiler
that we know what we are doing */
amp->caps = (struct amp_caps *) caps;
/*
* populate the amp->state
* TODO: read the Preferences here!
*/
rs = &amp->state;
rs->comm_state = 0;
rs->ampport.type.rig = caps->port_type; /* default from caps */
rs->ampport.write_delay = caps->write_delay;
rs->ampport.post_write_delay = caps->post_write_delay;
rs->ampport.timeout = caps->timeout;
rs->ampport.retry = caps->retry;
rs->has_get_level = caps->has_get_level;
switch (caps->port_type)
{
case RIG_PORT_SERIAL:
// Dont' think we need a default port here
//strncpy(rs->ampport.pathname, DEFAULT_SERIAL_PORT, FILPATHLEN - 1);
rs->ampport.parm.serial.rate = caps->serial_rate_max; /* fastest ! */
rs->ampport.parm.serial.data_bits = caps->serial_data_bits;
rs->ampport.parm.serial.stop_bits = caps->serial_stop_bits;
rs->ampport.parm.serial.parity = caps->serial_parity;
rs->ampport.parm.serial.handshake = caps->serial_handshake;
break;
case RIG_PORT_NETWORK:
case RIG_PORT_UDP_NETWORK:
strncpy(rs->ampport.pathname, "127.0.0.1:4534", FILPATHLEN - 1);
break;
default:
strncpy(rs->ampport.pathname, "", FILPATHLEN - 1);
}
rs->ampport.fd = -1;
/*
* let the backend a chance to setup his private data
* This must be done only once defaults are setup,
* so the backend init can override amp_state.
*/
if (caps->amp_init != NULL)
{
retcode = caps->amp_init(amp);
if (retcode != RIG_OK)
{
amp_debug(RIG_DEBUG_VERBOSE,
"%s: backend_init failed!\n",
__func__);
/* cleanup and exit */
free(amp);
return NULL;
}
}
return amp;
}
/**
* \brief open the communication to the amp
* \param amp The #AMP handle of the amplifier to be opened
*
* Opens communication to a amplifier which \a AMP handle has been passed
* by argument.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \retval RIG_EINVAL \a amp is NULL or unconsistent.
* \retval RIG_ENIMPL port type communication is not implemented yet.
*
* \sa amp_init(), amp_close()
*/
int HAMLIB_API amp_open(AMP *amp)
{
const struct amp_caps *caps;
struct amp_state *rs;
int status;
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp || !amp->caps)
{
return -RIG_EINVAL;
}
caps = amp->caps;
rs = &amp->state;
if (rs->comm_state)
{
return -RIG_EINVAL;
}
rs->ampport.fd = -1;
switch (rs->ampport.type.rig)
{
case RIG_PORT_SERIAL:
status = serial_open(&rs->ampport);
if (status != 0)
{
return status;
}
break;
case RIG_PORT_PARALLEL:
status = par_open(&rs->ampport);
if (status < 0)
{
return status;
}
break;
case RIG_PORT_DEVICE:
status = open(rs->ampport.pathname, O_RDWR, 0);
if (status < 0)
{
return -RIG_EIO;
}
rs->ampport.fd = status;
break;
case RIG_PORT_USB:
status = usb_port_open(&rs->ampport);
if (status < 0)
{
return status;
}
break;
case RIG_PORT_NONE:
case RIG_PORT_RPC:
break; /* ez :) */
case RIG_PORT_NETWORK:
case RIG_PORT_UDP_NETWORK:
/* FIXME: default port */
status = network_open(&rs->ampport, 4533);
if (status < 0)
{
return status;
}
break;
default:
return -RIG_EINVAL;
}
add_opened_amp(amp);
rs->comm_state = 1;
/*
* Maybe the backend has something to initialize
* In case of failure, just close down and report error code.
*/
if (caps->amp_open != NULL)
{
status = caps->amp_open(amp);
if (status != RIG_OK)
{
return status;
}
}
return RIG_OK;
}
/**
* \brief close the communication to the amp
* \param amp The #AMP handle of the amplifier to be closed
*
* Closes communication to a amplifier which \a AMP handle has been passed
* by argument that was previously open with amp_open().
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa amp_cleanup(), amp_open()
*/
int HAMLIB_API amp_close(AMP *amp)
{
const struct amp_caps *caps;
struct amp_state *rs;
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp || !amp->caps)
{
return -RIG_EINVAL;
}
caps = amp->caps;
rs = &amp->state;
if (!rs->comm_state)
{
return -RIG_EINVAL;
}
/*
* Let the backend say 73s to the amp.
* and ignore the return code.
*/
if (caps->amp_close)
{
caps->amp_close(amp);
}
if (rs->ampport.fd != -1)
{
switch (rs->ampport.type.rig)
{
case RIG_PORT_SERIAL:
ser_close(&rs->ampport);
break;
case RIG_PORT_PARALLEL:
par_close(&rs->ampport);
break;
case RIG_PORT_USB:
usb_port_close(&rs->ampport);
break;
case RIG_PORT_NETWORK:
case RIG_PORT_UDP_NETWORK:
network_close(&rs->ampport);
break;
default:
close(rs->ampport.fd);
}
rs->ampport.fd = -1;
}
remove_opened_amp(amp);
rs->comm_state = 0;
return RIG_OK;
}
/**
* \brief release a amp handle and free associated memory
* \param amp The #AMP handle of the radio to be closed
*
* Releases a amp struct which port has eventualy been closed already
* with amp_close().
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa amp_init(), amp_close()
*/
int HAMLIB_API amp_cleanup(AMP *amp)
{
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp || !amp->caps)
{
return -RIG_EINVAL;
}
/*
* check if they forgot to close the amp
*/
if (amp->state.comm_state)
{
amp_close(amp);
}
/*
* basically free up the priv struct
*/
if (amp->caps->amp_cleanup)
{
amp->caps->amp_cleanup(amp);
}
free(amp);
return RIG_OK;
}
/**
* \brief reset the amplifier
* \param amp The amp handle
* \param reset The reset operation to perform
*
* Resets the amplifier.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
*/
int HAMLIB_API amp_reset(AMP *amp, amp_reset_t reset)
{
const struct amp_caps *caps;
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (CHECK_AMP_ARG(amp))
{
return -RIG_EINVAL;
}
caps = amp->caps;
if (caps->reset == NULL)
{
return -RIG_ENAVAIL;
}
return caps->reset(amp, reset);
}
int HAMLIB_API amp_get_freq(AMP *amp, freq_t *freq)
{
const struct amp_caps *caps;
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (CHECK_AMP_ARG(amp))
{
return -RIG_EINVAL;
}
caps = amp->caps;
if (caps->get_freq == NULL)
{
return -RIG_ENAVAIL;
}
return caps->get_freq(amp, freq);
}
int HAMLIB_API amp_set_freq(AMP *amp, freq_t freq)
{
const struct amp_caps *caps;
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (CHECK_AMP_ARG(amp))
{
return -RIG_EINVAL;
}
caps = amp->caps;
if (caps->set_freq == NULL)
{
return -RIG_ENAVAIL;
}
return caps->set_freq(amp, freq);
}
/**
* \brief get general information from the amplifier
* \param amp The amp handle
*
* Retrieves some general information from the amplifier.
* This can include firmware revision, exact model name, or just nothing.
*
* \return a pointer to static memory containing the ASCIIZ string
* if the operation has been sucessful, otherwise NULL if an error occured
* or get_info not part of capabilities.
*/
const char *HAMLIB_API amp_get_info(AMP *amp)
{
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (CHECK_AMP_ARG(amp))
{
return NULL;
}
if (amp->caps->get_info == NULL)
{
return NULL;
}
return amp->caps->get_info(amp);
}
int HAMLIB_API amp_get_level(AMP *amp, setting_t level, value_t *val)
{
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (CHECK_AMP_ARG(amp))
{
return -RIG_EINVAL;
}
if (amp->caps->get_level == NULL)
{
return -RIG_ENIMPL;
}
return amp->caps->get_level(amp, level, val);
}
int HAMLIB_API amp_get_ext_level(AMP *amp, token_t level, value_t *val)
{
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (CHECK_AMP_ARG(amp))
{
return -RIG_EINVAL;
}
if (amp->caps->get_ext_level == NULL)
{
return -RIG_ENIMPL;
}
return amp->caps->get_ext_level(amp, level, val);
}
/**
* \brief turn on/off the amplifier or standby/operate toggle
* \param amp The amp handle
* \param status The status to set to
*
* turns on/off the amplifier.
* See #RIG_POWER_ON, #RIG_POWER_OFF and #RIG_POWER_STANDBY #RIG_POWER_OPERATE defines
* for the \a status.
*
* \return RIG_OK if the operation has been sucessful, ortherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa amp_get_powerstat()
*/
int HAMLIB_API amp_set_powerstat(AMP *amp, powerstat_t status)
{
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (CHECK_AMP_ARG(amp))
{
return -RIG_EINVAL;
}
if (amp->caps->set_powerstat == NULL)
{
return -RIG_ENIMPL;
}
return amp->caps->set_powerstat(amp, status);
}
int HAMLIB_API amp_get_powerstat(AMP *amp, powerstat_t *status)
{
amp_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (CHECK_AMP_ARG(amp))
{
return -RIG_EINVAL;
}
if (amp->caps->get_powerstat == NULL)
{
return -RIG_ENIMPL;
}
return amp->caps->get_powerstat(amp, status);
}
/*! @} */

Wyświetl plik

@ -182,7 +182,6 @@ const struct confparams *HAMLIB_API rig_ext_lookup(RIG *rig, const char *name)
return NULL;
}
/**
* \param rig
* \param token

249
src/extamp.c 100644
Wyświetl plik

@ -0,0 +1,249 @@
/*
* Hamlib Interface - extra parameter interface for amplifiers
* Copyright (c) 2000-2008 by Stephane Fillod
* Derived from ext.c
* Copyright (c) 2019 by Michael Black W9MDB
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/**
* \addtogroup amp
* @{
*/
/**
* \file ext.c
* \brief Extension request parameter interface
*
* An open-ended set of extension parameters and levels are available for each
* amp, as provided in the ampcaps extparms and extlevels lists. These
* provide a way to work with amp-specific functions that don't fit into the
* basic "virtual amp" of Hamlib. See amplifiers/kpa.c for an example.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <hamlib/amplifier.h>
#include "token.h"
/**
* \param amp The amp handle
* \param cfunc callback function of each extlevel
* \param data cookie to be passed to \a cfunc callback
* \brief Executes cfunc on all the elements stored in the extlevels table
*
* The callback \a cfunc is called until it returns a value which is not
* strictly positive. A zero value means a normal end of iteration, and a
* negative value an abnormal end, which will be the return value of
* amp_ext_level_foreach.
*/
int HAMLIB_API amp_ext_level_foreach(AMP *amp,
int (*cfunc)(AMP *,
const struct confparams *,
amp_ptr_t),
amp_ptr_t data)
{
const struct confparams *cfp;
int ret;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp || !amp->caps || !cfunc)
{
return -RIG_EINVAL;
}
for (cfp = amp->caps->extlevels; cfp && cfp->name; cfp++)
{
ret = (*cfunc)(amp, cfp, data);
if (ret == 0)
{
return RIG_OK;
}
if (ret < 0)
{
return ret;
}
}
return RIG_OK;
}
/**
* \param amp The amp handle
* \param cfunc callback function of each extparm
* \param data cookie to be passed to \a cfunc callback
* \brief Executes cfunc on all the elements stored in the extparms table
*
* The callback \a cfunc is called until it returns a value which is not
* strictly positive. A zero value means a normal end of iteration, and a
* negative value an abnormal end, which will be the return value of
* amp_ext_parm_foreach.
*/
int HAMLIB_API amp_ext_parm_foreach(AMP *amp,
int (*cfunc)(AMP *,
const struct confparams *,
amp_ptr_t),
amp_ptr_t data)
{
const struct confparams *cfp;
int ret;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp || !amp->caps || !cfunc)
{
return -RIG_EINVAL;
}
for (cfp = amp->caps->extparms; cfp && cfp->name; cfp++)
{
ret = (*cfunc)(amp, cfp, data);
if (ret == 0)
{
return RIG_OK;
}
if (ret < 0)
{
return ret;
}
}
return RIG_OK;
}
/**
* \param amp
* \param name
* \brief lookup ext token by its name, return pointer to confparams struct.
*
* Lookup extlevels table first, then fall back to extparms.
*
* Returns NULL if nothing found
*
* TODO: should use Lex to speed it up, strcmp hurts!
*/
const struct confparams *HAMLIB_API amp_ext_lookup(AMP *amp, const char *name)
{
const struct confparams *cfp;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp || !amp->caps)
{
return NULL;
}
for (cfp = amp->caps->extlevels; cfp && cfp->name; cfp++)
{
if (!strcmp(cfp->name, name))
{
return cfp;
}
}
for (cfp = amp->caps->extparms; cfp && cfp->name; cfp++)
{
if (!strcmp(cfp->name, name))
{
return cfp;
}
}
return NULL;
}
/**
* \param amp
* \param token
* \brief lookup ext token, return pointer to confparams struct.
*
* lookup extlevels table first, then fall back to extparms.
*
* Returns NULL if nothing found
*/
const struct confparams * HAMLIB_API amp_ext_lookup_tok(AMP *amp, token_t token)
{
const struct confparams *cfp;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp || !amp->caps)
{
return NULL;
}
for (cfp = amp->caps->extlevels; cfp && cfp->token; cfp++)
{
if (cfp->token == token)
{
return cfp;
}
}
for (cfp = amp->caps->extparms; cfp && cfp->token; cfp++)
{
if (cfp->token == token)
{
return cfp;
}
}
return NULL;
}
/**
* \param amp
* \param name
* \brief Simple lookup returning token id assicated with name
*/
token_t HAMLIB_API amp_ext_token_lookup(AMP *amp, const char *name)
{
const struct confparams *cfp;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
cfp = amp_ext_lookup(amp, name);
if (!cfp)
{
return RIG_CONF_END;
}
return cfp->token;
}
/** @} */

Wyświetl plik

@ -51,6 +51,7 @@
#include <unistd.h>
#include <hamlib/rig.h>
#include <hamlib/amplifier.h>
#include "misc.h"
@ -628,6 +629,23 @@ static struct
{ RIG_LEVEL_NONE, "" },
};
static struct
{
setting_t level;
const char *str;
} levelamp_str[] =
{
{ AMP_LEVEL_SWR, "SWR" },
{ AMP_LEVEL_NH, "NH" },
{ AMP_LEVEL_PF, "PF" },
{ AMP_LEVEL_PWR_INPUT, "PWRINPUT" },
{ AMP_LEVEL_PWR_FWD, "PWRFORWARD" },
{ AMP_LEVEL_PWR_REFLECTED, "PWRREFLECTED" },
{ AMP_LEVEL_PWR_PEAK, "PWRPEAK" },
{ AMP_LEVEL_FAULT, "FAULT" },
{ AMP_LEVEL_NONE, "" },
};
/**
* \brief Convert alpha string to enum RIG_LEVEL_...
@ -653,6 +671,32 @@ setting_t HAMLIB_API rig_parse_level(const char *s)
return RIG_LEVEL_NONE;
}
/**
* \brief Convert alpha string to enum AMP_LEVEL_...
* \param s input alpha string
* \return AMP_LEVEL_...
*
* \sa amp_level_e()
*/
setting_t HAMLIB_API amp_parse_level(const char *s)
{
int i;
rig_debug(RIG_DEBUG_VERBOSE, "%s called level=%s\n", __func__, s);
rig_debug(RIG_DEBUG_VERBOSE, "%s called str=%s\n", __func__, levelamp_str[0].str);
for (i = 0 ; levelamp_str[i].str[0] != '\0'; i++)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called checking=%s\n", __func__, levelamp_str[i].str);
if (!strcmp(s, levelamp_str[i].str))
{
return levelamp_str[i].level;
}
}
return RIG_LEVEL_NONE;
}
/**
* \brief Convert enum RIG_LEVEL_... to alpha string
@ -683,6 +727,35 @@ const char * HAMLIB_API rig_strlevel(setting_t level)
return "";
}
/**
* \brief Convert enum AMP_LEVEL_... to alpha string
* \param level AMP_LEVEL_...
* \return alpha string
*
* \sa amp_level_e()
*/
const char * HAMLIB_API amp_strlevel(setting_t level)
{
int i;
//rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (level == AMP_LEVEL_NONE)
{
return "";
}
for (i = 0; levelamp_str[i].str[0] != '\0'; i++)
{
if (level == levelamp_str[i].level)
{
return levelamp_str[i].str;
}
}
return "";
}
static struct
{

Wyświetl plik

@ -24,6 +24,7 @@
#include <hamlib/rig.h>
#include <hamlib/rotator.h>
#include <hamlib/amplifier.h>
#ifdef __cplusplus
#define EXTERN_C extern "C"
@ -69,4 +70,19 @@
rig_probe_func_t cfunc, \
rig_ptr_t data))
#define PREFIX_INITAMPS initamps
#define PREFIX_PROBEAMPS probeallamps
#define DECLARE_INITAMP_BACKEND(backend) \
EXTERN_C BACKEND_EXPORT(int) \
MAKE_VERSIONED_FN(PREFIX_INITAMPS, ABI_VERSION, backend(void *be_handle))
#define DECLARE_PROBEAMP_BACKEND(backend) \
EXTERN_C BACKEND_EXPORT(amp_model_t) \
MAKE_VERSIONED_FN(PREFIX_PROBEAMPS, \
ABI_VERSION, \
backend(hamlib_port_t *port, \
rig_probe_func_t cfunc, \
rig_ptr_t data))
#endif /* _REGISTER_H */

Wyświetl plik

@ -1962,10 +1962,10 @@ int HAMLIB_API rig_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt)
return par_ptt_get(&rig->state.pttport, ptt);
case RIG_PTT_CM108:
if (caps->get_ptt)
{
return caps->get_ptt(rig, vfo, ptt);
}
//if (caps->get_ptt)
//{
// return caps->get_ptt(rig, vfo, ptt);
//}
return cm108_ptt_get(&rig->state.pttport, ptt);

Wyświetl plik

@ -46,6 +46,7 @@
#include <fcntl.h>
#include <hamlib/rig.h>
#include <hamlib/amplifier.h>
#include "cal.h"
@ -310,6 +311,35 @@ setting_t HAMLIB_API rig_has_get_level(RIG *rig, setting_t level)
}
/**
* \brief check retrieval ability of level settings
* \param amp The amp handle
* \param level The level settings
*
* Checks if an amp is capable of *getting* a level setting.
* Since the \a level is an OR'ed bitwise argument, more than
* one level can be checked at the same time.
*
* EXAMPLE: if (amp_has_get_level(my_amp, AMP_LVL_SWR)) disp_SWR();
*
* \return a bit map of supported level settings that can be retrieved,
* otherwise 0 if none supported.
*
* \sa amp_has_set_level(), amp_get_level()
*/
setting_t HAMLIB_API amp_has_get_level(AMP *amp, setting_t level)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!amp || !amp->caps)
{
return 0;
}
return (amp->state.has_get_level & level);
}
/**
* \brief check settable ability of level settings
* \param rig The rig handle

Wyświetl plik

@ -6,18 +6,21 @@
DISTCLEANFILES = rigctl.log rigctl.sum testbcd.log testbcd.sum
bin_PROGRAMS = rigctl rigctld rigmem rigsmtr rigswr rotctl rotctld rigctlcom
bin_PROGRAMS = rigctl rigctld rigmem rigsmtr rigswr rotctl rotctld rigctlcom ampctl ampctld
check_PROGRAMS = dumpmem testrig testtrn testbcd testfreq listrigs testloc rig_bench
RIGCOMMONSRC = rigctl_parse.c rigctl_parse.h dumpcaps.c sprintflst.c sprintflst.h uthash.h
ROTCOMMONSRC = rotctl_parse.c rotctl_parse.h dumpcaps_rot.c uthash.h
AMPCOMMONSRC = ampctl_parse.c ampctl_parse.h dumpcaps_amp.c sprintflst.c sprintflst.h uthash.h
rigctl_SOURCES = rigctl.c $(RIGCOMMONSRC)
rigctld_SOURCES = rigctld.c $(RIGCOMMONSRC)
rigctlcom_SOURCES = rigctlcom.c $(RIGCOMMONSRC)
rotctl_SOURCES = rotctl.c $(ROTCOMMONSRC)
rotctld_SOURCES = rotctld.c $(ROTCOMMONSRC)
ampctl_SOURCES = ampctl.c $(AMPCOMMONSRC)
ampctld_SOURCES = ampctld.c $(AMPCOMMONSRC)
rigswr_SOURCES = rigswr.c
rigsmtr_SOURCES = rigsmtr.c
rigmem_SOURCES = rigmem.c memsave.c memload.c memcsv.c sprintflst.c sprintflst.h
@ -29,12 +32,15 @@ LDADD = $(top_builddir)/src/libhamlib.la $(top_builddir)/lib/libmisc.la
rigmem_CFLAGS = $(AM_CFLAGS) $(LIBXML2_CFLAGS)
rigctld_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS)
rotctld_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS)
ampctld_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS)
rigctlcom_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS)
rigctl_LDADD = $(PTHREAD_LIBS) $(LDADD) $(READLINE_LIBS)
rigctld_LDADD = $(NET_LIBS) $(PTHREAD_LIBS) $(LDADD) $(READLINE_LIBS)
rotctl_LDADD = $(PTHREAD_LIBS) $(LDADD) $(READLINE_LIBS)
rotctld_LDADD = $(NET_LIBS) $(PTHREAD_LIBS) $(LDADD) $(READLINE_LIBS)
ampctl_LDADD = $(PTHREAD_LIBS) $(LDADD) $(READLINE_LIBS)
ampctld_LDADD = $(NET_LIBS) $(PTHREAD_LIBS) $(LDADD) $(READLINE_LIBS)
rigmem_LDADD = $(LIBXML2_LIBS) $(LDADD)
rigctlcom_LDADD = $(NET_LIBS) $(PTHREAD_LIBS) $(LDADD) $(READLINE_LIBS)
@ -44,8 +50,10 @@ rigswr_LDFLAGS = $(WINEXELDFLAGS)
rigsmtr_LDFLAGS = $(WINEXELDFLAGS)
rigmem_LDFLAGS = $(WINEXELDFLAGS)
rotctl_LDFLAGS = $(WINEXELDFLAGS)
ampctl_LDFLAGS = $(WINEXELDFLAGS)
rigctld_LDFLAGS = $(WINEXELDFLAGS)
rotctld_LDFLAGS = $(WINEXELDFLAGS)
ampctld_LDFLAGS = $(WINEXELDFLAGS)
rigctlcom_LDFLAGS = $(WINEXELDFLAGS)

479
tests/ampctl.c 100644
Wyświetl plik

@ -0,0 +1,479 @@
/*
* ampctl.c - (C) Stephane Fillod 2000-2010
* (C) Nate Bargmann 2003,2007,2010,2011,2012,2013
* (C) The Hamlib Group 2002,2006
* (C) Derived from rotctl.c Michael Black W9MDB 2019
*
* This program tests/controls an amplifier using Hamlib.
* It takes commands in interactive mode as well as
* from command line options.
*
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#ifdef HAVE_LIBREADLINE
# if defined(HAVE_READLINE_READLINE_H)
# include <readline/readline.h>
# elif defined(HAVE_READLINE_H) /* !defined(HAVE_READLINE_READLINE_H) */
# include <readline.h>
# else /* !defined(HAVE_READLINE_H) */
extern char *readline();
# endif /* HAVE_READLINE_H */
#else
/* no readline */
#endif /* HAVE_LIBREADLINE */
#ifdef HAVE_READLINE_HISTORY
# include <sys/stat.h>
# define HST_SHRT_OPTS "iI"
# if defined(HAVE_READLINE_HISTORY_H)
# include <readline/history.h>
# elif defined(HAVE_HISTORY_H)
# include <history.h>
# else /* !defined(HAVE_HISTORY_H) */
extern void add_history();
extern int write_history();
extern int read_history();
# endif /* defined(HAVE_READLINE_HISTORY_H) */
#else
/* no history */
# define HST_SHRT_OPTS ""
#endif /* HAVE_READLINE_HISTORY */
#include <hamlib/amplifier.h>
#include "misc.h"
#include "ampctl_parse.h"
/*
* Prototypes
*/
void usage();
/*
* 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.
* TODO: add an option to read from a file
*/
#define SHORT_OPTIONS "+m:r:s:C:t:LvhVluZ"
static struct option long_options[] =
{
{"model", 1, 0, 'm'},
{"amp-file", 1, 0, 'r'},
{"serial-speed", 1, 0, 's'},
{"send-cmd-term", 1, 0, 't'},
{"list", 0, 0, 'l'},
{"set-conf", 1, 0, 'C'},
{"show-conf", 0, 0, 'L'},
{"dump-caps", 0, 0, 'u'},
{"debug-time-stamps", 0, 0, 'Z'},
#ifdef HAVE_READLINE_HISTORY
{"read-history", 0, 0, 'i'},
{"save-history", 0, 0, 'I'},
#endif
{"verbose", 0, 0, 'v'},
{"help", 0, 0, 'h'},
{"version", 0, 0, 'V'},
{0, 0, 0, 0}
};
#define MAXCONFLEN 128
/* variable for readline support */
#ifdef HAVE_LIBREADLINE
static const int have_rl = 1;
#endif
int interactive = 1; /* if no cmd on command line, switch to interactive */
int prompt = 1; /* Print prompt in ampctl */
char send_cmd_term = '\r'; /* send_cmd termination char */
int main(int argc, char *argv[])
{
AMP *my_amp; /* handle to amp (instance) */
amp_model_t my_model = AMP_MODEL_DUMMY;
int retcode; /* generic return code from functions */
int exitcode;
int verbose = 0;
int show_conf = 0;
int dump_caps_opt = 0;
#ifdef HAVE_READLINE_HISTORY
int rd_hist = 0;
int sv_hist = 0;
const char *hist_dir = NULL;
const char hist_file[] = "/.ampctl_history";
char *hist_path = NULL;
struct stat hist_dir_stat;
#endif /* HAVE_READLINE_HISTORY */
const char *amp_file = NULL;
int serial_rate = 0;
char conf_parms[MAXCONFLEN] = "";
while (1)
{
int c;
int option_index = 0;
c = getopt_long(argc,
argv,
SHORT_OPTIONS HST_SHRT_OPTS,
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);
}
amp_file = 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 't':
if (!optarg)
{
usage(); /* wrong arg count */
exit(1);
}
if (strlen(optarg) > 1)
{
send_cmd_term = strtol(optarg, NULL, 0);
}
else
{
send_cmd_term = optarg[0];
}
break;
#ifdef HAVE_READLINE_HISTORY
case 'i':
rd_hist++;
break;
case 'I':
sv_hist++;
break;
#endif /* HAVE_READLINE_HISTORY */
case 'v':
verbose++;
break;
case 'L':
show_conf++;
break;
case 'l':
rig_set_debug(0);
list_models();
exit(0);
case 'u':
dump_caps_opt++;
break;
case 'Z':
rig_set_debug_time_stamp(1);
break;
default:
usage(); /* unknown option? */
exit(1);
}
}
rig_set_debug(verbose);
rig_debug(RIG_DEBUG_VERBOSE, "ampctl, %s\n", hamlib_version);
rig_debug(RIG_DEBUG_VERBOSE,
"Report bugs to <hamlib-developer@lists.sourceforge.net>\n\n");
/*
* at least one command on command line,
* disable interactive mode
*/
if (optind < argc)
{
interactive = 0;
}
my_amp = amp_init(my_model);
if (!my_amp)
{
fprintf(stderr,
"Unknown amp num %d, or initialization error.\n",
my_model);
fprintf(stderr, "Please check with --list option.\n");
exit(2);
}
retcode = set_conf(my_amp, conf_parms);
if (retcode != RIG_OK)
{
fprintf(stderr, "Config parameter error: %s\n", rigerror(retcode));
exit(2);
}
if (amp_file)
{
strncpy(my_amp->state.ampport.pathname, amp_file, FILPATHLEN - 1);
}
/* FIXME: bound checking and port type == serial */
if (serial_rate != 0)
{
my_amp->state.ampport.parm.serial.rate = serial_rate;
}
#if 0
/*
* print out conf parameters
*/
if (show_conf)
{
amp_token_foreach(my_amp, print_conf_list, (rig_ptr_t)my_amp);
}
#endif
/*
* Print out capabilities, and exits immediately as we may be interested
* only in caps, and rig_open may fail.
*/
if (dump_caps_opt)
{
dumpcaps_amp(my_amp, stdout);
amp_cleanup(my_amp); /* if you care about memory */
exit(0);
}
retcode = amp_open(my_amp);
if (retcode != RIG_OK)
{
fprintf(stderr, "amp_open: error = %s \n", rigerror(retcode));
exit(2);
}
if (verbose > 0)
{
printf("Opened amp model %d, '%s'\n",
my_amp->caps->amp_model,
my_amp->caps->model_name);
}
rig_debug(RIG_DEBUG_VERBOSE,
"Backend version: %s, Status: %s\n",
my_amp->caps->version,
rig_strstatus(my_amp->caps->status));
exitcode = 0;
#ifdef HAVE_LIBREADLINE
if (interactive && prompt && have_rl)
{
rl_readline_name = "ampctl";
#ifdef HAVE_READLINE_HISTORY
using_history(); /* Initialize Readline History */
if (rd_hist || sv_hist)
{
if (!(hist_dir = getenv("AMPCTL_HIST_DIR")))
{
hist_dir = getenv("HOME");
}
if (((stat(hist_dir, &hist_dir_stat) == -1) && (errno == ENOENT))
|| !(S_ISDIR(hist_dir_stat.st_mode)))
{
fprintf(stderr, "Warning: %s is not a directory!\n", hist_dir);
}
int hist_path_size = sizeof(char) * (strlen(hist_dir) + strlen(hist_file) + 1);
hist_path = (char *)calloc(hist_path_size, sizeof(char));
snprintf(hist_path, hist_path_size, "%s%s", hist_dir, hist_file);
}
if (rd_hist && hist_path)
{
if (read_history(hist_path) == ENOENT)
{
fprintf(stderr,
"Warning: Could not read history from %s\n",
hist_path);
}
}
#endif /* HAVE_READLINE_HISTORY */
}
#endif /* HAVE_LIBREADLINE */
do
{
retcode = ampctl_parse(my_amp, stdin, stdout, argv, argc);
if (retcode == 2)
{
exitcode = 2;
}
}
while (retcode == 0 || retcode == 2);
#ifdef HAVE_LIBREADLINE
if (interactive && prompt && have_rl)
{
#ifdef HAVE_READLINE_HISTORY
if (sv_hist && hist_path)
{
if (write_history(hist_path) == ENOENT)
{
fprintf(stderr,
"\nWarning: Could not write history to %s\n",
hist_path);
}
}
if ((rd_hist || sv_hist) && hist_path)
{
free(hist_path);
hist_path = (char *)NULL;
}
#endif /* HAVE_READLINE_HISTORY */
}
#endif /* HAVE_LIBREADLINE */
amp_close(my_amp); /* close port */
amp_cleanup(my_amp); /* if you care about memory */
return exitcode;
}
void usage()
{
printf("Usage: ampctl [OPTION]... [COMMAND]...\n"
"Send COMMANDs to a connected amplifier.\n\n");
printf(
" -m, --model=ID select amplifier model number. See model list\n"
" -r, --amp-file=DEVICE set device of the amplifier to operate on\n"
" -s, --serial-speed=BAUD set serial speed of the serial port\n"
" -t, --send-cmd-term=CHAR set send_cmd command termination char\n"
" -C, --set-conf=PARM=VAL set config parameters\n"
" -L, --show-conf list all config parameters\n"
" -l, --list list all model numbers and exit\n"
" -u, --dump-caps dump capabilities and exit\n"
#ifdef HAVE_READLINE_HISTORY
" -i, --read-history read prior interactive session history\n"
" -I, --save-history save current interactive session history\n"
#endif
" -v, --verbose set verbose mode, cumulative\n"
" -Z, --debug-time-stamps enable time stamps for debug messages\n"
" -h, --help display this help and exit\n"
" -V, --version output version information and exit\n\n"
);
usage_amp(stdout);
printf("\nReport bugs to <hamlib-developer@lists.sourceforge.net>.\n");
}

2305
tests/ampctl_parse.c 100644

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,50 @@
/*
* ampctl_parse.h - (C) Stephane Fillod 2000-2008
* Derived from rotctl_parse.h - (C) Michael Black 2019
*
* This program test/control an amplifier using Hamlib.
* It takes commands in interactive mode as well as
* from command line options.
*
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef AMPCTL_PARSE_H
#define AMPCTL_PARSE_H
#include <stdio.h>
#include <hamlib/amplifier.h>
/*
* external prototype
*/
int dumpcaps_amp(AMP *, FILE *);
/*
* Prototypes
*/
void usage_amp(FILE *);
void version();
void list_models();
int print_conf_list(const struct confparams *cfp, rig_ptr_t data);
int set_conf(AMP *my_amp, char *conf_parms);
int ampctl_parse(AMP *my_amp, FILE *fin, FILE *fout, char *argv[], int argc);
#endif /* AMPCTL_PARSE_H */

715
tests/ampctld.c 100644
Wyświetl plik

@ -0,0 +1,715 @@
/*
* ampctld.c - (C) Stephane Fillod 2000-2011
* (C) Nate Bargmann 2010,2011,2012,2013
*
* This program test/control an amplifier using Hamlib.
* It takes commands from network connection.
*
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <getopt.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h> /* See NOTES */
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#elif HAVE_WS2TCPIP_H
# include <ws2tcpip.h>
# include <fcntl.h>
# if defined(HAVE_WSPIAPI_H)
# include <wspiapi.h>
# endif
#endif
#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif
#ifdef HAVE_PTHREAD
# include <pthread.h>
#endif
#include <hamlib/amplifier.h>
#include "misc.h"
#include "ampctl_parse.h"
struct handle_data
{
AMP *amp;
int sock;
struct sockaddr_storage cli_addr;
socklen_t clilen;
};
void *handle_socket(void *arg);
void usage();
/*
* 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.
* TODO: add an option to read from a file
*/
#define SHORT_OPTIONS "m:r:s:C:t:T:LuvhVlZ"
static struct option long_options[] =
{
{"model", 1, 0, 'm'},
{"amp-file", 1, 0, 'r'},
{"serial-speed", 1, 0, 's'},
{"port", 1, 0, 't'},
{"listen-addr", 1, 0, 'T'},
{"list", 0, 0, 'l'},
{"set-conf", 1, 0, 'C'},
{"show-conf", 0, 0, 'L'},
{"dump-caps", 0, 0, 'u'},
{"debug-time-stamps", 0, 0, 'Z'},
{"verbose", 0, 0, 'v'},
{"help", 0, 0, 'h'},
{"version", 0, 0, 'V'},
{0, 0, 0, 0}
};
int interactive = 1; /* no cmd because of daemon */
int prompt = 0 ; /* Daemon mode for rigparse return string */
const char *portno = "4533";
const char *src_addr = NULL; /* INADDR_ANY */
char send_cmd_term = '\r'; /* send_cmd termination char */
#define MAXCONFLEN 128
static void handle_error(enum rig_debug_level_e lvl, const char *msg)
{
int e;
#ifdef __MINGW32__
LPVOID lpMsgBuf;
lpMsgBuf = (LPVOID)"Unknown error";
e = WSAGetLastError();
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
e,
// Default language
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0,
NULL))
{
rig_debug(lvl, "%s: Network error %d: %s\n", msg, e, lpMsgBuf);
LocalFree(lpMsgBuf);
}
else
{
rig_debug(lvl, "%s: Network error %d\n", msg, e);
}
#else
e = errno;
rig_debug(lvl, "%s: Network error %d: %s\n", msg, e, strerror(e));
#endif
}
int main(int argc, char *argv[])
{
AMP *my_amp; /* handle to amp (instance) */
amp_model_t my_model = AMP_MODEL_DUMMY;
int retcode; /* generic return code from functions */
int verbose = 0;
int show_conf = 0;
int dump_caps_opt = 0;
const char *amp_file = NULL;
int serial_rate = 0;
char conf_parms[MAXCONFLEN] = "";
struct addrinfo hints, *result, *saved_result;
int sock_listen;
int reuseaddr = 1;
int sockopt;
char host[NI_MAXHOST];
char serv[NI_MAXSERV];
#ifdef HAVE_PTHREAD
pthread_t thread;
pthread_attr_t attr;
#endif
struct handle_data *arg;
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);
}
amp_file = 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 't':
if (!optarg)
{
usage(); /* wrong arg count */
exit(1);
}
portno = optarg;
break;
case 'T':
if (!optarg)
{
usage(); /* wrong arg count */
exit(1);
}
src_addr = optarg;
break;
case 'v':
verbose++;
break;
case 'L':
show_conf++;
break;
case 'l':
list_models();
exit(0);
case 'u':
dump_caps_opt++;
break;
case 'Z':
rig_set_debug_time_stamp(1);
break;
default:
usage(); /* unknown option? */
exit(1);
}
}
rig_set_debug(verbose);
rig_debug(RIG_DEBUG_VERBOSE, "ampctld, %s\n", hamlib_version);
rig_debug(RIG_DEBUG_VERBOSE,
"Report bugs to <hamlib-developer@lists.sourceforge.net>\n\n");
my_amp = amp_init(my_model);
if (!my_amp)
{
fprintf(stderr,
"Unknown amp num %d, or initialization error.\n",
my_model);
fprintf(stderr, "Please check with --list option.\n");
exit(2);
}
#if 0
retcode = set_conf(my_amp, conf_parms);
if (retcode != RIG_OK)
{
fprintf(stderr, "Config parameter error: %s\n", rigerror(retcode));
exit(2);
}
#endif
if (amp_file)
{
strncpy(my_amp->state.ampport.pathname, amp_file, FILPATHLEN - 1);
}
/* FIXME: bound checking and port type == serial */
if (serial_rate != 0)
{
my_amp->state.ampport.parm.serial.rate = serial_rate;
}
#if 0
/*
* print out conf parameters
*/
if (show_conf)
{
amp_token_foreach(my_amp, print_conf_list, (rig_ptr_t)my_amp);
}
#endif
/*
* Print out conf parameters, and exits immediately as we may be
* interested only in only caps, and rig_open may fail.
*/
if (dump_caps_opt)
{
dumpcaps_amp(my_amp, stdout);
amp_cleanup(my_amp); /* if you care about memory */
exit(0);
}
retcode = amp_open(my_amp);
if (retcode != RIG_OK)
{
fprintf(stderr, "amp_open: error = %s \n", rigerror(retcode));
exit(2);
}
if (verbose > 0)
{
printf("Opened amp model %d, '%s'\n",
my_amp->caps->amp_model,
my_amp->caps->model_name);
}
rig_debug(RIG_DEBUG_VERBOSE,
"Backend version: %s, Status: %s\n",
my_amp->caps->version,
rig_strstatus(my_amp->caps->status));
#ifdef __MINGW32__
# ifndef SO_OPENTYPE
# define SO_OPENTYPE 0x7008
# endif
# ifndef SO_SYNCHRONOUS_NONALERT
# define SO_SYNCHRONOUS_NONALERT 0x20
# endif
# ifndef INVALID_SOCKET
# define INVALID_SOCKET -1
# endif
WSADATA wsadata;
if (WSAStartup(MAKEWORD(1, 1), &wsadata) == SOCKET_ERROR)
{
fprintf(stderr, "WSAStartup socket error\n");
exit(1);
}
sockopt = SO_SYNCHRONOUS_NONALERT;
setsockopt(INVALID_SOCKET,
SOL_SOCKET,
SO_OPENTYPE,
(char *)&sockopt,
sizeof(sockopt));
#endif
/*
* Prepare listening socket
*/
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM; /* TCP socket */
hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
hints.ai_protocol = 0; /* Any protocol */
retcode = getaddrinfo(src_addr, portno, &hints, &result);
if (retcode != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(retcode));
exit(2);
}
saved_result = result;
do
{
sock_listen = socket(result->ai_family,
result->ai_socktype,
result->ai_protocol);
if (sock_listen < 0)
{
handle_error(RIG_DEBUG_ERR, "socket");
freeaddrinfo(result); /* No longer needed */
exit(1);
}
if (setsockopt(sock_listen, SOL_SOCKET, SO_REUSEADDR,
(char *)&reuseaddr, sizeof(reuseaddr)) < 0)
{
handle_error(RIG_DEBUG_ERR, "setsockopt");
freeaddrinfo(result); /* No longer needed */
exit(1);
}
#ifdef IPV6_V6ONLY
if (AF_INET6 == result->ai_family)
{
/* allow IPv4 mapped to IPv6 clients, MS & BSD default this
to 1 i.e. disallowed */
sockopt = 0;
if (setsockopt(sock_listen,
IPPROTO_IPV6,
IPV6_V6ONLY,
(char *)&sockopt,
sizeof(sockopt))
< 0)
{
handle_error(RIG_DEBUG_ERR, "setsockopt");
freeaddrinfo(saved_result); /* No longer needed */
exit(1);
}
}
#endif
if (0 == bind(sock_listen, result->ai_addr, result->ai_addrlen))
{
break;
}
handle_error(RIG_DEBUG_WARN, "binding failed (trying next interface)");
#ifdef __MINGW32__
closesocket(sock_listen);
#else
close(sock_listen);
#endif
}
while ((result = result->ai_next) != NULL);
freeaddrinfo(saved_result); /* No longer needed */
if (NULL == result)
{
rig_debug(RIG_DEBUG_ERR, "bind error - no available interface\n");
exit(1);
}
if (listen(sock_listen, 4) < 0)
{
handle_error(RIG_DEBUG_ERR, "listening");
exit(1);
}
#ifdef SIGPIPE
/* Ignore SIGPIPE as we will handle it at the write()/send() calls
that will consequently fail with EPIPE. All child threads will
inherit this disposition which is what we want. */
#if HAVE_SIGACTION
struct sigaction act;
memset(&act, 0, sizeof act);
act.sa_handler = SIG_IGN;
act.sa_flags = SA_RESTART;
if (sigaction(SIGPIPE, &act, NULL))
{
handle_error(RIG_DEBUG_ERR, "sigaction");
}
#elif HAVE_SIGNAL
if (SIG_ERR == signal(SIGPIPE, SIG_IGN))
{
handle_error(RIG_DEBUG_ERR, "signal");
}
#endif
#endif
/*
* main loop accepting connections
*/
do
{
arg = malloc(sizeof(struct handle_data));
if (!arg)
{
rig_debug(RIG_DEBUG_ERR, "malloc: %s\n", strerror(errno));
exit(1);
}
arg->amp = my_amp;
arg->clilen = sizeof(arg->cli_addr);
arg->sock = accept(sock_listen,
(struct sockaddr *) &arg->cli_addr,
&arg->clilen);
if (arg->sock < 0)
{
handle_error(RIG_DEBUG_ERR, "accept");
break;
}
if ((retcode = getnameinfo((struct sockaddr const *)&arg->cli_addr,
arg->clilen,
host,
sizeof(host),
serv,
sizeof(serv),
NI_NOFQDN))
< 0)
{
rig_debug(RIG_DEBUG_WARN,
"Peer lookup error: %s",
gai_strerror(retcode));
}
rig_debug(RIG_DEBUG_VERBOSE,
"Connection opened from %s:%s\n",
host,
serv);
#ifdef HAVE_PTHREAD
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
retcode = pthread_create(&thread, &attr, handle_socket, arg);
if (retcode != 0)
{
rig_debug(RIG_DEBUG_ERR, "pthread_create: %s\n", strerror(retcode));
break;
}
#else
handle_socket(arg);
#endif
}
while (retcode == 0);
amp_close(my_amp); /* close port */
amp_cleanup(my_amp); /* if you care about memory */
#ifdef __MINGW32__
WSACleanup();
#endif
return 0;
}
/*
* This is the function run by the threads
*/
void *handle_socket(void *arg)
{
struct handle_data *handle_data_arg = (struct handle_data *)arg;
FILE *fsockin;
FILE *fsockout;
int retcode;
char host[NI_MAXHOST];
char serv[NI_MAXSERV];
#ifdef __MINGW32__
int sock_osfhandle = _open_osfhandle(handle_data_arg->sock, _O_RDONLY);
if (sock_osfhandle == -1)
{
rig_debug(RIG_DEBUG_ERR, "_open_osfhandle error: %s\n", strerror(errno));
goto handle_exit;
}
fsockin = _fdopen(sock_osfhandle, "rb");
#else
fsockin = fdopen(handle_data_arg->sock, "rb");
#endif
if (!fsockin)
{
rig_debug(RIG_DEBUG_ERR, "fdopen in: %s\n", strerror(errno));
goto handle_exit;
}
#ifdef __MINGW32__
fsockout = _fdopen(sock_osfhandle, "wb");
#else
fsockout = fdopen(handle_data_arg->sock, "wb");
#endif
if (!fsockout)
{
rig_debug(RIG_DEBUG_ERR, "fdopen out: %s\n", strerror(errno));
fclose(fsockin);
goto handle_exit;
}
do
{
retcode = ampctl_parse(handle_data_arg->amp, fsockin, fsockout, NULL, 0);
if (ferror(fsockin) || ferror(fsockout))
{
retcode = 1;
}
}
while (retcode == 0 || retcode == 2);
if ((retcode = getnameinfo((struct sockaddr const *)&handle_data_arg->cli_addr,
handle_data_arg->clilen,
host,
sizeof(host),
serv,
sizeof(serv),
NI_NOFQDN))
< 0)
{
rig_debug(RIG_DEBUG_WARN,
"Peer lookup error: %s",
gai_strerror(retcode));
}
rig_debug(RIG_DEBUG_VERBOSE,
"Connection closed from %s:%s\n",
host,
serv);
fclose(fsockin);
#ifndef __MINGW32__
fclose(fsockout);
#endif
handle_exit:
#ifdef __MINGW32__
closesocket(handle_data_arg->sock);
#else
close(handle_data_arg->sock);
#endif
free(arg);
#ifdef HAVE_PTHREAD
pthread_exit(NULL);
#endif
return NULL;
}
void usage()
{
printf("Usage: ampctld [OPTION]... [COMMAND]...\n"
"Daemon serving COMMANDs to a connected amplifier.\n\n");
printf(
" -m, --model=ID select amplifier model number. See model list\n"
" -r, --amp-file=DEVICE set device of the amplifier to operate on\n"
" -s, --serial-speed=BAUD set serial speed of the serial port\n"
" -t, --port=NUM set TCP listening port, default %s\n"
" -T, --listen-addr=IPADDR set listening IP address, default ANY\n"
" -C, --set-conf=PARM=VAL set config parameters\n"
" -L, --show-conf list all config parameters\n"
" -l, --list list all model numbers and exit\n"
" -u, --dump-caps dump capabilities and exit\n"
" -v, --verbose set verbose mode, cumulative\n"
" -Z, --debug-time-stamps enable time stamps for debug messages\n"
" -h, --help display this help and exit\n"
" -V, --version output version information and exit\n\n",
portno);
usage_amp(stdout);
printf("\nReport bugs to <hamlib-developer@lists.sourceforge.net>.\n");
}

Wyświetl plik

@ -0,0 +1,155 @@
/*
* dumpcaps_amp.c - Copyright (C) 2000-2012 Stephane Fillod
* This programs dumps the capabilities of a backend rig.
*
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <hamlib/rig.h>
#include "misc.h"
#include "sprintflst.h"
#include "ampctl_parse.h"
/*
* the amp may be in amp_init state, but not openned
*/
int dumpcaps_amp(AMP *amp, FILE *fout)
{
const struct amp_caps *caps;
int backend_warnings = 0;
static char prntbuf[1024];
if (!amp || !amp->caps)
{
return -RIG_EINVAL;
}
caps = amp->caps;
fprintf(fout, "Caps dump for model:\t%d\n", caps->amp_model);
fprintf(fout, "Model name:\t\t%s\n", caps->model_name);
fprintf(fout, "Mfg name:\t\t%s\n", caps->mfg_name);
fprintf(fout, "Backend version:\t%s\n", caps->version);
fprintf(fout, "Backend copyright:\t%s\n", caps->copyright);
fprintf(fout, "Backend status:\t\t%s\n", rig_strstatus(caps->status));
fprintf(fout, "Amp type:\t\t");
switch (caps->amp_type & AMP_TYPE_MASK)
{
case AMP_TYPE_OTHER:
fprintf(fout, "Other\n");
break;
default:
fprintf(fout, "Unknown type=%d\n", caps->amp_type);
backend_warnings++;
}
fprintf(fout, "Port type:\t\t");
switch (caps->port_type)
{
case RIG_PORT_SERIAL:
fprintf(fout, "RS-232\n");
fprintf(fout,
"Serial speed:\t\t%d..%d bauds, %d%c%d%s\n",
caps->serial_rate_min,
caps->serial_rate_max,
caps->serial_data_bits,
caps->serial_parity == RIG_PARITY_NONE ? 'N' :
caps->serial_parity == RIG_PARITY_ODD ? 'O' :
caps->serial_parity == RIG_PARITY_EVEN ? 'E' :
caps->serial_parity == RIG_PARITY_MARK ? 'M' : 'S',
caps->serial_stop_bits,
caps->serial_handshake == RIG_HANDSHAKE_NONE ? "" :
(caps->serial_handshake == RIG_HANDSHAKE_XONXOFF ? " XONXOFF" : " CTS/RTS")
);
break;
case RIG_PORT_PARALLEL:
fprintf(fout, "Parallel\n");
break;
case RIG_PORT_DEVICE:
fprintf(fout, "Device driver\n");
break;
case RIG_PORT_USB:
fprintf(fout, "USB\n");
break;
case RIG_PORT_NETWORK:
fprintf(fout, "Network link\n");
break;
case RIG_PORT_UDP_NETWORK:
fprintf(fout, "UDP Network link\n");
break;
case RIG_PORT_NONE:
fprintf(fout, "None\n");
break;
default:
fprintf(fout, "Unknown\n");
backend_warnings++;
}
fprintf(fout,
"Write delay:\t\t%dmS, timeout %dmS, %d retr%s\n",
caps->write_delay,
caps->timeout, caps->retry,
(caps->retry == 1) ? "y" : "ies");
fprintf(fout,
"Post Write delay:\t%dmS\n",
caps->post_write_delay);
fprintf(fout, "Has priv data:\t\t%c\n", caps->priv != NULL ? 'Y' : 'N');
sprintf_level_amp(prntbuf, caps->has_get_level);
fprintf(fout, "Get level: %s\n", prntbuf);
/*
* Status is either 'Y'es, 'E'mulated, 'N'o
*
* TODO: keep me up-to-date with API call list!
*/
fprintf(fout, "Has Init:\t\t%c\n", caps->amp_init != NULL ? 'Y' : 'N');
fprintf(fout, "Has Cleanup:\t\t%c\n", caps->amp_cleanup != NULL ? 'Y' : 'N');
fprintf(fout, "Has Open:\t\t%c\n", caps->amp_open != NULL ? 'Y' : 'N');
fprintf(fout, "Has Close:\t\t%c\n", caps->amp_close != NULL ? 'Y' : 'N');
fprintf(fout, "Can set Conf:\t\t%c\n", caps->set_conf != NULL ? 'Y' : 'N');
fprintf(fout, "Can get Conf:\t\t%c\n", caps->get_conf != NULL ? 'Y' : 'N');
fprintf(fout, "Can Reset:\t\t%c\n", caps->reset != NULL ? 'Y' : 'N');
fprintf(fout, "Can get Info:\t\t%c\n", caps->get_info != NULL ? 'Y' : 'N');
fprintf(fout, "\nOverall backend warnings: %d\n", backend_warnings);
return backend_warnings;
}

Wyświetl plik

@ -33,6 +33,7 @@
#include <unistd.h>
#include <hamlib/rig.h>
#include <hamlib/amplifier.h>
#include "sprintflst.h"
#include "misc.h"
@ -187,6 +188,34 @@ int sprintf_level(char *str, setting_t level)
return len;
}
int sprintf_level_amp(char *str, setting_t level)
{
int i, len = 0;
*str = '\0';
if (level == AMP_LEVEL_NONE)
{
return 0;
}
for (i = 0; i < RIG_SETTING_MAX; i++)
{
const char *ms = amp_strlevel(level & rig_idx2setting(i));
if (!ms || !ms[0])
{
continue; /* unknown, FIXME! */
}
strcat(str, ms);
strcat(str, " ");
len += strlen(ms) + 1;
}
return len;
}
int sprintf_level_ext(char *str, const struct confparams *extlevels)
{

Wyświetl plik

@ -32,6 +32,7 @@ extern int sprintf_mode(char *str, rmode_t);
extern int sprintf_vfo(char *str, vfo_t);
extern int sprintf_func(char *str, setting_t);
extern int sprintf_level(char *str, setting_t);
extern int sprintf_level_amp(char *str, setting_t);
extern int sprintf_level_ext(char *str, const struct confparams *);
extern int sprintf_level_gran(char *str, setting_t, const gran_t gran[]);
extern int sprintf_parm(char *str, setting_t);