Hamlib/rotators/easycomm/easycomm.c

691 wiersze
16 KiB
C

/*
* Hamlib Rotator backend - Easycom
* Copyright (c) 2001-2003 by Stephane Fillod
* Contributed by Francois Retief <fgretief@sun.ac.za>
* Copyright (c) 2014 by Alexander Schultze <alexschultze@gmail.com>
*
*
* 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 <stdio.h>
#include <string.h> /* String function definitions */
#include "hamlib/rotator.h"
#include "serial.h"
#include "register.h"
#include "idx_builtin.h"
#include "easycomm.h"
#define EASYCOMM3_LEVELS ROT_LEVEL_SPEED
/* ************************************************************************* */
/**
* easycomm_transaction
*
* Assumes rot!=NULL and cmdstr!=NULL
*
* cmdstr - string to send to rotator
* data - buffer for reply string
* data_len - (input) Maximum size of buffer
* (output) Number of bytes read.
*/
static int
2019-11-30 16:19:08 +00:00
easycomm_transaction(ROT *rot, const char *cmdstr, char *data, size_t data_len)
{
2024-02-16 10:23:20 +00:00
hamlib_port_t *rotp = ROTPORT(rot);
2019-11-30 16:19:08 +00:00
int retval;
2023-12-18 15:11:19 +00:00
int retry = rot->caps->retry;
2019-11-30 16:19:08 +00:00
rig_debug(RIG_DEBUG_TRACE, "%s called: %s\n", __func__, cmdstr);
if (!rot)
{
return -RIG_EINVAL;
}
2023-12-18 15:11:19 +00:00
do
2019-11-30 16:19:08 +00:00
{
2024-02-16 10:23:20 +00:00
rig_flush(rotp);
retval = write_block(rotp, (unsigned char *) cmdstr, strlen(cmdstr));
2019-11-30 16:19:08 +00:00
2023-12-18 15:11:19 +00:00
if (retval != RIG_OK)
{
goto transaction_quit;
}
2019-11-30 16:19:08 +00:00
2023-12-18 15:11:19 +00:00
if (data == NULL)
{
return RIG_OK; /* don't want a reply */
}
2019-11-30 16:19:08 +00:00
2024-02-16 10:23:20 +00:00
retval = read_string(rotp, (unsigned char *) data, data_len,
2023-12-18 15:11:19 +00:00
"\n", 1, 0, 1);
if (retval < 0)
{
rig_debug(RIG_DEBUG_TRACE, "%s read_string failed with status %d:%s\n",
__func__,
retval, strerror(retval));
goto transaction_quit;
}
else
{
rig_debug(RIG_DEBUG_TRACE, "%s read_string: %s\n", __func__, data);
retval = RIG_OK;
}
2019-11-30 16:19:08 +00:00
}
2023-12-18 15:11:19 +00:00
while (--retry && retval != RIG_OK);
2019-11-30 16:19:08 +00:00
transaction_quit:
return retval;
}
/* ************************************************************************* */
static int
easycomm_rot_set_position(ROT *rot, azimuth_t az, elevation_t el)
{
char cmdstr[64];
int retval;
2019-11-30 16:19:08 +00:00
rig_debug(RIG_DEBUG_TRACE, "%s called: %f %f\n", __func__, az, el);
2019-11-30 16:19:08 +00:00
if (rot->caps->rot_model == ROT_MODEL_EASYCOMM1)
{
SNPRINTF(cmdstr, sizeof(cmdstr), "AZ%.1f EL%.1f UP000 XXX DN000 XXX\n", az, el);
}
2019-11-30 16:19:08 +00:00
else // for easycomm 2 & 3 and upwards
{
SNPRINTF(cmdstr, sizeof(cmdstr), "AZ%.1f EL%.1f\n", az, el);
}
2019-11-30 16:19:08 +00:00
retval = easycomm_transaction(rot, cmdstr, NULL, 0);
2019-11-30 16:19:08 +00:00
if (retval != RIG_OK)
{
return retval;
}
/* TODO: Error processing */
2019-11-30 16:19:08 +00:00
return RIG_OK;
}
static int
easycomm_rot_get_position(ROT *rot, azimuth_t *az, elevation_t *el)
{
char cmdstr[16], ackbuf[32];
int retval;
2019-11-30 16:16:28 +00:00
rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__);
SNPRINTF(cmdstr, sizeof(cmdstr), "AZ\n");
retval = easycomm_transaction(rot, cmdstr, ackbuf, sizeof(ackbuf));
2019-11-30 16:19:08 +00:00
if (retval != RIG_OK)
{
rig_debug(RIG_DEBUG_TRACE, "%s got error: %d\n", __func__, retval);
return retval;
}
/* Parse parse string to extract AZ values */
2019-11-30 16:16:28 +00:00
rig_debug(RIG_DEBUG_TRACE, "%s got response: %s\n", __func__, ackbuf);
retval = sscanf(ackbuf, "AZ%f", az);
2019-11-30 16:19:08 +00:00
if (retval != 1)
2019-11-30 16:19:08 +00:00
{
2019-11-30 16:16:28 +00:00
rig_debug(RIG_DEBUG_ERR, "%s: unknown response (%s)\n", __func__, ackbuf);
return -RIG_ERJCTED;
}
2019-11-30 16:19:08 +00:00
SNPRINTF(cmdstr, sizeof(cmdstr), "EL\n");
retval = easycomm_transaction(rot, cmdstr, ackbuf, sizeof(ackbuf));
if (retval != RIG_OK)
{
rig_debug(RIG_DEBUG_TRACE, "%s got error: %d\n", __func__, retval);
return retval;
}
/* Parse parse string to extract EL values */
rig_debug(RIG_DEBUG_TRACE, "%s got response: %s\n", __func__, ackbuf);
retval = sscanf(ackbuf, "EL%f", el);
if (retval != 1)
{
rig_debug(RIG_DEBUG_ERR, "%s: unknown response (%s)\n", __func__, ackbuf);
return -RIG_ERJCTED;
}
easycomm patch from Steve Conklin, AI4QR The attached patch restores what I think is the original easycomm rotator interface functionality. It eliminates the conditional code for USE_CUSTOM_CODE and USE_TEST_CODE. Apparently for a very long time, the easycomm back end has been build with USE_CUSTOM_CODE hardcoded in the source file. This generated code that issued commands not even remotely similar to what's specified in the easycommII protocol, which is documented in the easycomm directory for hamlib. It appears that at some point someone used the easycomm back end to implement some custom tests for something, and it was committed and has been carried this way ever since. This restored what I think is proper functionality according to the easycomm spec. If you are a user of the easycomm back end, or you know of any easycomm compatible rotor controllers that can be used for testing, let me know and I can be more thorough about this. Notes and disclaimers: 0. The original easycomm spec author seems to be unavailable. 1. I don't think that there was valid code to parse the position data returned from the rotor controller. What was actually getting compiled simply set some hard-coded values. I replaced it with what I think is called for by the spec. 2. The easycomm spec is vague about what is supposed to be returned for any command, so I may still not be parsing position information correctly as it comes from other easycomm controllers. 3. I wrote my own rotator controller code based upon an interpretation of the easycomm II spec. This back end for rotctl works with my implementation. I don't have access to any other easycomm controllers or even know whether any exist, so I am unable to test this against any other implementation of easycomm. 4. Even when you select EASYCOMM II as the back end, it sends commands which are only supposed to be valid for easycomm I according to the spec (i.e. the position set command includes uplink and downlink frequency and mode information fields). My rotor controller handles these, so I didn't change the position set portion of the code. I understand if there's concern for breaking rotator control for existing users of the easycomm back end (if any actually exist). If this patch is too risky, I'll either rewrite my controller to use another protocol, or add another back end for my own newly invented protocol "ai4qrcomm" (and document it better than easycomm). Thanks, Steve, AI4QR Signed-off-by: Nate Bargmann <n0nb@n0nb.us>
2013-09-05 23:21:04 +00:00
return RIG_OK;
}
static int
easycomm_rot_stop(ROT *rot)
{
int retval;
2019-11-30 16:16:28 +00:00
rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__);
retval = easycomm_transaction(rot, "SA SE \n", NULL, 0);
2019-11-30 16:19:08 +00:00
if (retval != RIG_OK)
{
return retval;
}
2019-11-30 16:19:08 +00:00
/* TODO: error processing */
return RIG_OK;
}
static int
easycomm_rot_reset(ROT *rot, rot_reset_t rst)
{
int retval;
2019-11-30 16:16:28 +00:00
rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__);
retval = easycomm_transaction(rot, "RESET\n", NULL, 0);
2019-11-30 16:19:08 +00:00
if (retval != RIG_OK) /* Custom command (not in Easycomm) */
2019-11-30 16:19:08 +00:00
{
return retval;
}
2019-11-30 16:19:08 +00:00
return RIG_OK;
}
static int
easycomm_rot_park(ROT *rot)
{
int retval;
2019-11-30 16:16:28 +00:00
rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__);
retval = easycomm_transaction(rot, "PARK\n", NULL, 0);
2019-11-30 16:19:08 +00:00
if (retval != RIG_OK) /* Custom command (not in Easycomm) */
2019-11-30 16:19:08 +00:00
{
return retval;
}
2019-11-30 16:19:08 +00:00
return RIG_OK;
}
static int
easycomm_rot_move(ROT *rot, int direction, int speed)
{
char cmdstr[24];
int retval;
2019-11-30 16:16:28 +00:00
rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__);
2019-11-30 16:19:08 +00:00
/* For EasyComm 1/2/3 */
switch (direction)
{
case ROT_MOVE_UP: /* Elevation increase */
SNPRINTF(cmdstr, sizeof(cmdstr), "MU\n");
break;
2019-11-30 16:19:08 +00:00
case ROT_MOVE_DOWN: /* Elevation decrease */
SNPRINTF(cmdstr, sizeof(cmdstr), "MD\n");
break;
2019-11-30 16:19:08 +00:00
case ROT_MOVE_LEFT: /* Azimuth decrease */
SNPRINTF(cmdstr, sizeof(cmdstr), "ML\n");
break;
2019-11-30 16:19:08 +00:00
case ROT_MOVE_RIGHT: /* Azimuth increase */
SNPRINTF(cmdstr, sizeof(cmdstr), "MR\n");
break;
2019-11-30 16:19:08 +00:00
default:
2019-11-30 16:19:08 +00:00
rig_debug(RIG_DEBUG_ERR, "%s: Invalid direction value! (%d)\n", __func__,
direction);
return -RIG_EINVAL;
}
retval = easycomm_transaction(rot, cmdstr, NULL, 0);
2019-11-30 16:19:08 +00:00
if (retval != RIG_OK)
2019-11-30 16:19:08 +00:00
{
return retval;
2019-11-30 16:19:08 +00:00
}
return RIG_OK;
}
static int easycomm_rot_move_velocity(ROT *rot, int direction, int speed)
{
struct rot_state *rs = &rot->state;
char cmdstr[24];
int retval;
int easycomm_speed;
2019-11-30 16:16:28 +00:00
rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__);
2019-11-30 16:19:08 +00:00
2020-12-17 21:07:04 +00:00
if (speed == ROT_SPEED_NOCHANGE)
{
easycomm_speed = rs->current_speed;
2020-12-17 21:07:04 +00:00
}
else
{
if (speed < 1 || speed > 100)
{
rig_debug(RIG_DEBUG_ERR, "%s: Invalid speed value (1-100)! (%d)\n", __func__,
2020-12-17 21:07:04 +00:00
speed);
return -RIG_EINVAL;
}
easycomm_speed = ((speed - 1) * 100);
rs->current_speed = easycomm_speed;
}
/* Speed for EasyComm 3 */
2019-11-30 16:19:08 +00:00
switch (direction)
{
case ROT_MOVE_UP: /* Elevation increase */
SNPRINTF(cmdstr, sizeof(cmdstr), "VU%04d\n", easycomm_speed);
break;
2019-11-30 16:19:08 +00:00
case ROT_MOVE_DOWN: /* Elevation decrease */
SNPRINTF(cmdstr, sizeof(cmdstr), "VD%04d\n", easycomm_speed);
break;
2019-11-30 16:19:08 +00:00
case ROT_MOVE_LEFT: /* Azimuth decrease */
SNPRINTF(cmdstr, sizeof(cmdstr), "VL%04d\n", easycomm_speed);
break;
2019-11-30 16:19:08 +00:00
case ROT_MOVE_RIGHT: /* Azimuth increase */
SNPRINTF(cmdstr, sizeof(cmdstr), "VR%04d\n", easycomm_speed);
break;
2019-11-30 16:19:08 +00:00
default:
2019-11-30 16:19:08 +00:00
rig_debug(RIG_DEBUG_ERR, "%s: Invalid direction value! (%d)\n", __func__,
direction);
return -RIG_EINVAL;
}
retval = easycomm_transaction(rot, cmdstr, NULL, 0);
2019-11-30 16:19:08 +00:00
if (retval != RIG_OK)
2019-11-30 16:19:08 +00:00
{
return retval;
2019-11-30 16:19:08 +00:00
}
return RIG_OK;
}
static int easycomm_rot_get_level(ROT *rot, setting_t level, value_t *val)
{
2023-10-13 22:36:29 +00:00
const struct rot_state *rs = &rot->state;
rig_debug(RIG_DEBUG_VERBOSE, "%s called: %s\n", __func__, rot_strlevel(level));
2020-12-17 21:07:04 +00:00
switch (level)
{
case ROT_LEVEL_SPEED:
val->i = rs->current_speed;
break;
default:
return -RIG_ENAVAIL;
}
return RIG_OK;
}
static int easycomm_rot_set_level(ROT *rot, setting_t level, value_t val)
{
struct rot_state *rs = &rot->state;
rig_debug(RIG_DEBUG_VERBOSE, "%s called: %s\n", __func__, rot_strlevel(level));
2020-12-17 21:07:04 +00:00
switch (level)
{
case ROT_LEVEL_SPEED:
{
int speed = val.i;
if (speed < 0)
{
speed = 0;
}
2020-12-17 21:07:04 +00:00
else if (speed > 9999)
{
speed = 9999;
}
rs->current_speed = speed;
break;
}
default:
return -RIG_ENAVAIL;
}
return RIG_OK;
}
/*
* Get Info
* returns the model name string
*/
2023-10-14 17:01:41 +00:00
// cppcheck-suppress constParameterCallback
2019-11-30 16:19:08 +00:00
static const char *easycomm_rot_get_info(ROT *rot)
{
2019-11-30 16:19:08 +00:00
const struct rot_caps *rc;
2019-11-30 16:19:08 +00:00
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
2019-11-30 16:19:08 +00:00
if (!rot)
{
return (const char *) - RIG_EINVAL;
}
2019-11-30 16:19:08 +00:00
rc = rot->caps;
2019-11-30 16:19:08 +00:00
return rc->model_name;
}
/*
* Receive status / configuration / output
*
* For configuration registers, *val must contain string of register e.g. '0'-'f'
*/
static int easycomm_rot_get_conf(ROT *rot, hamlib_token_t token, char *val)
2019-11-30 16:19:08 +00:00
{
char cmdstr[16], ackbuf[32];
int retval;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
rig_debug(RIG_DEBUG_TRACE, "%s: token = %d", __func__, (int)token);
if (!rot)
{
return -RIG_EINVAL;
}
switch (token)
{
case TOK_GET_STATUS:
SNPRINTF(cmdstr, sizeof(cmdstr), "GS\n;");
2019-11-30 16:19:08 +00:00
break;
case TOK_GET_ERRORS:
SNPRINTF(cmdstr, sizeof(cmdstr), "GE\n;");
2019-11-30 16:19:08 +00:00
break;
case TOK_GET_INPUT:
SNPRINTF(cmdstr, sizeof(cmdstr), "IP\n;");
2019-11-30 16:19:08 +00:00
break;
case TOK_GET_ANALOG_INPUT:
SNPRINTF(cmdstr, sizeof(cmdstr), "AN\n;");
2019-11-30 16:19:08 +00:00
break;
case TOK_GET_VERSION:
SNPRINTF(cmdstr, sizeof(cmdstr), "VE\n;");
2019-11-30 16:19:08 +00:00
break;
case TOK_GET_CONFIG:
SNPRINTF(cmdstr, sizeof(cmdstr), "CR %c\n;", *val);
2019-11-30 16:19:08 +00:00
break;
default:
return -RIG_EINVAL;
}
rig_debug(RIG_DEBUG_TRACE, "%s: cmdstr = %s, *val = %c\n", __func__, cmdstr,
*val);
retval = easycomm_transaction(rot, cmdstr, ackbuf, sizeof(ackbuf));
if (retval != RIG_OK)
{
rig_debug(RIG_DEBUG_TRACE, "%s got error: %d\n", __func__, retval);
return retval;
}
2019-11-30 16:16:28 +00:00
rig_debug(RIG_DEBUG_TRACE, "%s got response: %s\n", __func__, ackbuf);
/* Return given string at correct position*/
memcpy(val, ackbuf + 2, sizeof(ackbuf) - 2); /* CCxxxxxx */
return RIG_OK;
}
/*
* Set configuration
*
* For configuration registers, *val must contain char of register e.g. '0'-'f' followed by setting
* e.g. x,yyyyy
*/
static int easycomm_rot_set_conf(ROT *rot, hamlib_token_t token, const char *val)
2019-11-30 16:19:08 +00:00
{
char cmdstr[16];
int retval;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
rig_debug(RIG_DEBUG_TRACE, "%s: token = %d", __func__, (int)token);
if (!rot)
{
return -RIG_EINVAL;
}
switch (token)
{
case TOK_SET_CONFIG:
SNPRINTF(cmdstr, sizeof(cmdstr), "CW%s\n;", val);
2019-11-30 16:19:08 +00:00
break;
default:
return -RIG_EINVAL;
}
rig_debug(RIG_DEBUG_TRACE, "%s: cmdstr = %s, *val = %c\n", __func__, cmdstr,
*val);
retval = easycomm_transaction(rot, cmdstr, NULL, 0);
if (retval != RIG_OK)
{
rig_debug(RIG_DEBUG_TRACE, "%s got error: %d\n", __func__, retval);
return retval;
}
return RIG_OK;
}
static int easycomm_rot_init(ROT *rot)
{
struct rot_state *rs = &rot->state;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
// Set default speed to half of maximum
rs->current_speed = 5000;
return RIG_OK;
}
/* ************************************************************************* */
/*
* Easycomm rotator capabilities.
*/
/** EasycommI implement essentially only the set position function, but
* I included the stop command too. The radio control tags is only included
* as dummy entries because the spec require them.
*/
2019-11-30 16:19:08 +00:00
const struct rot_caps easycomm1_rot_caps =
{
ROT_MODEL(ROT_MODEL_EASYCOMM1),
2019-11-30 16:19:08 +00:00
.model_name = "EasycommI",
.mfg_name = "Hamlib",
.version = "20231219.0",
2019-11-30 16:19:08 +00:00
.copyright = "LGPL",
2021-09-15 18:50:31 +00:00
.status = RIG_STATUS_STABLE,
2019-11-30 16:19:08 +00:00
.rot_type = ROT_TYPE_OTHER,
.port_type = RIG_PORT_SERIAL,
.serial_rate_min = 9600,
.serial_rate_max = 19200,
.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 = 200,
.retry = 3,
.min_az = 0.0,
.max_az = 360.0,
.min_el = 0.0,
.max_el = 180.0,
.priv = NULL, /* priv */
.set_position = easycomm_rot_set_position,
.stop = easycomm_rot_stop,
.get_info = easycomm_rot_get_info,
};
/* EasycommII implement most of the functions. Again the radio tags
* is only dummy values.
*/
2019-11-30 16:19:08 +00:00
const struct rot_caps easycomm2_rot_caps =
{
ROT_MODEL(ROT_MODEL_EASYCOMM2),
2019-11-30 16:19:08 +00:00
.model_name = "EasycommII",
.mfg_name = "Hamlib",
2023-12-18 15:11:19 +00:00
.version = "20231218.0",
2019-11-30 16:19:08 +00:00
.copyright = "LGPL",
2021-09-15 18:50:31 +00:00
.status = RIG_STATUS_STABLE,
2019-11-30 16:19:08 +00:00
.rot_type = ROT_TYPE_OTHER,
.port_type = RIG_PORT_SERIAL,
.serial_rate_min = 9600,
.serial_rate_max = 19200,
.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 = 200,
.retry = 3,
.min_az = 0.0,
.max_az = 360.0,
.min_el = 0.0,
.max_el = 180.0,
.priv = NULL, /* priv */
.rot_init = NULL,
.rot_cleanup = NULL,
.rot_open = NULL,
.rot_close = NULL,
.get_position = easycomm_rot_get_position,
.set_position = easycomm_rot_set_position,
.stop = easycomm_rot_stop,
.park = easycomm_rot_park,
.reset = easycomm_rot_reset,
.move = easycomm_rot_move,
.set_conf = easycomm_rot_set_conf,
.get_conf = easycomm_rot_get_conf,
.get_info = easycomm_rot_get_info,
};
/* EasycommIII provides changes Moving functions and info.
*/
2019-11-30 16:19:08 +00:00
const struct rot_caps easycomm3_rot_caps =
{
ROT_MODEL(ROT_MODEL_EASYCOMM3),
2019-11-30 16:19:08 +00:00
.model_name = "EasycommIII",
.mfg_name = "Hamlib",
2023-12-18 15:11:19 +00:00
.version = "2022312180",
2019-11-30 16:19:08 +00:00
.copyright = "LGPL",
.status = RIG_STATUS_STABLE,
2019-11-30 16:19:08 +00:00
.rot_type = ROT_TYPE_OTHER,
.port_type = RIG_PORT_SERIAL,
.serial_rate_min = 9600,
.serial_rate_max = 19200,
.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 = 200,
.retry = 3,
.min_az = 0.0,
.max_az = 360.0,
.min_el = 0.0,
.max_el = 180.0,
.priv = NULL, /* priv */
.has_get_level = EASYCOMM3_LEVELS,
.has_set_level = ROT_LEVEL_SET(EASYCOMM3_LEVELS),
.level_gran = { [ROT_LVL_SPEED] = { .min = { .i = 0 }, .max = { .i = 9999 }, .step = { .i = 1 } } },
.rot_init = easycomm_rot_init,
2019-11-30 16:19:08 +00:00
.rot_cleanup = NULL,
.rot_open = NULL,
.rot_close = NULL,
.get_position = easycomm_rot_get_position,
.set_position = easycomm_rot_set_position,
.stop = easycomm_rot_stop,
.park = easycomm_rot_park,
.reset = easycomm_rot_reset,
.move = easycomm_rot_move_velocity,
.get_level = easycomm_rot_get_level,
.set_level = easycomm_rot_set_level,
2019-11-30 16:19:08 +00:00
.set_conf = easycomm_rot_set_conf,
.get_conf = easycomm_rot_get_conf,
.get_info = easycomm_rot_get_info,
};
/* ************************************************************************* */
DECLARE_INITROT_BACKEND(easycomm)
{
2019-11-30 16:19:08 +00:00
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
rot_register(&easycomm1_rot_caps);
rot_register(&easycomm2_rot_caps);
rot_register(&easycomm3_rot_caps);
2019-11-30 16:19:08 +00:00
return RIG_OK;
}
/* ************************************************************************* */
/* end of file */