kopia lustrzana https://github.com/Hamlib/Hamlib
845 wiersze
17 KiB
C
845 wiersze
17 KiB
C
/* hamlib - Ham Radio Control Libraries
|
|
Copyright (C) 2000 Stephane Fillod and Frank Singleton
|
|
This file is part of the hamlib package.
|
|
|
|
Hamlib 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.
|
|
|
|
Hamlib 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 sane; see the file COPYING. If not, write to the Free
|
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
|
|
|
|
#include <rig.h>
|
|
#include <riglist.h>
|
|
#include "serial.h"
|
|
|
|
|
|
#define DEFAULT_SERIAL_PORT "/dev/ttyS0"
|
|
|
|
/*
|
|
* It would be nice to have an automatic way of referencing all the backends
|
|
* supported by hamlib. Maybe this array should be placed in a separate file..
|
|
*
|
|
* The rig_base is a variable length rig_caps* array, NULL terminated
|
|
*/
|
|
|
|
static const struct rig_caps *rig_base[] = {
|
|
&ft747_caps, &ic706_caps, &ic706mkiig_caps, /* ... */ NULL, };
|
|
|
|
static const char *rigerror_table[] = {
|
|
"Command completed sucessfully",
|
|
"Invalid parameter",
|
|
"Invalid configuration",
|
|
"Memory shortage",
|
|
"Feature not implemented",
|
|
"Communication timed out",
|
|
"IO error",
|
|
"Internal Hamlib error",
|
|
"Protocol error",
|
|
"Command rejected by the rig",
|
|
"Command performed, but arg truncated, result not guaranteed"
|
|
};
|
|
|
|
/*
|
|
* TODO: check table bounds, use gettext
|
|
*/
|
|
const char *rigerror(int errnum)
|
|
{
|
|
return rigerror_table[abs(errnum)];
|
|
}
|
|
|
|
|
|
RIG *rig_init(rig_model_t rig_model)
|
|
{
|
|
RIG *rig;
|
|
int i;
|
|
|
|
rig_debug(RIG_DEBUG_VERBOSE,"rig:rig_init called \n");
|
|
|
|
/* lookup for this rig */
|
|
for (i=0; rig_base[i]; i++) {
|
|
if (rig_base[i]->rig_model == rig_model)
|
|
break;
|
|
}
|
|
if (rig_base[i] == NULL) {
|
|
/* End of list, rig not supported, sorry! */
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* okay, we've found it. Allocate some memory and set it to zeros,
|
|
* and especially the initialize the callbacks
|
|
*/
|
|
rig = calloc(1, sizeof(RIG));
|
|
if (rig == NULL) {
|
|
/*
|
|
* FIXME: how can the caller know it's a memory shortage,
|
|
* and not "rig not found" ?
|
|
*/
|
|
return NULL;
|
|
}
|
|
|
|
/* remember, rig->caps is readonly */
|
|
rig->caps = rig_base[i];
|
|
|
|
/*
|
|
* populate the rig->state
|
|
* TODO: read the Preferences here!
|
|
*/
|
|
|
|
rig->state.port_type = RIG_PORT_SERIAL; /* default is serial port */
|
|
strncpy(rig->state.rig_path, DEFAULT_SERIAL_PORT, FILPATHLEN);
|
|
rig->state.port_type = RIG_PORT_SERIAL; /* default is serial port */
|
|
rig->state.serial_rate = rig->caps->serial_rate_max; /* fastest ! */
|
|
rig->state.serial_data_bits = rig->caps->serial_data_bits;
|
|
rig->state.serial_stop_bits = rig->caps->serial_stop_bits;
|
|
rig->state.serial_parity = rig->caps->serial_parity;
|
|
rig->state.serial_handshake = rig->caps->serial_handshake;
|
|
rig->state.timeout = rig->caps->timeout;
|
|
rig->state.retry = rig->caps->retry;
|
|
rig->state.ptt_type = rig->caps->ptt_type;
|
|
rig->state.vfo_comp = 0.0; /* override it with preferences */
|
|
|
|
/*
|
|
* let the backend a chance to setup his private data
|
|
* FIXME: check rig_init() return code
|
|
*/
|
|
if (rig->caps->rig_init != NULL)
|
|
rig->caps->rig_init(rig);
|
|
|
|
return rig;
|
|
}
|
|
|
|
int rig_open(RIG *rig)
|
|
{
|
|
int status;
|
|
|
|
rig_debug(RIG_DEBUG_VERBOSE,"rig:rig_open called \n");
|
|
|
|
if (!rig)
|
|
return -RIG_EINVAL;
|
|
|
|
switch(rig->state.port_type) {
|
|
case RIG_PORT_SERIAL:
|
|
status = serial_open(&rig->state);
|
|
if (status != 0)
|
|
return status;
|
|
break;
|
|
|
|
case RIG_PORT_NETWORK: /* not implemented yet! */
|
|
default:
|
|
return -RIG_ENIMPL;
|
|
}
|
|
|
|
/*
|
|
* Maybe the backend has something to initialize
|
|
* FIXME: check rig_open() return code
|
|
*/
|
|
if (rig->caps->rig_open != NULL)
|
|
rig->caps->rig_open(rig);
|
|
|
|
return RIG_OK;
|
|
}
|
|
|
|
/*
|
|
* Examples of typical rig_* wrapper
|
|
*/
|
|
|
|
/*
|
|
* rig_set_freq
|
|
*
|
|
*/
|
|
|
|
int rig_set_freq(RIG *rig, freq_t freq)
|
|
{
|
|
if (!rig || !rig->caps)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->state.vfo_comp != 0.0)
|
|
freq += (freq_t)(rig->state.vfo_comp * freq);
|
|
|
|
if (rig->caps->set_freq == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->set_freq(rig, freq);
|
|
}
|
|
|
|
/*
|
|
* rig_get_freq
|
|
*
|
|
*/
|
|
|
|
int rig_get_freq(RIG *rig, freq_t *freq)
|
|
{
|
|
int status;
|
|
|
|
if (!rig || !rig->caps || !freq)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->get_freq == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else {
|
|
status = rig->caps->get_freq(rig, freq);
|
|
if (rig->state.vfo_comp != 0.0)
|
|
*freq += (freq_t)(rig->state.vfo_comp * (*freq));
|
|
return status;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* rig_set_mode
|
|
*
|
|
*/
|
|
|
|
int rig_set_mode(RIG *rig, rmode_t mode)
|
|
{
|
|
if (!rig || !rig->caps)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->set_mode == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->set_mode(rig, mode);
|
|
}
|
|
|
|
/*
|
|
* rig_get_mode
|
|
*
|
|
*/
|
|
|
|
int rig_get_mode(RIG *rig, rmode_t *mode)
|
|
{
|
|
if (!rig || !rig->caps || !mode)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->get_mode == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->get_mode(rig, mode);
|
|
}
|
|
|
|
|
|
/*
|
|
* rig_set_vfo
|
|
*
|
|
*/
|
|
|
|
int rig_set_vfo(RIG *rig, vfo_t vfo)
|
|
{
|
|
if (!rig || !rig->caps)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->set_vfo == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->set_vfo(rig, vfo);
|
|
}
|
|
|
|
/*
|
|
* rig_get_vfo
|
|
*
|
|
*/
|
|
|
|
int rig_get_vfo(RIG *rig, vfo_t *vfo)
|
|
{
|
|
if (!rig || !rig->caps || !vfo)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->get_vfo == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->get_vfo(rig, vfo);
|
|
}
|
|
|
|
/*
|
|
* rig_set_ptt
|
|
* Set ptt on/off
|
|
*/
|
|
|
|
int rig_set_ptt(RIG *rig, ptt_t ptt)
|
|
{
|
|
if (!rig || !rig->caps)
|
|
return -RIG_EINVAL;
|
|
|
|
switch (rig->state.ptt_type) {
|
|
case RIG_PTT_RIG:
|
|
if (rig->caps->set_ptt == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->set_ptt(rig, ptt);
|
|
break;
|
|
|
|
case RIG_PTT_SERIAL:
|
|
case RIG_PTT_PARALLEL:
|
|
case RIG_PTT_NONE:
|
|
default:
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
}
|
|
}
|
|
|
|
/*
|
|
* rig_get_ptt
|
|
* Are we on air?
|
|
*/
|
|
|
|
int rig_get_ptt(RIG *rig, ptt_t *ptt)
|
|
{
|
|
if (!rig || !rig->caps || !ptt)
|
|
return -RIG_EINVAL;
|
|
|
|
switch (rig->state.ptt_type) {
|
|
case RIG_PTT_RIG:
|
|
if (rig->caps->get_ptt == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->get_ptt(rig, ptt);
|
|
break;
|
|
|
|
case RIG_PTT_SERIAL:
|
|
case RIG_PTT_PARALLEL:
|
|
case RIG_PTT_NONE:
|
|
default:
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* rig_set_rpt_shift
|
|
* Set the repeater shift
|
|
*/
|
|
|
|
int rig_set_rpt_shift(RIG *rig, rptr_shift_t rptr_shift)
|
|
{
|
|
if (!rig || !rig->caps)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->set_rpt_shift == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->set_rpt_shift(rig, rptr_shift);
|
|
}
|
|
|
|
/*
|
|
* rig_get_rpt_shift
|
|
* Get the current repeater shift
|
|
*/
|
|
|
|
int rig_get_rpt_shift(RIG *rig, rptr_shift_t *rptr_shift)
|
|
{
|
|
if (!rig || !rig->caps || !rptr_shift)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->get_ts == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->get_rpt_shift(rig, rptr_shift);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* rig_set_ts
|
|
* Set the Tuning Step
|
|
*/
|
|
|
|
int rig_set_ts(RIG *rig, unsigned long ts)
|
|
{
|
|
if (!rig || !rig->caps)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->set_ts == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->set_ts(rig, ts);
|
|
}
|
|
|
|
/*
|
|
* rig_get_ts
|
|
* Get the current Tuning Step
|
|
*/
|
|
|
|
int rig_get_ts(RIG *rig, unsigned long *ts)
|
|
{
|
|
if (!rig || !rig->caps || !ts)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->get_ts == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->get_ts(rig, ts);
|
|
}
|
|
|
|
|
|
/*
|
|
* rig_set_power
|
|
* NB: power must be on a [0.0 .. 1.0] scale
|
|
* Approximation and rounding is done by the backend
|
|
*/
|
|
|
|
int rig_set_power(RIG *rig, float power)
|
|
{
|
|
if (!rig || !rig->caps || power<0.0 || power>1.0)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->set_power == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->set_power(rig, power);
|
|
}
|
|
|
|
/*
|
|
* rig_get_power
|
|
* NB: returned power must be on a [0.0 .. 1.0] scale
|
|
*/
|
|
|
|
int rig_get_power(RIG *rig, float *power)
|
|
{
|
|
if (!rig || !rig->caps || !power)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->get_power == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->get_power(rig, power);
|
|
}
|
|
|
|
/*
|
|
* rig_power2mW
|
|
* NB: power must be on a [0.0 .. 1.0] scale, returned value is in mW
|
|
*/
|
|
int rig_power2mW(RIG *rig, unsigned int *mwpower, float power, freq_t freq, mode_t mode)
|
|
{
|
|
const freq_range_t *txrange;
|
|
|
|
if (!rig || !rig->caps || !mwpower || power<0.0 || power>1.0)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->power2mW == NULL) {
|
|
txrange = rig_get_range(rig->caps->tx_range_list, freq, mode);
|
|
if (!txrange) {
|
|
/*
|
|
* freq is not on the tx range!
|
|
*/
|
|
return -RIG_ECONF; /* could be RIG_EINVAL ? */
|
|
}
|
|
*mwpower = (unsigned long)(power*txrange->high_power);
|
|
return RIG_OK;
|
|
} else
|
|
return rig->caps->power2mW(rig, mwpower, power, freq, mode);
|
|
}
|
|
|
|
/*
|
|
* rig_mW2power
|
|
* NB: returned power is on a [0.0 .. 1.0] scale
|
|
*/
|
|
int rig_mW2power(RIG *rig, float *power, unsigned int mwpower, freq_t freq, mode_t mode)
|
|
{
|
|
const freq_range_t *txrange;
|
|
|
|
if (!rig || !rig->caps || !power || mwpower==0)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->mW2power == NULL) {
|
|
txrange = rig_get_range(rig->caps->tx_range_list, freq, mode);
|
|
if (!txrange) {
|
|
/*
|
|
* freq is not on the tx range!
|
|
*/
|
|
return -RIG_ECONF; /* could be RIG_EINVAL ? */
|
|
}
|
|
*power = txrange->high_power/mwpower;
|
|
if (*power > 1.0)
|
|
*power = 1.0;
|
|
return (mwpower>txrange->high_power? RIG_OK : RIG_ETRUNC);
|
|
} else
|
|
return rig->caps->mW2power(rig, power, mwpower, freq, mode);
|
|
}
|
|
|
|
|
|
/*
|
|
* rig_set_volume
|
|
* The volume is specified on a scale from 0.0 to 1.0.
|
|
* 0.0 means the lowest volume, whereas 1.0 is the loudest the rig
|
|
* can do.
|
|
* The backend is responsible for the appropriate conversion (and rounding)
|
|
*/
|
|
|
|
int rig_set_volume(RIG *rig, float vol)
|
|
{
|
|
if (!rig || !rig->caps || vol<0.0 || vol>1.0)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->set_volume == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->set_volume(rig, vol);
|
|
}
|
|
|
|
/*
|
|
* rig_get_volume
|
|
*
|
|
*/
|
|
|
|
int rig_get_volume(RIG *rig, float *vol)
|
|
{
|
|
if (!rig || !rig->caps || !vol)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->get_volume == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->get_volume(rig, vol);
|
|
}
|
|
|
|
/*
|
|
* rig_set_squelch
|
|
*
|
|
*/
|
|
|
|
int rig_set_squelch(RIG *rig, float sql)
|
|
{
|
|
if (!rig || !rig->caps || sql<0.0 || sql>1.0)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->set_squelch == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->set_squelch(rig, sql);
|
|
}
|
|
|
|
/*
|
|
* rig_get_squelch
|
|
* Read squelch condition
|
|
*/
|
|
|
|
int rig_get_squelch(RIG *rig, float *sql)
|
|
{
|
|
if (!rig || !rig->caps || !sql)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->get_squelch == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->get_squelch(rig, sql);
|
|
}
|
|
|
|
/*
|
|
* rig_set_tonesq
|
|
* Set CTCSS.
|
|
* NB: tone is NOT in HZ, but in tenth of Hz!
|
|
* Exemple: If you want to set subaudible tone of 88.5, then pass 885
|
|
* to this function
|
|
* Also, if you want to disable Tone squelch, set tone to 0.
|
|
*/
|
|
|
|
int rig_set_tonesq(RIG *rig, unsigned int tone)
|
|
{
|
|
if (!rig || !rig->caps)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->set_tonesq == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->set_tonesq(rig, tone);
|
|
}
|
|
|
|
/*
|
|
* rig_get_tonesq
|
|
* Read CTCSS
|
|
* NB: tone is NOT in HZ, but in tenth of Hz!
|
|
*/
|
|
|
|
int rig_get_tonesq(RIG *rig, unsigned int *tone)
|
|
{
|
|
if (!rig || !rig->caps || !tone)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->get_tonesq == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->get_tonesq(rig, tone);
|
|
}
|
|
|
|
/*
|
|
* rig_set_tone
|
|
* Set subaudible tone to access a repeater.
|
|
* NB: tone is NOT in HZ, but in tenth of Hz!
|
|
* Exemple: If you want to set subaudible tone of 88.5, then pass 885
|
|
* to this function
|
|
* Also, if you want to disable Tone generation, set tone to 0.
|
|
*/
|
|
|
|
int rig_set_tone(RIG *rig, unsigned int tone)
|
|
{
|
|
if (!rig || !rig->caps)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->set_tone == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->set_tone(rig, tone);
|
|
}
|
|
|
|
/*
|
|
* rig_get_tone
|
|
* Read current subaudible tone to access a repeater.
|
|
* NB: tone is NOT in HZ, but in tenth of Hz!
|
|
*/
|
|
|
|
int rig_get_tone(RIG *rig, unsigned int *tone)
|
|
{
|
|
if (!rig || !rig->caps || !tone)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->get_tone == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->get_tone(rig, tone);
|
|
}
|
|
|
|
|
|
/*
|
|
* rig_get_strength
|
|
* read S-meter level
|
|
* The signal strength in db is returned in pointed strength argument
|
|
*/
|
|
|
|
int rig_get_strength(RIG *rig, int *strength)
|
|
{
|
|
if (!rig || !rig->caps || !strength)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->get_strength == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->get_strength(rig, strength);
|
|
}
|
|
|
|
/*
|
|
* rig_set_poweron
|
|
*/
|
|
|
|
int rig_set_poweron(RIG *rig)
|
|
{
|
|
if (!rig || !rig->caps)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->set_poweron == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->set_poweron(rig);
|
|
}
|
|
|
|
/*
|
|
* rig_set_poweroff
|
|
*/
|
|
|
|
int rig_set_poweroff(RIG *rig)
|
|
{
|
|
if (!rig || !rig->caps)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->set_poweroff == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->set_poweroff(rig);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* more rig_* to come -- FS
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
* Close port
|
|
*/
|
|
int rig_close(RIG *rig)
|
|
{
|
|
rig_debug(RIG_DEBUG_VERBOSE,"rig:rig_close called \n");
|
|
|
|
if (rig == NULL || rig->caps)
|
|
return -RIG_EINVAL;
|
|
|
|
/*
|
|
* Let the backend say 73s to the rig
|
|
*/
|
|
if (rig->caps->rig_close)
|
|
rig->caps->rig_close(rig);
|
|
|
|
if (rig->state.fd != -1) {
|
|
close(rig->state.fd);
|
|
rig->state.fd = -1;
|
|
}
|
|
|
|
return RIG_OK;
|
|
}
|
|
|
|
/*
|
|
* Release a rig struct which port has already been closed
|
|
*/
|
|
int rig_cleanup(RIG *rig)
|
|
{
|
|
rig_debug(RIG_DEBUG_VERBOSE,"rig:rig_cleanup called \n");
|
|
|
|
if (rig == NULL || rig->caps)
|
|
return -RIG_EINVAL;
|
|
|
|
/*
|
|
* basically free up the priv struct
|
|
*/
|
|
if (rig->caps->rig_cleanup)
|
|
rig->caps->rig_cleanup(rig);
|
|
|
|
free(rig);
|
|
|
|
return RIG_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* CAUTION: this is really Experimental, It never worked!!
|
|
* try to guess a rig, can be very buggy! (but fun if it works!)
|
|
* FIXME: finish me and handle nicely errors
|
|
*/
|
|
RIG *rig_probe(const char *port_path)
|
|
{
|
|
RIG *rig;
|
|
int i;
|
|
|
|
for (i = 0; rig_base[i]; i++) {
|
|
if (rig_base[i]->rig_probe != NULL) {
|
|
rig = rig_init(rig_base[i]->rig_model);
|
|
strncpy(rig->state.rig_path, port_path, FILPATHLEN);
|
|
rig_open(rig);
|
|
if (rig && rig_base[i]->rig_probe(rig) == 0) {
|
|
return rig;
|
|
} else {
|
|
rig_close(rig);
|
|
rig_cleanup(rig);
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
* "macro" to check if a rig has a function,
|
|
* example: if (rig_has_func(my_rig, RIG_FUNC_FAGC)) disp_fagc_button();
|
|
*/
|
|
int rig_has_func(RIG *rig, unsigned long func)
|
|
{
|
|
if (!rig || !rig->caps)
|
|
return -1;
|
|
|
|
return (rig->caps->has_func & func);
|
|
}
|
|
|
|
/*
|
|
* rig_set_func
|
|
*/
|
|
|
|
int rig_set_func(RIG *rig, unsigned long func)
|
|
{
|
|
if (!rig || !rig->caps)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->set_func == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->set_func(rig, func);
|
|
}
|
|
|
|
/*
|
|
* rig_get_func
|
|
* Query the setting of function bits set to 1
|
|
* and return their status.
|
|
*/
|
|
|
|
int rig_get_func(RIG *rig, unsigned long *func)
|
|
{
|
|
if (!rig || !rig->caps || !func)
|
|
return -RIG_EINVAL;
|
|
|
|
if (rig->caps->get_func == NULL)
|
|
return -RIG_ENIMPL; /* not implemented */
|
|
else
|
|
return rig->caps->get_func(rig, func);
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Get rig capabilities.
|
|
*
|
|
*/
|
|
|
|
const struct rig_caps *rig_get_caps(rig_model_t rig_model) {
|
|
|
|
int i;
|
|
const struct rig_caps *rc;
|
|
|
|
/* lookup for this rig */
|
|
for (i=0; rig_base[i]; i++) {
|
|
if (rig_base[i]->rig_model == rig_model)
|
|
break;
|
|
}
|
|
if (rig_base[i] == NULL) {
|
|
/* rig not supported, sorry! */
|
|
return NULL;
|
|
}
|
|
|
|
rc = rig_base[i];
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
/*
|
|
* rig_get_range returns a pointer to the freq_range_t
|
|
* concerning the freq/mode args.
|
|
* Works for rx and tx range list as well
|
|
*/
|
|
const freq_range_t *
|
|
rig_get_range(const freq_range_t range_list[], freq_t freq, unsigned long mode)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<FRQRANGESIZ; i++) {
|
|
if (range_list[i].start == 0 && range_list[i].end == 0) {
|
|
return NULL;
|
|
}
|
|
if ((freq >= range_list[i].start && freq <= range_list[i].end) &&
|
|
(range_list[i].modes & mode)) {
|
|
return (&range_list[i]);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|