Reformatted src directory

pull/1/head
Nate Bargmann 2017-08-05 09:09:12 -05:00
rodzic 01bef2d158
commit f76b354588
31 zmienionych plików z 9584 dodań i 7142 usunięć

Wyświetl plik

@ -39,6 +39,7 @@
/* add rig_set_cal(cal_table), rig_get_calstat(rawmin,rawmax,cal_table), */ /* add rig_set_cal(cal_table), rig_get_calstat(rawmin,rawmax,cal_table), */
/** /**
* \brief Convert raw S-meter data to calibated value, according to table * \brief Convert raw S-meter data to calibated value, according to table
* \param rawval input value * \param rawval input value
@ -52,48 +53,55 @@
* If a value is greater or equal to cal_table_t.table[cal_table_t.size-1].raw, * If a value is greater or equal to cal_table_t.table[cal_table_t.size-1].raw,
* rig_raw2val() will return cal_table_t.table[cal_table_t.size-1].val * rig_raw2val() will return cal_table_t.table[cal_table_t.size-1].val
*/ */
float HAMLIB_API rig_raw2val(int rawval, const cal_table_t *cal) float HAMLIB_API rig_raw2val(int rawval, const cal_table_t *cal)
{ {
#ifdef WANT_CHEAP_WNO_FP #ifdef WANT_CHEAP_WNO_FP
int interpolation; int interpolation;
#else #else
float interpolation; float interpolation;
#endif #endif
int i; int i;
/* ASSERT(cal != NULL) */ /* ASSERT(cal != NULL) */
/* ASSERT(cal->size <= MAX_CAL_LENGTH) */ /* ASSERT(cal->size <= MAX_CAL_LENGTH) */
if (cal->size == 0) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return rawval;
for (i=0; i<cal->size; i++) if (cal->size == 0) {
if (rawval < cal->table[i].raw) return rawval;
break; }
if (i==0) for (i = 0; i < cal->size; i++)
return cal->table[0].val; if (rawval < cal->table[i].raw) {
break;
}
if (i>=cal->size) if (i == 0) {
return cal->table[i-1].val; return cal->table[0].val;
}
if (cal->table[i].raw == cal->table[i-1].raw) /* catch divide by 0 error */ if (i >= cal->size) {
return cal->table[i].val; return cal->table[i - 1].val;
}
/* catch divide by 0 error */
if (cal->table[i].raw == cal->table[i - 1].raw) {
return cal->table[i].val;
}
#ifdef WANT_CHEAP_WNO_FP #ifdef WANT_CHEAP_WNO_FP
/* cheap, less accurate, but no fp needed */ /* cheap, less accurate, but no fp needed */
interpolation = ((cal->table[i].raw - rawval) * interpolation = ((cal->table[i].raw - rawval)
(cal->table[i].val - cal->table[i-1].val)) / * (cal->table[i].val - cal->table[i - 1].val))
(cal->table[i].raw - cal->table[i-1].raw); / (cal->table[i].raw - cal->table[i - 1].raw);
return cal->table[i].val - interpolation; return cal->table[i].val - interpolation;
#else #else
interpolation = ((cal->table[i].raw - rawval) * interpolation = ((cal->table[i].raw - rawval)
(float)(cal->table[i].val - cal->table[i-1].val)) / * (float)(cal->table[i].val - cal->table[i - 1].val))
(float)(cal->table[i].raw - cal->table[i-1].raw); / (float)(cal->table[i].raw - cal->table[i - 1].raw);
#endif #endif
return cal->table[i].val - interpolation; return cal->table[i].val - interpolation;
} }
/** @} */ /** @} */

Wyświetl plik

@ -65,7 +65,7 @@
#include <linux/hidraw.h> #include <linux/hidraw.h>
#endif #endif
#include "hamlib/rig.h" #include <hamlib/rig.h>
#include "cm108.h" #include "cm108.h"
@ -74,73 +74,78 @@
* \param port * \param port
* \return file descriptor * \return file descriptor
*/ */
int cm108_open(hamlib_port_t *port) int cm108_open(hamlib_port_t *port)
{ {
int fd; int fd;
rig_debug(RIG_DEBUG_VERBOSE,"cm108:cm108_open called \n"); rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!port->pathname[0]) {
return -RIG_EINVAL;
}
if (!port->pathname[0]) fd = open(port->pathname, O_RDWR);
return -RIG_EINVAL;
fd = open(port->pathname, O_RDWR); if (fd < 0) {
rig_debug(RIG_DEBUG_ERR,
if (fd < 0) { "%s: opening device \"%s\": %s\n",
rig_debug(RIG_DEBUG_ERR, "cm108:Opening device \"%s\": %s\n", port->pathname, strerror(errno)); __func__,
return -RIG_EIO; port->pathname,
} strerror(errno));
return -RIG_EIO;
}
#ifdef HAVE_LINUX_HIDRAW_H #ifdef HAVE_LINUX_HIDRAW_H
// CM108 detection copied from Thomas Sailer's soundmodem code // CM108 detection copied from Thomas Sailer's soundmodem code
rig_debug(RIG_DEBUG_VERBOSE,"cm108:Checking for cm108 (or compatible) device \n"); rig_debug(RIG_DEBUG_VERBOSE,
"%s: checking for cm108 (or compatible) device\n",
__func__);
struct hidraw_devinfo hiddevinfo; struct hidraw_devinfo hiddevinfo;
if (!ioctl(fd, HIDIOCGRAWINFO, &hiddevinfo)
&& ((hiddevinfo.vendor == 0x0d8c
// CM108/109/119/119A
&& ((hiddevinfo.product >= 0x0008
&& hiddevinfo.product <= 0x000f)
|| hiddevinfo.product == 0x013a))
// SSS1621/23
|| (hiddevinfo.vendor == 0x0c76
&& (hiddevinfo.product == 0x1605
|| hiddevinfo.product == 0x1607
|| hiddevinfo.product == 0x160b))))
{
rig_debug(RIG_DEBUG_VERBOSE,
"%s: cm108 compatible device detected\n",
__func__);
} else {
close(fd);
rig_debug(RIG_DEBUG_VERBOSE,
"%s: no cm108 (or compatible) device detected\n",
__func__);
return -RIG_EINVAL;
}
if (!ioctl(fd, HIDIOCGRAWINFO, &hiddevinfo)
&&
(
(hiddevinfo.vendor == 0x0d8c && // CM108/109/119/119A
((hiddevinfo.product >= 0x0008 &&
hiddevinfo.product <= 0x000f) ||
hiddevinfo.product == 0x013a)
)
||
(hiddevinfo.vendor == 0x0c76 && // SSS1621/23
(hiddevinfo.product == 0x1605 ||
hiddevinfo.product == 0x1607 ||
hiddevinfo.product == 0x160b)
)
)
)
{
rig_debug(RIG_DEBUG_VERBOSE,"cm108:cm108 compatible device detected \n");
}
else
{
close(fd);
rig_debug(RIG_DEBUG_VERBOSE,"cm108:No cm108 (or compatible) device detected \n");
return -RIG_EINVAL;
}
#endif #endif
port->fd = fd; port->fd = fd;
return fd; return fd;
} }
/** /**
* \brief Close CM108 HID port * \brief Close CM108 HID port
* \param port * \param port
*/ */
int cm108_close(hamlib_port_t *port) int cm108_close(hamlib_port_t *port)
{ {
rig_debug(RIG_DEBUG_VERBOSE,"cm108:cm108_close called \n"); rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return close(port->fd); return close(port->fd);
} }
/** /**
* \brief Set or unset Push to talk bit on CM108 GPIO * \brief Set or unset Push to talk bit on CM108 GPIO
* \param p * \param p
@ -149,62 +154,70 @@ int cm108_close(hamlib_port_t *port)
*/ */
int cm108_ptt_set(hamlib_port_t *p, ptt_t pttx) int cm108_ptt_set(hamlib_port_t *p, ptt_t pttx)
{ {
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
rig_debug(RIG_DEBUG_VERBOSE,"cm108:cm108_ptt_set called \n"); // For a CM108 USB audio device PTT is wired up to one of the GPIO
// pins. Usually this is GPIO3 (bit 2 of the GPIO register) because it
// is on the corner of the chip package (pin 13) so it's easily accessible.
// Some CM108 chips are epoxy-blobbed onto the PCB, so no GPIO
// pins are accessible. The SSS1623 chips have a different pinout, so
// we make the GPIO bit number configurable.
// For a CM108 USB audio device PTT is wired up to one of the GPIO switch (p->type.ptt) {
// pins. Usually this is GPIO3 (bit 2 of the GPIO register) because it case RIG_PTT_CM108: {
// is on the corner of the chip package (pin 13) so it's easily accessible.
// Some CM108 chips are epoxy-blobbed onto the PCB, so no GPIO
// pins are accessible. The SSS1623 chips have a different pinout, so
// we make the GPIO bit number configurable.
switch(p->type.ptt) { // Build a packet for CM108 HID to turn GPIO bit on or off.
case RIG_PTT_CM108: // Packet is 4 bytes, preceded by a 'report number' byte
{ // 0x00 report number
// Write data packet (from CM108 documentation)
// byte 0: 00xx xxxx Write GPIO
// byte 1: xxxx dcba GPIO3-0 output values (1=high)
// byte 2: xxxx dcba GPIO3-0 data-direction register (1=output)
// byte 3: xxxx xxxx SPDIF
// Build a packet for CM108 HID to turn GPIO bit on or off. rig_debug(RIG_DEBUG_VERBOSE,
// Packet is 4 bytes, preceded by a 'report number' byte "%s: bit number %d to state %d\n",
// 0x00 report number __func__,
// Write data packet (from CM108 documentation) p->parm.cm108.ptt_bitnum,
// byte 0: 00xx xxxx Write GPIO (pttx == RIG_PTT_ON) ? 1 : 0);
// byte 1: xxxx dcba GPIO3-0 output values (1=high)
// byte 2: xxxx dcba GPIO3-0 data-direction register (1=output)
// byte 3: xxxx xxxx SPDIF
rig_debug(RIG_DEBUG_VERBOSE,"cm108:cm108_ptt_set bit number %d to state %d\n", char out_rep[] = {
p->parm.cm108.ptt_bitnum, (pttx == RIG_PTT_ON) ? 1 : 0); 0x00, // report number
// HID output report
0x00,
(pttx == RIG_PTT_ON) ? (1 << p->parm.cm108.ptt_bitnum) : 0, // set GPIO
1 << p->parm.cm108.ptt_bitnum, // Data direction register (1=output)
0x00
};
char out_rep[] = { ssize_t nw;
0x00, // report number
// HID output report
0x00,
(pttx == RIG_PTT_ON) ? (1 << p->parm.cm108.ptt_bitnum) : 0, // set GPIO
1 << p->parm.cm108.ptt_bitnum, // Data direction register (1=output)
0x00
};
ssize_t nw; if (p->fd == -1) {
return -RIG_EINVAL;
}
if (p->fd == -1) // Send the HID packet
return -RIG_EINVAL; nw = write(p->fd, out_rep, sizeof(out_rep));
// Send the HID packet if (nw < 0) {
nw = write(p->fd, out_rep, sizeof(out_rep)); return -RIG_EIO;
if (nw < 0) { }
return -RIG_EIO;
}
return RIG_OK; return RIG_OK;
} }
default:
rig_debug(RIG_DEBUG_ERR,"Unsupported PTT type %d\n", default:
p->type.ptt); rig_debug(RIG_DEBUG_ERR,
return -RIG_EINVAL; "%s: unsupported PTT type %d\n",
} __func__,
return RIG_OK; p->type.ptt);
return -RIG_EINVAL;
}
return RIG_OK;
} }
/** /**
* \brief Get state of Push to Talk from CM108 GPIO * \brief Get state of Push to Talk from CM108 GPIO
* \param p * \param p
@ -213,21 +226,24 @@ int cm108_ptt_set(hamlib_port_t *p, ptt_t pttx)
*/ */
int cm108_ptt_get(hamlib_port_t *p, ptt_t *pttx) int cm108_ptt_get(hamlib_port_t *p, ptt_t *pttx)
{ {
rig_debug(RIG_DEBUG_VERBOSE,"cm108:cm108_ptt_get called \n"); rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
switch(p->type.ptt) { switch (p->type.ptt) {
case RIG_PTT_CM108: case RIG_PTT_CM108: {
{ int status;
int status; return -RIG_ENIMPL;
return -RIG_ENIMPL; return status;
return status; }
}
default: default:
rig_debug(RIG_DEBUG_ERR,"Unsupported PTT type %d\n", rig_debug(RIG_DEBUG_ERR,
p->type.ptt); "%s: unsupported PTT type %d\n",
return -RIG_ENAVAIL; __func__,
} p->type.ptt);
return RIG_OK; return -RIG_ENAVAIL;
}
return RIG_OK;
} }
/** /**
@ -238,26 +254,29 @@ int cm108_ptt_get(hamlib_port_t *p, ptt_t *pttx)
*/ */
int cm108_dcd_get(hamlib_port_t *p, dcd_t *dcdx) int cm108_dcd_get(hamlib_port_t *p, dcd_t *dcdx)
{ {
rig_debug(RIG_DEBUG_VERBOSE,"cm108:cm108_dcd_get called \n"); rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
// On the CM108 and compatible chips the squelch line on the radio is // On the CM108 and compatible chips the squelch line on the radio is
// wired to Volume Down input pin. The state of this pin is reported // wired to Volume Down input pin. The state of this pin is reported
// in HID messages from the CM108 device, but I am not sure how // in HID messages from the CM108 device, but I am not sure how
// to query this state on demand. // to query this state on demand.
switch(p->type.dcd) { switch (p->type.dcd) {
case RIG_DCD_CM108: case RIG_DCD_CM108: {
{ int status;
int status; return -RIG_ENIMPL;
return -RIG_ENIMPL; return status;
return status; }
}
default: default:
rig_debug(RIG_DEBUG_ERR,"Unsupported DCD type %d\n", rig_debug(RIG_DEBUG_ERR,
p->type.dcd); "%s: unsupported DCD type %d\n",
return -RIG_ENAVAIL; __func__,
} p->type.dcd);
return RIG_OK; return -RIG_ENAVAIL;
}
return RIG_OK;
} }
/** @} */ /** @} */

Wyświetl plik

@ -36,12 +36,23 @@ int cm108_ptt_set(hamlib_port_t *p, ptt_t pttx);
int cm108_ptt_get(hamlib_port_t *p, ptt_t *pttx); int cm108_ptt_get(hamlib_port_t *p, ptt_t *pttx);
int cm108_dcd_get(hamlib_port_t *p, dcd_t *dcdx); int cm108_dcd_get(hamlib_port_t *p, dcd_t *dcdx);
extern HAMLIB_EXPORT(int) cm108_write_data(hamlib_port_t *p, unsigned char data); extern HAMLIB_EXPORT(int) cm108_write_data(hamlib_port_t *p,
extern HAMLIB_EXPORT(int) cm108_write_control(hamlib_port_t *p, unsigned char control); unsigned char data);
extern HAMLIB_EXPORT(int) cm108_read_data(hamlib_port_t *p, unsigned char *data);
extern HAMLIB_EXPORT(int) cm108_read_control(hamlib_port_t *p, unsigned char *control); extern HAMLIB_EXPORT(int) cm108_write_control(hamlib_port_t *p,
extern HAMLIB_EXPORT(int) cm108_read_status(hamlib_port_t *p, unsigned char *status); unsigned char control);
extern HAMLIB_EXPORT(int) cm108_read_data(hamlib_port_t *p,
unsigned char *data);
extern HAMLIB_EXPORT(int) cm108_read_control(hamlib_port_t *p,
unsigned char *control);
extern HAMLIB_EXPORT(int) cm108_read_status(hamlib_port_t *p,
unsigned char *status);
extern HAMLIB_EXPORT(int) cm108_lock(hamlib_port_t *p); extern HAMLIB_EXPORT(int) cm108_lock(hamlib_port_t *p);
extern HAMLIB_EXPORT(int) cm108_unlock(hamlib_port_t *p); extern HAMLIB_EXPORT(int) cm108_unlock(hamlib_port_t *p);
__END_DECLS __END_DECLS

1160
src/conf.c

Plik diff jest za duży Load Diff

Wyświetl plik

@ -35,11 +35,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> /* Standard input/output definitions */ #include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */ #include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */ #include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */ #include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */ #include <errno.h> /* Error number definitions */
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
@ -48,16 +48,17 @@
#endif #endif
#include <hamlib/rig.h> #include <hamlib/rig.h>
#include "misc.h" #include "misc.h"
#define DUMP_HEX_WIDTH 16
static int rig_debug_level = RIG_DEBUG_TRACE; static int rig_debug_level = RIG_DEBUG_TRACE;
static FILE *rig_debug_stream; static FILE *rig_debug_stream;
static vprintf_cb_t rig_vprintf_cb; static vprintf_cb_t rig_vprintf_cb;
static rig_ptr_t rig_vprintf_arg; static rig_ptr_t rig_vprintf_arg;
#define DUMP_HEX_WIDTH 16
/** /**
* \param ptr Pointer to memory area * \param ptr Pointer to memory area
* \param size Number of chars to words to dump * \param size Number of chars to words to dump
@ -65,39 +66,42 @@ static rig_ptr_t rig_vprintf_arg;
*/ */
void dump_hex(const unsigned char ptr[], size_t size) void dump_hex(const unsigned char ptr[], size_t size)
{ {
/* example /* example
* 0000 4b 30 30 31 34 35 30 30 30 30 30 30 30 35 30 32 K001450000000502 * 0000 4b 30 30 31 34 35 30 30 30 30 30 30 30 35 30 32 K001450000000502
* 0010 30 30 0d 0a 00.. * 0010 30 30 0d 0a 00..
*/ */
char line[4 + 4 + 3 * DUMP_HEX_WIDTH + 4 + DUMP_HEX_WIDTH + 1]; char line[4 + 4 + 3 * DUMP_HEX_WIDTH + 4 + DUMP_HEX_WIDTH + 1];
unsigned char c; unsigned char c;
int i; int i;
if (!rig_need_debug(RIG_DEBUG_TRACE)) if (!rig_need_debug(RIG_DEBUG_TRACE)) {
return; return;
}
line[sizeof(line) - 1] = '\0'; line[sizeof(line) - 1] = '\0';
for (i = 0; i < size; ++i) { for (i = 0; i < size; ++i) {
if (i % DUMP_HEX_WIDTH == 0) { if (i % DUMP_HEX_WIDTH == 0) {
/* new line */ /* new line */
sprintf(line + 0, "%04x", i); sprintf(line + 0, "%04x", i);
memset(line + 4, ' ', sizeof(line) - 4 - 1); memset(line + 4, ' ', sizeof(line) - 4 - 1);
} }
c = ptr[i]; c = ptr[i];
/* hex print */ /* hex print */
sprintf(line + 8 + 3 * (i % DUMP_HEX_WIDTH), "%02x", c); sprintf(line + 8 + 3 * (i % DUMP_HEX_WIDTH), "%02x", c);
line[8 + 3 * (i % DUMP_HEX_WIDTH) + 2] = ' '; /* no \0 */ line[8 + 3 * (i % DUMP_HEX_WIDTH) + 2] = ' '; /* no \0 */
/* ascii print */ /* ascii print */
line[8 + 3 * DUMP_HEX_WIDTH + 4 + (i % DUMP_HEX_WIDTH)] = (c >= ' ' && c < 0x7f) ? c : '.'; line[8 + 3 * DUMP_HEX_WIDTH + 4 + (i % DUMP_HEX_WIDTH)] = (c >= ' '
&& c < 0x7f) ? c : '.';
/* actually print the line */ /* actually print the line */
if (i + 1 == size || (i && i % DUMP_HEX_WIDTH == DUMP_HEX_WIDTH - 1)) if (i + 1 == size || (i && i % DUMP_HEX_WIDTH == DUMP_HEX_WIDTH - 1)) {
rig_debug(RIG_DEBUG_TRACE, "%s\n", line); rig_debug(RIG_DEBUG_TRACE, "%s\n", line);
} }
}
} }
@ -107,97 +111,114 @@ void dump_hex(const unsigned char ptr[], size_t size)
*/ */
void HAMLIB_API rig_set_debug(enum rig_debug_level_e debug_level) void HAMLIB_API rig_set_debug(enum rig_debug_level_e debug_level)
{ {
rig_debug_level = debug_level; rig_debug_level = debug_level;
} }
/** /**
* \param debug_level * \param debug_level
* \brief Useful for dump_hex, etc. * \brief Useful for dump_hex, etc.
*/ */
int HAMLIB_API rig_need_debug(enum rig_debug_level_e debug_level) int HAMLIB_API rig_need_debug(enum rig_debug_level_e debug_level)
{ {
return (debug_level <= rig_debug_level); return (debug_level <= rig_debug_level);
} }
/** /**
* \param debug_level * \param debug_level
* \param fmt * \param fmt
* \brief Default is debugging messages are done through stderr * \brief Default is debugging messages are done through stderr
*/ */
void HAMLIB_API rig_debug(enum rig_debug_level_e debug_level, const char *fmt, ...) void HAMLIB_API rig_debug(enum rig_debug_level_e debug_level,
const char *fmt, ...)
{ {
va_list ap; va_list ap;
if (!rig_need_debug(debug_level)) if (!rig_need_debug(debug_level)) {
return; return;
}
va_start(ap, fmt); va_start(ap, fmt);
if (rig_vprintf_cb) { if (rig_vprintf_cb) {
rig_vprintf_cb(debug_level, rig_vprintf_arg, fmt, ap);
} else {
if (!rig_debug_stream) {
rig_debug_stream = stderr;
}
rig_vprintf_cb(debug_level, rig_vprintf_arg, fmt, ap); vfprintf(rig_debug_stream, fmt, ap);
fflush(rig_debug_stream);
}
} else { va_end(ap);
if (!rig_debug_stream)
rig_debug_stream = stderr;
vfprintf (rig_debug_stream, fmt, ap);
fflush(rig_debug_stream);
}
va_end(ap);
#ifdef ANDROID #ifdef ANDROID
int a; int a;
va_start(ap, fmt); va_start(ap, fmt);
switch (debug_level){
switch (debug_level) {
// case RIG_DEBUG_NONE: // case RIG_DEBUG_NONE:
case RIG_DEBUG_BUG: case RIG_DEBUG_BUG:
a = ANDROID_LOG_FATAL; break; a = ANDROID_LOG_FATAL;
case RIG_DEBUG_ERR: break;
a = ANDROID_LOG_ERROR; break;
case RIG_DEBUG_WARN: case RIG_DEBUG_ERR:
a = ANDROID_LOG_WARN; break; a = ANDROID_LOG_ERROR;
case RIG_DEBUG_VERBOSE: break;
a = ANDROID_LOG_VERBOSE; break;
case RIG_DEBUG_TRACE: case RIG_DEBUG_WARN:
a = ANDROID_LOG_VERBOSE; break; a = ANDROID_LOG_WARN;
default: break;
a = ANDROID_LOG_DEBUG; break;
case RIG_DEBUG_VERBOSE:
a = ANDROID_LOG_VERBOSE;
break;
case RIG_DEBUG_TRACE:
a = ANDROID_LOG_VERBOSE;
break;
default:
a = ANDROID_LOG_DEBUG;
break;
} }
__android_log_vprint(a, PACKAGE_NAME, fmt, ap); __android_log_vprint(a, PACKAGE_NAME, fmt, ap);
va_end(ap); va_end(ap);
#endif #endif
} }
/** /**
* \brief set callback to handle debug messages * \brief set callback to handle debug messages
* \param cb The callback to install * \param cb The callback to install
* \param arg A Pointer to some private data to pass later on to the callback * \param arg A Pointer to some private data to pass later on to the callback
* *
* Install a callback for \a rig_debug messages. * Install a callback for \a rig_debug messages.
\code \code
int int
rig_message_cb (enum rig_debug_level_e debug_level, rig_message_cb(enum rig_debug_level_e debug_level,
rig_ptr_t user_data, rig_ptr_t user_data,
const char *fmt, const char *fmt,
va_list ap) va_list ap)
{ {
char buf[1024]; char buf[1024];
sprintf (buf, "Message(%s) ", (char*)user_data); sprintf (buf, "Message(%s) ", (char*)user_data);
syslog (LOG_USER, buf); syslog (LOG_USER, buf);
vsprintf (buf, fmt, ap); vsprintf (buf, fmt, ap);
syslog (LOG_USER, buf); syslog (LOG_USER, buf);
return RIG_OK; return RIG_OK;
} }
. . . . . .
char *cookie = "Foo"; char *cookie = "Foo";
rig_set_debug_callback (rig_message_cb, (rig_ptr_t)cookie); rig_set_debug_callback (rig_message_cb, (rig_ptr_t)cookie);
\endcode \endcode
* *
* \return RIG_OK if the operation has been sucessful, otherwise * \return RIG_OK if the operation has been sucessful, otherwise
@ -208,25 +229,26 @@ rig_message_cb (enum rig_debug_level_e debug_level,
*/ */
vprintf_cb_t HAMLIB_API rig_set_debug_callback(vprintf_cb_t cb, rig_ptr_t arg) vprintf_cb_t HAMLIB_API rig_set_debug_callback(vprintf_cb_t cb, rig_ptr_t arg)
{ {
vprintf_cb_t prev_cb = rig_vprintf_cb; vprintf_cb_t prev_cb = rig_vprintf_cb;
rig_vprintf_cb = cb; rig_vprintf_cb = cb;
rig_vprintf_arg = arg; rig_vprintf_arg = arg;
return prev_cb; return prev_cb;
} }
/** /**
* \brief change stderr to some different output * \brief change stderr to some different output
* \param stream The stream to set output to * \param stream The stream to set output to
*/ */
FILE* HAMLIB_API rig_set_debug_file(FILE *stream) FILE * HAMLIB_API rig_set_debug_file(FILE *stream)
{ {
FILE *prev_stream = rig_debug_stream; FILE *prev_stream = rig_debug_stream;
rig_debug_stream = stream; rig_debug_stream = stream;
return prev_stream; return prev_stream;
} }
/** @} */ /** @} */

Wyświetl plik

@ -53,7 +53,6 @@
#include <hamlib/rig.h> #include <hamlib/rig.h>
#include "event.h" #include "event.h"
#if defined(WIN32) && !defined(HAVE_TERMIOS_H) #if defined(WIN32) && !defined(HAVE_TERMIOS_H)
@ -78,8 +77,10 @@ static void sa_sigalrmhandler(int signum);
#endif #endif
#endif #endif
/* This one should be in an include file */ /* This one should be in an include file */
extern int foreach_opened_rig(int (*cfunc)(RIG *, rig_ptr_t),rig_ptr_t data); extern int foreach_opened_rig(int (*cfunc)(RIG *, rig_ptr_t), rig_ptr_t data);
/* /*
* add_trn_rig * add_trn_rig
@ -89,61 +90,80 @@ extern int foreach_opened_rig(int (*cfunc)(RIG *, rig_ptr_t),rig_ptr_t data);
int add_trn_rig(RIG *rig) int add_trn_rig(RIG *rig)
{ {
#ifdef HAVE_SIGACTION #ifdef HAVE_SIGACTION
struct sigaction act; struct sigaction act;
int status; int status;
/* /*
* FIXME: multiple open will register several time SIGIO hndlr * FIXME: multiple open will register several time SIGIO hndlr
*/ */
memset(&act, 0, sizeof(act)); memset(&act, 0, sizeof(act));
#ifdef HAVE_SIGINFO_T #ifdef HAVE_SIGINFO_T
act.sa_sigaction = sa_sigioaction; act.sa_sigaction = sa_sigioaction;
#else #else
act.sa_handler = sa_sigiohandler; act.sa_handler = sa_sigiohandler;
#endif #endif
sigemptyset(&act.sa_mask); sigemptyset(&act.sa_mask);
#if defined(HAVE_SIGINFO_T) && defined(SA_SIGINFO) #if defined(HAVE_SIGINFO_T) && defined(SA_SIGINFO)
act.sa_flags = SA_SIGINFO|SA_RESTART; act.sa_flags = SA_SIGINFO | SA_RESTART;
#else #else
act.sa_flags = SA_RESTART; act.sa_flags = SA_RESTART;
#endif #endif
status = sigaction(SIGIO, &act, &hamlib_trn_oldact); status = sigaction(SIGIO, &act, &hamlib_trn_oldact);
if (status < 0)
rig_debug(RIG_DEBUG_ERR,"%s: sigaction failed: %s\n",
__func__, strerror(errno));
status = fcntl(rig->state.rigport.fd, F_SETOWN, getpid()); if (status < 0) {
if (status < 0) rig_debug(RIG_DEBUG_ERR,
rig_debug(RIG_DEBUG_ERR,"%s: fcntl SETOWN failed: %s\n", "%s: sigaction failed: %s\n",
__func__, strerror(errno)); __func__,
strerror(errno));
}
status = fcntl(rig->state.rigport.fd, F_SETOWN, getpid());
if (status < 0) {
rig_debug(RIG_DEBUG_ERR,
"%s: fcntl SETOWN failed: %s\n",
__func__,
strerror(errno));
}
#if defined(HAVE_SIGINFO_T) && defined(O_ASYNC) #if defined(HAVE_SIGINFO_T) && defined(O_ASYNC)
#ifdef F_SETSIG #ifdef F_SETSIG
status = fcntl(rig->state.rigport.fd, F_SETSIG, SIGIO); status = fcntl(rig->state.rigport.fd, F_SETSIG, SIGIO);
if (status < 0)
rig_debug(RIG_DEBUG_ERR,"%s: fcntl SETSIG failed: %s\n", if (status < 0) {
__func__, strerror(errno)); rig_debug(RIG_DEBUG_ERR,
"%s: fcntl SETSIG failed: %s\n",
__func__,
strerror(errno));
}
#endif #endif
status = fcntl(rig->state.rigport.fd, F_SETFL, O_ASYNC); status = fcntl(rig->state.rigport.fd, F_SETFL, O_ASYNC);
if (status < 0)
rig_debug(RIG_DEBUG_ERR,"%s: fcntl SETASYNC failed: %s\n", if (status < 0) {
__func__, strerror(errno)); rig_debug(RIG_DEBUG_ERR,
"%s: fcntl SETASYNC failed: %s\n",
__func__,
strerror(errno));
}
#else #else
return -RIG_ENIMPL; return -RIG_ENIMPL;
#endif #endif
return RIG_OK; return RIG_OK;
#else #else
return -RIG_ENIMPL; return -RIG_ENIMPL;
#endif /* !HAVE_SIGACTION */ #endif /* !HAVE_SIGACTION */
} }
/* /*
* remove_trn_rig * remove_trn_rig
* not exported in Hamlib API. * not exported in Hamlib API.
@ -152,31 +172,41 @@ int add_trn_rig(RIG *rig)
int remove_trn_rig(RIG *rig) int remove_trn_rig(RIG *rig)
{ {
#ifdef HAVE_SIGACTION #ifdef HAVE_SIGACTION
int status; int status;
/* assert(rig->caps->transceive == RIG_TRN_RIG); */ /* assert(rig->caps->transceive == RIG_TRN_RIG); */
#if defined(HAVE_SIGINFO_T) && defined(O_ASYNC) #if defined(HAVE_SIGINFO_T) && defined(O_ASYNC)
status = fcntl(rig->state.rigport.fd, F_SETFL, 0); status = fcntl(rig->state.rigport.fd, F_SETFL, 0);
if (status < 0)
rig_debug(RIG_DEBUG_ERR,"%s: fcntl SETASYNC failed: %s\n", if (status < 0) {
__func__, strerror(errno)); rig_debug(RIG_DEBUG_ERR,
"%s: fcntl SETASYNC failed: %s\n",
__func__,
strerror(errno));
}
#endif #endif
status = sigaction(SIGIO, &hamlib_trn_oldact, NULL); status = sigaction(SIGIO, &hamlib_trn_oldact, NULL);
if (status < 0)
rig_debug(RIG_DEBUG_ERR,"%s: sigaction failed: %s\n",
__func__, strerror(errno));
return RIG_OK; if (status < 0) {
rig_debug(RIG_DEBUG_ERR,
"%s: sigaction failed: %s\n",
__func__,
strerror(errno));
}
return RIG_OK;
#else #else
return -RIG_ENIMPL; return -RIG_ENIMPL;
#endif /* !HAVE_SIGACTION */ #endif /* !HAVE_SIGACTION */
} }
#ifdef HAVE_SIGACTION #ifdef HAVE_SIGACTION
/* /*
* add_trn_poll_rig * add_trn_poll_rig
* not exported in Hamlib API. * not exported in Hamlib API.
@ -184,36 +214,40 @@ int remove_trn_rig(RIG *rig)
static int add_trn_poll_rig(RIG *rig) static int add_trn_poll_rig(RIG *rig)
{ {
#ifdef HAVE_SIGACTION #ifdef HAVE_SIGACTION
struct sigaction act; struct sigaction act;
int status; int status;
/* /*
* FIXME: multiple open will register several time SIGALRM hndlr * FIXME: multiple open will register several time SIGALRM hndlr
*/ */
memset(&act, 0, sizeof(act)); memset(&act, 0, sizeof(act));
#ifdef HAVE_SIGINFO_T #ifdef HAVE_SIGINFO_T
act.sa_sigaction = sa_sigalrmaction; act.sa_sigaction = sa_sigalrmaction;
#else #else
act.sa_handler = sa_sigalrmhandler; act.sa_handler = sa_sigalrmhandler;
#endif #endif
act.sa_flags = SA_RESTART; act.sa_flags = SA_RESTART;
sigemptyset(&act.sa_mask); sigemptyset(&act.sa_mask);
status = sigaction(SIGALRM, &act, &hamlib_trn_poll_oldact); status = sigaction(SIGALRM, &act, &hamlib_trn_poll_oldact);
if (status < 0)
rig_debug(RIG_DEBUG_ERR,"%s sigaction failed: %s\n",
__func__,
strerror(errno));
return RIG_OK; if (status < 0) {
rig_debug(RIG_DEBUG_ERR,
"%s sigaction failed: %s\n",
__func__,
strerror(errno));
}
return RIG_OK;
#else #else
return -RIG_ENIMPL; return -RIG_ENIMPL;
#endif /* !HAVE_SIGINFO */ #endif /* !HAVE_SIGINFO */
} }
/* /*
* remove_trn_poll_rig * remove_trn_poll_rig
* not exported in Hamlib API. * not exported in Hamlib API.
@ -221,19 +255,22 @@ static int add_trn_poll_rig(RIG *rig)
static int remove_trn_poll_rig(RIG *rig) static int remove_trn_poll_rig(RIG *rig)
{ {
#ifdef HAVE_SIGINFO #ifdef HAVE_SIGINFO
int status; int status;
status = sigaction(SIGALRM, &hamlib_trn_poll_oldact, NULL); status = sigaction(SIGALRM, &hamlib_trn_poll_oldact, NULL);
if (status < 0)
rig_debug(RIG_DEBUG_ERR,"%s sigaction failed: %s\n",
__func__,
strerror(errno));
return RIG_OK; if (status < 0) {
rig_debug(RIG_DEBUG_ERR,
"%s sigaction failed: %s\n",
__func__,
strerror(errno));
}
return RIG_OK;
#else #else
return -RIG_ENIMPL; return -RIG_ENIMPL;
#endif /* !HAVE_SIGINFO */ #endif /* !HAVE_SIGINFO */
} }
@ -246,54 +283,64 @@ static int remove_trn_poll_rig(RIG *rig)
*/ */
static int search_rig_and_decode(RIG *rig, rig_ptr_t data) static int search_rig_and_decode(RIG *rig, rig_ptr_t data)
{ {
fd_set rfds; fd_set rfds;
struct timeval tv; struct timeval tv;
int retval; int retval;
/* /*
* so far, only file oriented ports have event reporting support * so far, only file oriented ports have event reporting support
*/ */
if (rig->state.rigport.type.rig != RIG_PORT_SERIAL || if (rig->state.rigport.type.rig != RIG_PORT_SERIAL
rig->state.rigport.fd == -1) || rig->state.rigport.fd == -1) {
return -1; return -1;
}
/* FIXME: siginfo is not portable, however use it where available */ /* FIXME: siginfo is not portable, however use it where available */
#if 0&&defined(HAVE_SIGINFO_T) #if 0&&defined(HAVE_SIGINFO_T)
siginfo_t *si = (siginfo_t*)data; siginfo_t *si = (siginfo_t *)data;
if (rig->state.rigport.fd != si->si_fd) {
return -1;
}
if (rig->state.rigport.fd != si->si_fd)
return -1;
#else #else
FD_ZERO(&rfds); FD_ZERO(&rfds);
FD_SET(rig->state.rigport.fd, &rfds); FD_SET(rig->state.rigport.fd, &rfds);
/* Read status immediately. */ /* Read status immediately. */
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 0; tv.tv_usec = 0;
/* don't use FIONREAD to detect activity
* since it is less portable than select
* REM: EINTR possible with 0sec timeout? retval==0?
*/
retval = select(rig->state.rigport.fd + 1, &rfds, NULL, NULL, &tv);
if (retval < 0) {
rig_debug(RIG_DEBUG_ERR,
"%s: select: %s\n",
__func__,
strerror(errno));
return -1;
}
/* don't use FIONREAD to detect activity
* since it is less portable than select
* REM: EINTR possible with 0sec timeout? retval==0?
*/
retval = select(rig->state.rigport.fd+1, &rfds, NULL, NULL, &tv);
if (retval < 0) {
rig_debug(RIG_DEBUG_ERR, "search_rig_and_decode: select: %s\n",
strerror(errno));
return -1;
}
#endif #endif
/* /*
* Do not disturb, the backend is currently receiving data * Do not disturb, the backend is currently receiving data
*/ */
if (rig->state.hold_decode) if (rig->state.hold_decode) {
return -1; return -1;
}
if (rig->caps->decode_event) if (rig->caps->decode_event) {
rig->caps->decode_event(rig); rig->caps->decode_event(rig);
}
return 1; /* process each opened rig */ return 1; /* process each opened rig */
} }
/* /*
* This is used by sa_sigio, the SIGALRM handler * This is used by sa_sigio, the SIGALRM handler
* to poll each RIG in RIG_TRN_POLL mode. * to poll each RIG in RIG_TRN_POLL mode.
@ -302,60 +349,71 @@ static int search_rig_and_decode(RIG *rig, rig_ptr_t data)
*/ */
static int search_rig_and_poll(RIG *rig, rig_ptr_t data) static int search_rig_and_poll(RIG *rig, rig_ptr_t data)
{ {
struct rig_state *rs = &rig->state; struct rig_state *rs = &rig->state;
int retval; int retval;
if (rig->state.transceive != RIG_TRN_POLL) if (rig->state.transceive != RIG_TRN_POLL) {
return -1; return -1;
/* }
* Do not disturb, the backend is currently receiving data
*/
if (rig->state.hold_decode)
return -1;
rig->state.hold_decode = 2; /*
* Do not disturb, the backend is currently receiving data
*/
if (rig->state.hold_decode) {
return -1;
}
if (rig->caps->get_vfo && rig->callbacks.vfo_event) { rig->state.hold_decode = 2;
vfo_t vfo = RIG_VFO_CURR;
retval = rig->caps->get_vfo(rig, &vfo); if (rig->caps->get_vfo && rig->callbacks.vfo_event) {
if (retval == RIG_OK) { vfo_t vfo = RIG_VFO_CURR;
if (vfo != rs->current_vfo) {
rig->callbacks.vfo_event(rig, vfo, rig->callbacks.vfo_arg);
}
rs->current_vfo = vfo;
}
}
if (rig->caps->get_freq && rig->callbacks.freq_event) {
freq_t freq;
retval = rig->caps->get_freq(rig, RIG_VFO_CURR, &freq); retval = rig->caps->get_vfo(rig, &vfo);
if (retval == RIG_OK) {
if (freq != rs->current_freq) {
rig->callbacks.freq_event(rig, RIG_VFO_CURR,
freq, rig->callbacks.freq_arg);
}
rs->current_freq = freq;
}
}
if (rig->caps->get_mode && rig->callbacks.mode_event) {
rmode_t rmode;
pbwidth_t width;
retval = rig->caps->get_mode(rig, RIG_VFO_CURR, &rmode, &width); if (retval == RIG_OK) {
if (retval == RIG_OK) { if (vfo != rs->current_vfo) {
if (rmode != rs->current_mode || width != rs->current_width) { rig->callbacks.vfo_event(rig, vfo, rig->callbacks.vfo_arg);
rig->callbacks.mode_event(rig, RIG_VFO_CURR, }
rmode, width, rig->callbacks.mode_arg);
}
rs->current_mode = rmode;
rs->current_width = width;
}
}
rig->state.hold_decode = 0; rs->current_vfo = vfo;
}
}
return 1; /* process each opened rig */ if (rig->caps->get_freq && rig->callbacks.freq_event) {
freq_t freq;
retval = rig->caps->get_freq(rig, RIG_VFO_CURR, &freq);
if (retval == RIG_OK) {
if (freq != rs->current_freq) {
rig->callbacks.freq_event(rig, RIG_VFO_CURR,
freq, rig->callbacks.freq_arg);
}
rs->current_freq = freq;
}
}
if (rig->caps->get_mode && rig->callbacks.mode_event) {
rmode_t rmode;
pbwidth_t width;
retval = rig->caps->get_mode(rig, RIG_VFO_CURR, &rmode, &width);
if (retval == RIG_OK) {
if (rmode != rs->current_mode || width != rs->current_width) {
rig->callbacks.mode_event(rig, RIG_VFO_CURR,
rmode, width, rig->callbacks.mode_arg);
}
rs->current_mode = rmode;
rs->current_width = width;
}
}
rig->state.hold_decode = 0;
return 1; /* process each opened rig */
} }
@ -369,18 +427,18 @@ static int search_rig_and_poll(RIG *rig, rig_ptr_t data)
#ifdef HAVE_SIGINFO_T #ifdef HAVE_SIGINFO_T
static void sa_sigioaction(int signum, siginfo_t *si, rig_ptr_t data) static void sa_sigioaction(int signum, siginfo_t *si, rig_ptr_t data)
{ {
rig_debug(RIG_DEBUG_VERBOSE, "sa_sigioaction: activity detected\n"); rig_debug(RIG_DEBUG_VERBOSE, "%s: activity detected\n", __func__);
foreach_opened_rig(search_rig_and_decode, si); foreach_opened_rig(search_rig_and_decode, si);
} }
#else #else
static void sa_sigiohandler(int signum) static void sa_sigiohandler(int signum)
{ {
rig_debug(RIG_DEBUG_VERBOSE, "sa_sigiohandler: activity detected\n"); rig_debug(RIG_DEBUG_VERBOSE, "%s: activity detected\n", __func__);
foreach_opened_rig(search_rig_and_decode, NULL); foreach_opened_rig(search_rig_and_decode, NULL);
} }
#endif #endif
@ -396,31 +454,32 @@ static void sa_sigiohandler(int signum)
#ifdef HAVE_SIGINFO_T #ifdef HAVE_SIGINFO_T
static void sa_sigalrmaction(int signum, siginfo_t *si, rig_ptr_t data) static void sa_sigalrmaction(int signum, siginfo_t *si, rig_ptr_t data)
{ {
rig_debug(RIG_DEBUG_TRACE, "sa_sigalrmaction entered\n"); rig_debug(RIG_DEBUG_TRACE, "%s entered\n", __func__);
foreach_opened_rig(search_rig_and_poll, si); foreach_opened_rig(search_rig_and_poll, si);
} }
#else #else
static void sa_sigalrmhandler(int signum) static void sa_sigalrmhandler(int signum)
{ {
rig_debug(RIG_DEBUG_TRACE, "sa_sigalrmhandler entered\n"); rig_debug(RIG_DEBUG_TRACE, "%s entered\n", __func__);
foreach_opened_rig(search_rig_and_poll, NULL); foreach_opened_rig(search_rig_and_poll, NULL);
} }
#endif /* !HAVE_SIGINFO_T */ #endif /* !HAVE_SIGINFO_T */
#endif /* HAVE_SIGINFO */ #endif /* HAVE_SIGINFO */
#endif /* !DOC_HIDDEN */ #endif /* !DOC_HIDDEN */
/** /**
* \brief set the callback for freq events * \brief set the callback for freq events
* \param rig The rig handle * \param rig The rig handle
* \param cb The callback to install * \param cb The callback to install
* \param arg A Pointer to some private data to pass later on to the callback * \param arg A Pointer to some private data to pass later on to the callback
* *
* Install a callback for freq events, to be called when in transceive mode. * Install a callback for freq events, to be called when in transceive mode.
* *
@ -430,23 +489,26 @@ static void sa_sigalrmhandler(int signum)
* *
* \sa rig_set_trn() * \sa rig_set_trn()
*/ */
int HAMLIB_API rig_set_freq_callback(RIG *rig, freq_cb_t cb, rig_ptr_t arg) int HAMLIB_API rig_set_freq_callback(RIG *rig, freq_cb_t cb, rig_ptr_t arg)
{ {
if (CHECK_RIG_ARG(rig)) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
rig->callbacks.freq_event = cb; if (CHECK_RIG_ARG(rig)) {
rig->callbacks.freq_arg = arg; return -RIG_EINVAL;
}
return RIG_OK; rig->callbacks.freq_event = cb;
rig->callbacks.freq_arg = arg;
return RIG_OK;
} }
/** /**
* \brief set the callback for mode events * \brief set the callback for mode events
* \param rig The rig handle * \param rig The rig handle
* \param cb The callback to install * \param cb The callback to install
* \param arg A Pointer to some private data to pass later on to the callback * \param arg A Pointer to some private data to pass later on to the callback
* *
* Install a callback for mode events, to be called when in transceive mode. * Install a callback for mode events, to be called when in transceive mode.
* *
@ -456,23 +518,26 @@ int HAMLIB_API rig_set_freq_callback(RIG *rig, freq_cb_t cb, rig_ptr_t arg)
* *
* \sa rig_set_trn() * \sa rig_set_trn()
*/ */
int HAMLIB_API rig_set_mode_callback(RIG *rig, mode_cb_t cb, rig_ptr_t arg) int HAMLIB_API rig_set_mode_callback(RIG *rig, mode_cb_t cb, rig_ptr_t arg)
{ {
if (CHECK_RIG_ARG(rig)) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
rig->callbacks.mode_event = cb; if (CHECK_RIG_ARG(rig)) {
rig->callbacks.mode_arg = arg; return -RIG_EINVAL;
}
return RIG_OK; rig->callbacks.mode_event = cb;
rig->callbacks.mode_arg = arg;
return RIG_OK;
} }
/** /**
* \brief set the callback for vfo events * \brief set the callback for vfo events
* \param rig The rig handle * \param rig The rig handle
* \param cb The callback to install * \param cb The callback to install
* \param arg A Pointer to some private data to pass later on to the callback * \param arg A Pointer to some private data to pass later on to the callback
* *
* Install a callback for vfo events, to be called when in transceive mode. * Install a callback for vfo events, to be called when in transceive mode.
* *
@ -482,23 +547,26 @@ int HAMLIB_API rig_set_mode_callback(RIG *rig, mode_cb_t cb, rig_ptr_t arg)
* *
* \sa rig_set_trn() * \sa rig_set_trn()
*/ */
int HAMLIB_API rig_set_vfo_callback(RIG *rig, vfo_cb_t cb, rig_ptr_t arg) int HAMLIB_API rig_set_vfo_callback(RIG *rig, vfo_cb_t cb, rig_ptr_t arg)
{ {
if (CHECK_RIG_ARG(rig)) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
rig->callbacks.vfo_event = cb; if (CHECK_RIG_ARG(rig)) {
rig->callbacks.vfo_arg = arg; return -RIG_EINVAL;
}
return RIG_OK; rig->callbacks.vfo_event = cb;
rig->callbacks.vfo_arg = arg;
return RIG_OK;
} }
/** /**
* \brief set the callback for ptt events * \brief set the callback for ptt events
* \param rig The rig handle * \param rig The rig handle
* \param cb The callback to install * \param cb The callback to install
* \param arg A Pointer to some private data to pass later on to the callback * \param arg A Pointer to some private data to pass later on to the callback
* *
* Install a callback for ptt events, to be called when in transceive mode. * Install a callback for ptt events, to be called when in transceive mode.
* *
@ -508,23 +576,26 @@ int HAMLIB_API rig_set_vfo_callback(RIG *rig, vfo_cb_t cb, rig_ptr_t arg)
* *
* \sa rig_set_trn() * \sa rig_set_trn()
*/ */
int HAMLIB_API rig_set_ptt_callback(RIG *rig, ptt_cb_t cb, rig_ptr_t arg) int HAMLIB_API rig_set_ptt_callback(RIG *rig, ptt_cb_t cb, rig_ptr_t arg)
{ {
if (CHECK_RIG_ARG(rig)) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
rig->callbacks.ptt_event = cb; if (CHECK_RIG_ARG(rig)) {
rig->callbacks.ptt_arg = arg; return -RIG_EINVAL;
}
return RIG_OK; rig->callbacks.ptt_event = cb;
rig->callbacks.ptt_arg = arg;
return RIG_OK;
} }
/** /**
* \brief set the callback for dcd events * \brief set the callback for dcd events
* \param rig The rig handle * \param rig The rig handle
* \param cb The callback to install * \param cb The callback to install
* \param arg A Pointer to some private data to pass later on to the callback * \param arg A Pointer to some private data to pass later on to the callback
* *
* Install a callback for dcd events, to be called when in transceive mode. * Install a callback for dcd events, to be called when in transceive mode.
* *
@ -534,23 +605,26 @@ int HAMLIB_API rig_set_ptt_callback(RIG *rig, ptt_cb_t cb, rig_ptr_t arg)
* *
* \sa rig_set_trn() * \sa rig_set_trn()
*/ */
int HAMLIB_API rig_set_dcd_callback(RIG *rig, dcd_cb_t cb, rig_ptr_t arg) int HAMLIB_API rig_set_dcd_callback(RIG *rig, dcd_cb_t cb, rig_ptr_t arg)
{ {
if (CHECK_RIG_ARG(rig)) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
rig->callbacks.dcd_event = cb; if (CHECK_RIG_ARG(rig)) {
rig->callbacks.dcd_arg = arg; return -RIG_EINVAL;
}
return RIG_OK; rig->callbacks.dcd_event = cb;
rig->callbacks.dcd_arg = arg;
return RIG_OK;
} }
/** /**
* \brief set the callback for pipelined tuning module * \brief set the callback for pipelined tuning module
* \param rig The rig handle * \param rig The rig handle
* \param cb The callback to install * \param cb The callback to install
* \param arg A Pointer to some private data to pass later on to the callback * \param arg A Pointer to some private data to pass later on to the callback
* used to maintain state during pipelined tuning. * used to maintain state during pipelined tuning.
* *
* Install a callback for pipelined tuning module, to be called when the * Install a callback for pipelined tuning module, to be called when the
@ -562,22 +636,25 @@ int HAMLIB_API rig_set_dcd_callback(RIG *rig, dcd_cb_t cb, rig_ptr_t arg)
* *
* \sa rig_set_trn() * \sa rig_set_trn()
*/ */
int HAMLIB_API rig_set_pltune_callback(RIG *rig, pltune_cb_t cb, rig_ptr_t arg) int HAMLIB_API rig_set_pltune_callback(RIG *rig, pltune_cb_t cb, rig_ptr_t arg)
{ {
if (CHECK_RIG_ARG(rig)) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
rig->callbacks.pltune = cb; if (CHECK_RIG_ARG(rig)) {
rig->callbacks.pltune_arg = arg; return -RIG_EINVAL;
}
return RIG_OK; rig->callbacks.pltune = cb;
rig->callbacks.pltune_arg = arg;
return RIG_OK;
} }
/** /**
* \brief control the transceive mode * \brief control the transceive mode
* \param rig The rig handle * \param rig The rig handle
* \param trn The transceive status to set to * \param trn The transceive status to set to
* *
* Enable/disable the transceive handling of a rig and kick off async mode. * Enable/disable the transceive handling of a rig and kick off async mode.
* *
@ -587,111 +664,127 @@ int HAMLIB_API rig_set_pltune_callback(RIG *rig, pltune_cb_t cb, rig_ptr_t arg)
* *
* \sa rig_get_trn() * \sa rig_get_trn()
*/ */
int HAMLIB_API rig_set_trn(RIG *rig, int trn) int HAMLIB_API rig_set_trn(RIG *rig, int trn)
{ {
const struct rig_caps *caps; const struct rig_caps *caps;
int retcode = RIG_OK; int retcode = RIG_OK;
#ifdef HAVE_SETITIMER #ifdef HAVE_SETITIMER
struct itimerval value; struct itimerval value;
#endif #endif
if (CHECK_RIG_ARG(rig)) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rig->caps; if (CHECK_RIG_ARG(rig)) {
return -RIG_EINVAL;
}
/* detect whether tranceive is active already */ caps = rig->caps;
if (trn != RIG_TRN_OFF && rig->state.transceive != RIG_TRN_OFF) {
if (trn == rig->state.transceive) {
return RIG_OK;
} else {
/* when going POLL<->RIG, transtition to OFF */
retcode = rig_set_trn(rig, RIG_TRN_OFF);
if (retcode != RIG_OK)
return retcode;
}
}
switch (trn) { /* detect whether tranceive is active already */
case RIG_TRN_RIG: if (trn != RIG_TRN_OFF && rig->state.transceive != RIG_TRN_OFF) {
if (caps->transceive != RIG_TRN_RIG) if (trn == rig->state.transceive) {
return -RIG_ENAVAIL; return RIG_OK;
} else {
/* when going POLL<->RIG, transtition to OFF */
retcode = rig_set_trn(rig, RIG_TRN_OFF);
retcode = add_trn_rig(rig); if (retcode != RIG_OK) {
/* some protocols (e.g. CI-V's) offer no way return retcode;
* to turn on/off the transceive mode */ }
if (retcode == RIG_OK && caps->set_trn) { }
retcode = caps->set_trn(rig, RIG_TRN_RIG); }
}
break;
case RIG_TRN_POLL: switch (trn) {
case RIG_TRN_RIG:
if (caps->transceive != RIG_TRN_RIG) {
return -RIG_ENAVAIL;
}
retcode = add_trn_rig(rig);
/* some protocols (e.g. CI-V's) offer no way
* to turn on/off the transceive mode */
if (retcode == RIG_OK && caps->set_trn) {
retcode = caps->set_trn(rig, RIG_TRN_RIG);
}
break;
case RIG_TRN_POLL:
#ifdef HAVE_SETITIMER #ifdef HAVE_SETITIMER
add_trn_poll_rig(rig); add_trn_poll_rig(rig);
/* install handler here */
value.it_value.tv_sec = 0;
value.it_value.tv_usec = rig->state.poll_interval * 1000;
value.it_interval.tv_sec = 0;
value.it_interval.tv_usec = rig->state.poll_interval * 1000;
retcode = setitimer(ITIMER_REAL, &value, NULL);
if (retcode == -1) {
rig_debug(RIG_DEBUG_ERR,
"%s: setitimer: %s\n",
__func__,
strerror(errno));
remove_trn_poll_rig(rig);
return -RIG_EINTERNAL;
}
/* install handler here */
value.it_value.tv_sec = 0;
value.it_value.tv_usec = rig->state.poll_interval*1000;
value.it_interval.tv_sec = 0;
value.it_interval.tv_usec = rig->state.poll_interval*1000;
retcode = setitimer(ITIMER_REAL, &value, NULL);
if (retcode == -1) {
rig_debug(RIG_DEBUG_ERR, "%s: setitimer: %s\n",
__func__,
strerror(errno));
remove_trn_poll_rig(rig);
return -RIG_EINTERNAL;
}
#else #else
return -RIG_ENAVAIL; return -RIG_ENAVAIL;
#endif #endif
break; break;
case RIG_TRN_OFF: case RIG_TRN_OFF:
if (rig->state.transceive == RIG_TRN_POLL) { if (rig->state.transceive == RIG_TRN_POLL) {
#ifdef HAVE_SETITIMER #ifdef HAVE_SETITIMER
retcode = remove_trn_poll_rig(rig); retcode = remove_trn_poll_rig(rig);
value.it_value.tv_sec = 0; value.it_value.tv_sec = 0;
value.it_value.tv_usec = 0; value.it_value.tv_usec = 0;
value.it_interval.tv_sec = 0; value.it_interval.tv_sec = 0;
value.it_interval.tv_usec = 0; value.it_interval.tv_usec = 0;
retcode = setitimer(ITIMER_REAL, &value, NULL);
if (retcode == -1) {
rig_debug(RIG_DEBUG_ERR, "%s: setitimer: %s\n",
__func__,
strerror(errno));
return -RIG_EINTERNAL;
}
retcode = setitimer(ITIMER_REAL, &value, NULL);
if (retcode == -1) {
rig_debug(RIG_DEBUG_ERR, "%s: setitimer: %s\n",
__func__,
strerror(errno));
return -RIG_EINTERNAL;
}
#else #else
return -RIG_ENAVAIL; return -RIG_ENAVAIL;
#endif #endif
} else if (rig->state.transceive == RIG_TRN_RIG) { } else if (rig->state.transceive == RIG_TRN_RIG) {
retcode = remove_trn_rig(rig); retcode = remove_trn_rig(rig);
if (caps->set_trn && caps->transceive == RIG_TRN_RIG) {
retcode = caps->set_trn(rig, RIG_TRN_OFF);
}
}
break;
default: if (caps->set_trn && caps->transceive == RIG_TRN_RIG) {
return -RIG_EINVAL; retcode = caps->set_trn(rig, RIG_TRN_OFF);
} }
}
if (retcode == RIG_OK) break;
rig->state.transceive = trn;
return retcode; default:
return -RIG_EINVAL;
}
if (retcode == RIG_OK) {
rig->state.transceive = trn;
}
return retcode;
} }
/** /**
* \brief get the current transceive mode * \brief get the current transceive mode
* \param rig The rig handle * \param rig The rig handle
* \param trn The location where to store the current transceive mode * \param trn The location where to store the current transceive mode
* *
* Retrieves the current status of the transceive mode, i.e. if radio * Retrieves the current status of the transceive mode, i.e. if radio
* sends new status automatically when some changes happened on the radio. * sends new status automatically when some changes happened on the radio.
@ -704,14 +797,18 @@ int HAMLIB_API rig_set_trn(RIG *rig, int trn)
*/ */
int HAMLIB_API rig_get_trn(RIG *rig, int *trn) int HAMLIB_API rig_get_trn(RIG *rig, int *trn)
{ {
if (CHECK_RIG_ARG(rig) || !trn) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
if (rig->caps->get_trn != NULL) if (CHECK_RIG_ARG(rig) || !trn) {
return rig->caps->get_trn(rig, trn); return -RIG_EINVAL;
}
*trn = rig->state.transceive; if (rig->caps->get_trn != NULL) {
return RIG_OK; return rig->caps->get_trn(rig, trn);
}
*trn = rig->state.transceive;
return RIG_OK;
} }
/** @} */ /** @} */

148
src/ext.c
Wyświetl plik

@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
*/ */
/** /**
* \addtogroup rig * \addtogroup rig
* @{ * @{
@ -48,7 +49,6 @@
#include "token.h" #include "token.h"
/** /**
* \param rig The rig handle * \param rig The rig handle
* \param cfunc callback function of each extlevel * \param cfunc callback function of each extlevel
@ -58,25 +58,37 @@
* A zero value means a normal end of iteration, and a negative value an abnormal end, * A zero value means a normal end of iteration, and a negative value an abnormal end,
* which will be the return value of rig_ext_level_foreach. * which will be the return value of rig_ext_level_foreach.
*/ */
int HAMLIB_API rig_ext_level_foreach(RIG *rig, int (*cfunc)(RIG *, const struct confparams *, rig_ptr_t), rig_ptr_t data) int HAMLIB_API rig_ext_level_foreach(RIG *rig,
int (*cfunc)(RIG *,
const struct confparams *,
rig_ptr_t),
rig_ptr_t data)
{ {
const struct confparams *cfp; const struct confparams *cfp;
int ret; int ret;
if (!rig || !rig->caps || !cfunc) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
for (cfp = rig->caps->extlevels; cfp && cfp->name; cfp++) { if (!rig || !rig->caps || !cfunc) {
ret = (*cfunc)(rig, cfp, data); return -RIG_EINVAL;
if (ret == 0) }
return RIG_OK;
if (ret < 0)
return ret;
}
return RIG_OK; for (cfp = rig->caps->extlevels; cfp && cfp->name; cfp++) {
ret = (*cfunc)(rig, cfp, data);
if (ret == 0) {
return RIG_OK;
}
if (ret < 0) {
return ret;
}
}
return RIG_OK;
} }
/** /**
* \param rig The rig handle * \param rig The rig handle
* \param cfunc callback function of each extparm * \param cfunc callback function of each extparm
@ -86,25 +98,37 @@ int HAMLIB_API rig_ext_level_foreach(RIG *rig, int (*cfunc)(RIG *, const struct
* A zero value means a normal end of iteration, and a negative value an abnormal end, * A zero value means a normal end of iteration, and a negative value an abnormal end,
* which will be the return value of rig_ext_parm_foreach. * which will be the return value of rig_ext_parm_foreach.
*/ */
int HAMLIB_API rig_ext_parm_foreach(RIG *rig, int (*cfunc)(RIG *, const struct confparams *, rig_ptr_t), rig_ptr_t data) int HAMLIB_API rig_ext_parm_foreach(RIG *rig,
int (*cfunc)(RIG *,
const struct confparams *,
rig_ptr_t),
rig_ptr_t data)
{ {
const struct confparams *cfp; const struct confparams *cfp;
int ret; int ret;
if (!rig || !rig->caps || !cfunc) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
for (cfp = rig->caps->extparms; cfp && cfp->name; cfp++) { if (!rig || !rig->caps || !cfunc) {
ret = (*cfunc)(rig, cfp, data); return -RIG_EINVAL;
if (ret == 0) }
return RIG_OK;
if (ret < 0)
return ret;
}
return RIG_OK; for (cfp = rig->caps->extparms; cfp && cfp->name; cfp++) {
ret = (*cfunc)(rig, cfp, data);
if (ret == 0) {
return RIG_OK;
}
if (ret < 0) {
return ret;
}
}
return RIG_OK;
} }
/** /**
* \param rig * \param rig
* \param name * \param name
@ -118,20 +142,28 @@ int HAMLIB_API rig_ext_parm_foreach(RIG *rig, int (*cfunc)(RIG *, const struct c
*/ */
const struct confparams * HAMLIB_API rig_ext_lookup(RIG *rig, const char *name) const struct confparams * HAMLIB_API rig_ext_lookup(RIG *rig, const char *name)
{ {
const struct confparams *cfp; const struct confparams *cfp;
if (!rig || !rig->caps) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return NULL;
for (cfp = rig->caps->extlevels; cfp && cfp->name; cfp++) if (!rig || !rig->caps) {
if (!strcmp(cfp->name, name)) return NULL;
return cfp; }
for (cfp = rig->caps->extparms; cfp && cfp->name; cfp++)
if (!strcmp(cfp->name, name)) for (cfp = rig->caps->extlevels; cfp && cfp->name; cfp++)
return cfp; if (!strcmp(cfp->name, name)) {
return NULL; return cfp;
}
for (cfp = rig->caps->extparms; cfp && cfp->name; cfp++)
if (!strcmp(cfp->name, name)) {
return cfp;
}
return NULL;
} }
/** /**
* \param rig * \param rig
* \param token * \param token
@ -143,20 +175,28 @@ const struct confparams * HAMLIB_API rig_ext_lookup(RIG *rig, const char *name)
*/ */
const struct confparams * HAMLIB_API rig_ext_lookup_tok(RIG *rig, token_t token) const struct confparams * HAMLIB_API rig_ext_lookup_tok(RIG *rig, token_t token)
{ {
const struct confparams *cfp; const struct confparams *cfp;
if (!rig || !rig->caps) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return NULL;
for (cfp = rig->caps->extlevels; cfp && cfp->token; cfp++) if (!rig || !rig->caps) {
if (cfp->token == token) return NULL;
return cfp; }
for (cfp = rig->caps->extparms; cfp && cfp->token; cfp++)
if (cfp->token == token) for (cfp = rig->caps->extlevels; cfp && cfp->token; cfp++)
return cfp; if (cfp->token == token) {
return NULL; return cfp;
}
for (cfp = rig->caps->extparms; cfp && cfp->token; cfp++)
if (cfp->token == token) {
return cfp;
}
return NULL;
} }
/** /**
* \param rig * \param rig
* \param name * \param name
@ -164,13 +204,17 @@ const struct confparams * HAMLIB_API rig_ext_lookup_tok(RIG *rig, token_t token)
*/ */
token_t HAMLIB_API rig_ext_token_lookup(RIG *rig, const char *name) token_t HAMLIB_API rig_ext_token_lookup(RIG *rig, const char *name)
{ {
const struct confparams *cfp; const struct confparams *cfp;
cfp = rig_ext_lookup(rig, name); rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!cfp)
return RIG_CONF_END;
return cfp->token; cfp = rig_ext_lookup(rig, name);
if (!cfp) {
return RIG_CONF_END;
}
return cfp->token;
} }
/** @} */ /** @} */

Wyświetl plik

@ -19,8 +19,6 @@
* *
*/ */
#include "gpio.h"
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
@ -28,74 +26,101 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include "gpio.h"
int gpio_open(hamlib_port_t *port, int on_value) int gpio_open(hamlib_port_t *port, int on_value)
{ {
char pathname[FILPATHLEN]; char pathname[FILPATHLEN];
FILE *fexp, *fdir; FILE *fexp, *fdir;
int fd; int fd;
port->parm.gpio.on_value = on_value; port->parm.gpio.on_value = on_value;
snprintf(pathname, FILPATHLEN, "/sys/class/gpio/export");
fexp = fopen(pathname, "w");
if (!fexp) {
rig_debug(RIG_DEBUG_ERR, "Export GPIO%s (using %s): %s\n",
port->pathname, pathname, strerror(errno));
return -RIG_EIO;
}
fprintf(fexp, "%s\n", port->pathname);
fclose(fexp);
snprintf(pathname, FILPATHLEN, "/sys/class/gpio/gpio%s/direction", port->pathname); snprintf(pathname, FILPATHLEN, "/sys/class/gpio/export");
fdir = fopen(pathname, "w"); fexp = fopen(pathname, "w");
if (!fdir) {
rig_debug(RIG_DEBUG_ERR, "GPIO%s direction (using %s): %s\n",
port->pathname, pathname, strerror(errno));
return -RIG_EIO;
}
fprintf(fdir, "out\n");
fclose(fdir);
snprintf(pathname, FILPATHLEN, "/sys/class/gpio/gpio%s/value", port->pathname); if (!fexp) {
fd = open(pathname, O_WRONLY); rig_debug(RIG_DEBUG_ERR,
if (fd < 0) { "Export GPIO%s (using %s): %s\n",
rig_debug(RIG_DEBUG_ERR, "GPIO%s opening value file %s: %s\n", port->pathname,
port->pathname, pathname, strerror(errno)); pathname,
return -RIG_EIO; strerror(errno));
} return -RIG_EIO;
}
port->fd = fd; fprintf(fexp, "%s\n", port->pathname);
return fd; fclose(fexp);
snprintf(pathname,
FILPATHLEN,
"/sys/class/gpio/gpio%s/direction",
port->pathname);
fdir = fopen(pathname, "w");
if (!fdir) {
rig_debug(RIG_DEBUG_ERR,
"GPIO%s direction (using %s): %s\n",
port->pathname,
pathname,
strerror(errno));
return -RIG_EIO;
}
fprintf(fdir, "out\n");
fclose(fdir);
snprintf(pathname,
FILPATHLEN,
"/sys/class/gpio/gpio%s/value",
port->pathname);
fd = open(pathname, O_WRONLY);
if (fd < 0) {
rig_debug(RIG_DEBUG_ERR,
"GPIO%s opening value file %s: %s\n",
port->pathname,
pathname,
strerror(errno));
return -RIG_EIO;
}
port->fd = fd;
return fd;
} }
int gpio_close(hamlib_port_t *port) int gpio_close(hamlib_port_t *port)
{ {
return close(port->fd); return close(port->fd);
} }
int gpio_ptt_set(hamlib_port_t *port, ptt_t pttx) int gpio_ptt_set(hamlib_port_t *port, ptt_t pttx)
{ {
char *val; char *val;
port->parm.gpio.value = pttx != RIG_PTT_OFF; port->parm.gpio.value = pttx != RIG_PTT_OFF;
if ((port->parm.gpio.value && port->parm.gpio.on_value) || if ((port->parm.gpio.value && port->parm.gpio.on_value)
(!port->parm.gpio.value && !port->parm.gpio.on_value)) { || (!port->parm.gpio.value && !port->parm.gpio.on_value)) {
val = "1\n"; val = "1\n";
} else { } else {
val = "0\n"; val = "0\n";
} }
if (write(port->fd, val, strlen(val)) <= 0) if (write(port->fd, val, strlen(val)) <= 0) {
return -RIG_EIO; return -RIG_EIO;
return RIG_OK; }
return RIG_OK;
} }
int gpio_ptt_get(hamlib_port_t *port, ptt_t *pttx) int gpio_ptt_get(hamlib_port_t *port, ptt_t *pttx)
{ {
if (port->parm.gpio.value) if (port->parm.gpio.value) {
return RIG_PTT_ON; return RIG_PTT_ON;
else } else {
return RIG_PTT_OFF; return RIG_PTT_OFF;
}
} }

Wyświetl plik

@ -31,86 +31,86 @@
* everything at compile time. * everything at compile time.
* *
* struct rig_caps foo = { * struct rig_caps foo = {
* .level_gran = { [LVL_PREAMP] = { .min = 0, .max = 20, .step = 10 } }, * .level_gran = { [LVL_PREAMP] = { .min = 0, .max = 20, .step = 10 } },
* } * }
* *
* Of course, it can't work with setting2idx_builtin(RIG_LEVEL_XX|RIG_LEVEL_YY) * Of course, it can't work with setting2idx_builtin(RIG_LEVEL_XX|RIG_LEVEL_YY)
*/ */
#define setting2idx_builtin(s) ((s)==(1<<0)?0: \ #define setting2idx_builtin(s) ((s)==(1<<0)?0: \
(s)==(1<<1)?1: \ (s)==(1<<1)?1: \
(s)==(1<<2)?2: \ (s)==(1<<2)?2: \
(s)==(1<<3)?3: \ (s)==(1<<3)?3: \
(s)==(1<<4)?4: \ (s)==(1<<4)?4: \
(s)==(1<<5)?5: \ (s)==(1<<5)?5: \
(s)==(1<<6)?6: \ (s)==(1<<6)?6: \
(s)==(1<<7)?7: \ (s)==(1<<7)?7: \
(s)==(1<<8)?8: \ (s)==(1<<8)?8: \
(s)==(1<<9)?9: \ (s)==(1<<9)?9: \
(s)==(1<<10)?10: \ (s)==(1<<10)?10: \
(s)==(1<<11)?11: \ (s)==(1<<11)?11: \
(s)==(1<<12)?12: \ (s)==(1<<12)?12: \
(s)==(1<<13)?13: \ (s)==(1<<13)?13: \
(s)==(1<<14)?14: \ (s)==(1<<14)?14: \
(s)==(1<<15)?15: \ (s)==(1<<15)?15: \
(s)==(1<<16)?16: \ (s)==(1<<16)?16: \
(s)==(1<<17)?17: \ (s)==(1<<17)?17: \
(s)==(1<<18)?18: \ (s)==(1<<18)?18: \
(s)==(1<<19)?19: \ (s)==(1<<19)?19: \
(s)==(1<<20)?20: \ (s)==(1<<20)?20: \
(s)==(1<<21)?21: \ (s)==(1<<21)?21: \
(s)==(1<<22)?22: \ (s)==(1<<22)?22: \
(s)==(1<<23)?23: \ (s)==(1<<23)?23: \
(s)==(1<<24)?24: \ (s)==(1<<24)?24: \
(s)==(1<<25)?25: \ (s)==(1<<25)?25: \
(s)==(1<<26)?26: \ (s)==(1<<26)?26: \
(s)==(1<<27)?27: \ (s)==(1<<27)?27: \
(s)==(1<<28)?28: \ (s)==(1<<28)?28: \
(s)==(1<<29)?29: \ (s)==(1<<29)?29: \
(s)==(1<<30)?30: \ (s)==(1<<30)?30: \
(s)==(1<<31)?31: \ (s)==(1<<31)?31: \
0 \ 0 \
) )
#define LVL_PREAMP setting2idx_builtin(RIG_LEVEL_PREAMP) #define LVL_PREAMP setting2idx_builtin(RIG_LEVEL_PREAMP)
#define LVL_ATT setting2idx_builtin(RIG_LEVEL_ATT) #define LVL_ATT setting2idx_builtin(RIG_LEVEL_ATT)
#define LVL_VOX setting2idx_builtin(RIG_LEVEL_VOX) #define LVL_VOX setting2idx_builtin(RIG_LEVEL_VOX)
#define LVL_AF setting2idx_builtin(RIG_LEVEL_AF) #define LVL_AF setting2idx_builtin(RIG_LEVEL_AF)
#define LVL_RF setting2idx_builtin(RIG_LEVEL_RF) #define LVL_RF setting2idx_builtin(RIG_LEVEL_RF)
#define LVL_SQL setting2idx_builtin(RIG_LEVEL_SQL) #define LVL_SQL setting2idx_builtin(RIG_LEVEL_SQL)
#define LVL_IF setting2idx_builtin(RIG_LEVEL_IF) #define LVL_IF setting2idx_builtin(RIG_LEVEL_IF)
#define LVL_APF setting2idx_builtin(RIG_LEVEL_APF) #define LVL_APF setting2idx_builtin(RIG_LEVEL_APF)
#define LVL_NR setting2idx_builtin(RIG_LEVEL_NR) #define LVL_NR setting2idx_builtin(RIG_LEVEL_NR)
#define LVL_PBT_IN setting2idx_builtin(RIG_LEVEL_PBT_IN) #define LVL_PBT_IN setting2idx_builtin(RIG_LEVEL_PBT_IN)
#define LVL_PBT_OUT setting2idx_builtin(RIG_LEVEL_PBT_OUT) #define LVL_PBT_OUT setting2idx_builtin(RIG_LEVEL_PBT_OUT)
#define LVL_CWPITCH setting2idx_builtin(RIG_LEVEL_CWPITCH) #define LVL_CWPITCH setting2idx_builtin(RIG_LEVEL_CWPITCH)
#define LVL_RFPOWER setting2idx_builtin(RIG_LEVEL_RFPOWER) #define LVL_RFPOWER setting2idx_builtin(RIG_LEVEL_RFPOWER)
#define LVL_MICGAIN setting2idx_builtin(RIG_LEVEL_MICGAIN) #define LVL_MICGAIN setting2idx_builtin(RIG_LEVEL_MICGAIN)
#define LVL_KEYSPD setting2idx_builtin(RIG_LEVEL_KEYSPD) #define LVL_KEYSPD setting2idx_builtin(RIG_LEVEL_KEYSPD)
#define LVL_NOTCHF setting2idx_builtin(RIG_LEVEL_NOTCHF) #define LVL_NOTCHF setting2idx_builtin(RIG_LEVEL_NOTCHF)
#define LVL_COMP setting2idx_builtin(RIG_LEVEL_COMP) #define LVL_COMP setting2idx_builtin(RIG_LEVEL_COMP)
#define LVL_AGC setting2idx_builtin(RIG_LEVEL_AGC) #define LVL_AGC setting2idx_builtin(RIG_LEVEL_AGC)
#define LVL_BKINDL setting2idx_builtin(RIG_LEVEL_BKINDL) #define LVL_BKINDL setting2idx_builtin(RIG_LEVEL_BKINDL)
#define LVL_BALANCE setting2idx_builtin(RIG_LEVEL_BALANCE) #define LVL_BALANCE setting2idx_builtin(RIG_LEVEL_BALANCE)
#define LVL_METER setting2idx_builtin(RIG_LEVEL_METER) #define LVL_METER setting2idx_builtin(RIG_LEVEL_METER)
#define LVL_VOXGAIN setting2idx_builtin(RIG_LEVEL_VOXGAIN) #define LVL_VOXGAIN setting2idx_builtin(RIG_LEVEL_VOXGAIN)
#define LVL_VOXDELAY setting2idx_builtin(RIG_LEVEL_VOXDELAY) #define LVL_VOXDELAY setting2idx_builtin(RIG_LEVEL_VOXDELAY)
#define LVL_ANTIVOX setting2idx_builtin(RIG_LEVEL_ANTIVOX) #define LVL_ANTIVOX setting2idx_builtin(RIG_LEVEL_ANTIVOX)
#define LVL_RAWSTR setting2idx_builtin(RIG_LEVEL_RAWSTR) #define LVL_RAWSTR setting2idx_builtin(RIG_LEVEL_RAWSTR)
#define LVL_SQLSTAT setting2idx_builtin(RIG_LEVEL_SQLSTAT) #define LVL_SQLSTAT setting2idx_builtin(RIG_LEVEL_SQLSTAT)
#define LVL_SWR setting2idx_builtin(RIG_LEVEL_SWR) #define LVL_SWR setting2idx_builtin(RIG_LEVEL_SWR)
#define LVL_ALC setting2idx_builtin(RIG_LEVEL_ALC) #define LVL_ALC setting2idx_builtin(RIG_LEVEL_ALC)
#define LVL_STRENGTH setting2idx_builtin(RIG_LEVEL_STRENGTH) #define LVL_STRENGTH setting2idx_builtin(RIG_LEVEL_STRENGTH)
/*#define LVL_BWC setting2idx_builtin(RIG_LEVEL_BWC)*/ /*#define LVL_BWC setting2idx_builtin(RIG_LEVEL_BWC)*/
#define PARM_ANN setting2idx_builtin(RIG_PARM_ANN) #define PARM_ANN setting2idx_builtin(RIG_PARM_ANN)
#define PARM_APO setting2idx_builtin(RIG_PARM_APO) #define PARM_APO setting2idx_builtin(RIG_PARM_APO)
#define PARM_BACKLIGHT setting2idx_builtin(RIG_PARM_BACKLIGHT) #define PARM_BACKLIGHT setting2idx_builtin(RIG_PARM_BACKLIGHT)
#define PARM_BEEP setting2idx_builtin(RIG_PARM_BEEP) #define PARM_BEEP setting2idx_builtin(RIG_PARM_BEEP)
#define PARM_TIME setting2idx_builtin(RIG_PARM_TIME) #define PARM_TIME setting2idx_builtin(RIG_PARM_TIME)
#define PARM_BAT setting2idx_builtin(RIG_PARM_BAT) #define PARM_BAT setting2idx_builtin(RIG_PARM_BAT)
#define PARM_KEYLIGHT setting2idx_builtin(RIG_PARM_KEYLIGHT) #define PARM_KEYLIGHT setting2idx_builtin(RIG_PARM_KEYLIGHT)
#endif /* _IDX_BUILTIN_H */ #endif /* _IDX_BUILTIN_H */

Wyświetl plik

@ -44,7 +44,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include "hamlib/rig.h" #include <hamlib/rig.h>
#include "iofunc.h" #include "iofunc.h"
#include "misc.h" #include "misc.h"
@ -61,84 +61,112 @@
*/ */
int HAMLIB_API port_open(hamlib_port_t *p) int HAMLIB_API port_open(hamlib_port_t *p)
{ {
int status; int status;
int want_state_delay = 0; int want_state_delay = 0;
p->fd = -1; rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
switch(p->type.rig) { p->fd = -1;
case RIG_PORT_SERIAL:
status = serial_open(p);
if (status < 0)
return status;
if (p->parm.serial.rts_state != RIG_SIGNAL_UNSET &&
p->parm.serial.handshake != RIG_HANDSHAKE_HARDWARE) {
status = ser_set_rts(p,
p->parm.serial.rts_state == RIG_SIGNAL_ON);
want_state_delay = 1;
}
if (status != 0)
return status;
if (p->parm.serial.dtr_state != RIG_SIGNAL_UNSET) {
status = ser_set_dtr(p,
p->parm.serial.dtr_state == RIG_SIGNAL_ON);
want_state_delay = 1;
}
if (status != 0)
return status;
/*
* Wait whatever electrolytics in the circuit come up to voltage.
* Is 100ms enough? Too much?
*/
if (want_state_delay)
usleep(100*1000);
break; switch (p->type.rig) {
case RIG_PORT_SERIAL:
status = serial_open(p);
case RIG_PORT_PARALLEL: if (status < 0) {
status = par_open(p); return status;
if (status < 0) }
return status;
break;
case RIG_PORT_CM108: if (p->parm.serial.rts_state != RIG_SIGNAL_UNSET
status = cm108_open(p); && p->parm.serial.handshake != RIG_HANDSHAKE_HARDWARE) {
if (status < 0) status = ser_set_rts(p,
return status; p->parm.serial.rts_state == RIG_SIGNAL_ON);
break; want_state_delay = 1;
}
case RIG_PORT_DEVICE: if (status != 0) {
status = open(p->pathname, O_RDWR, 0); return status;
if (status < 0) }
return -RIG_EIO;
p->fd = status;
break;
case RIG_PORT_USB: if (p->parm.serial.dtr_state != RIG_SIGNAL_UNSET) {
status = usb_port_open(p); status = ser_set_dtr(p,
if (status < 0) p->parm.serial.dtr_state == RIG_SIGNAL_ON);
return status; want_state_delay = 1;
break; }
case RIG_PORT_NONE: if (status != 0) {
case RIG_PORT_RPC: return status;
break; /* ez :) */ }
case RIG_PORT_NETWORK: /*
case RIG_PORT_UDP_NETWORK: * Wait whatever electrolytics in the circuit come up to voltage.
* Is 100ms enough? Too much?
*/
if (want_state_delay) {
usleep(100 * 1000);
}
break;
case RIG_PORT_PARALLEL:
status = par_open(p);
if (status < 0) {
return status;
}
break;
case RIG_PORT_CM108:
status = cm108_open(p);
if (status < 0) {
return status;
}
break;
case RIG_PORT_DEVICE:
status = open(p->pathname, O_RDWR, 0);
if (status < 0) {
return -RIG_EIO;
}
p->fd = status;
break;
case RIG_PORT_USB:
status = usb_port_open(p);
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: hardcoded network port */ /* FIXME: hardcoded network port */
status = network_open(p, 4532); status = network_open(p, 4532);
if (status < 0)
return status;
break;
default: if (status < 0) {
return -RIG_EINVAL; return status;
} }
return RIG_OK; break;
default:
return -RIG_EINVAL;
}
return RIG_OK;
} }
/** /**
* \brief Close a hamlib_port * \brief Close a hamlib_port
* \param p rig port descriptor * \param p rig port descriptor
@ -151,93 +179,119 @@ int HAMLIB_API port_close(hamlib_port_t *p, rig_port_t port_type)
{ {
int ret = RIG_OK; int ret = RIG_OK;
if (p->fd != -1) { rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
switch (port_type) {
case RIG_PORT_SERIAL:
ret = ser_close(p);
break;
case RIG_PORT_PARALLEL:
ret = par_close(p);
break;
case RIG_PORT_CM108:
ret = cm108_close(p);
break;
case RIG_PORT_USB:
ret = usb_port_close(p);
break;
case RIG_PORT_NETWORK:
case RIG_PORT_UDP_NETWORK:
ret = network_close(p);
break;
default: if (p->fd != -1) {
rig_debug(RIG_DEBUG_ERR, "%s(): Unknown port type %d\n", switch (port_type) {
__func__, port_type); case RIG_PORT_SERIAL:
/* fall through */ ret = ser_close(p);
case RIG_PORT_DEVICE: break;
ret = close(p->fd);
}
p->fd = -1;
}
return ret; case RIG_PORT_PARALLEL:
ret = par_close(p);
break;
case RIG_PORT_CM108:
ret = cm108_close(p);
break;
case RIG_PORT_USB:
ret = usb_port_close(p);
break;
case RIG_PORT_NETWORK:
case RIG_PORT_UDP_NETWORK:
ret = network_close(p);
break;
default:
rig_debug(RIG_DEBUG_ERR, "%s(): Unknown port type %d\n",
__func__, port_type);
/* fall through */
case RIG_PORT_DEVICE:
ret = close(p->fd);
}
p->fd = -1;
}
return ret;
} }
#if defined(WIN32) && !defined(HAVE_TERMIOS_H) #if defined(WIN32) && !defined(HAVE_TERMIOS_H)
#include "win32termios.h" #include "win32termios.h"
/* On MinGW32/MSVC/.. the appropriate accessor must be used /* On MinGW32/MSVC/.. the appropriate accessor must be used
* depending on the port type, sigh. * depending on the port type, sigh.
*/ */
static ssize_t port_read(hamlib_port_t *p, void *buf, size_t count) static ssize_t port_read(hamlib_port_t *p, void *buf, size_t count)
{ {
int i; int i;
ssize_t ret; ssize_t ret;
if (p->type.rig == RIG_PORT_SERIAL) { if (p->type.rig == RIG_PORT_SERIAL) {
ret = win32_serial_read(p->fd, buf, count); ret = win32_serial_read(p->fd, buf, count);
if (p->parm.serial.data_bits == 7) {
unsigned char *pbuf = buf; if (p->parm.serial.data_bits == 7) {
/* clear MSB */ unsigned char *pbuf = buf;
for (i=0; i<ret; i++) {
pbuf[i] &= ~0x80; /* clear MSB */
for (i = 0; i < ret; i++) {
pbuf[i] &= ~0x80;
}
} }
return ret;
} else if (p->type.rig == RIG_PORT_NETWORK
|| p->type.rig == RIG_PORT_UDP_NETWORK) {
return recv(p->fd, buf, count, 0);
} else {
return read(p->fd, buf, count);
} }
return ret;
} else if (p->type.rig == RIG_PORT_NETWORK || p->type.rig == RIG_PORT_UDP_NETWORK)
return recv(p->fd, buf, count, 0);
else
return read(p->fd, buf, count);
} }
static ssize_t port_write(hamlib_port_t *p, const void *buf, size_t count) static ssize_t port_write(hamlib_port_t *p, const void *buf, size_t count)
{ {
if (p->type.rig == RIG_PORT_SERIAL) if (p->type.rig == RIG_PORT_SERIAL) {
return win32_serial_write(p->fd, buf, count); return win32_serial_write(p->fd, buf, count);
else if (p->type.rig == RIG_PORT_NETWORK || p->type.rig == RIG_PORT_UDP_NETWORK) } else if (p->type.rig == RIG_PORT_NETWORK
return send(p->fd, buf, count, 0); || p->type.rig == RIG_PORT_UDP_NETWORK) {
else return send(p->fd, buf, count, 0);
return write(p->fd, buf, count); } else {
return write(p->fd, buf, count);
}
} }
static int port_select(hamlib_port_t *p, int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
static int port_select(hamlib_port_t *p, int n, fd_set *readfds,
fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout)
{ {
#if 1 #if 1
/* select does not work very well with writefds/exceptfds
* So let's pretend there's none of them /* select does not work very well with writefds/exceptfds
*/ * So let's pretend there's none of them
if (exceptfds) */
FD_ZERO(exceptfds); if (exceptfds) {
if (writefds) FD_ZERO(exceptfds);
FD_ZERO(writefds); }
writefds = NULL;
exceptfds = NULL; if (writefds) {
FD_ZERO(writefds);
}
writefds = NULL;
exceptfds = NULL;
#endif #endif
if (p->type.rig == RIG_PORT_SERIAL) if (p->type.rig == RIG_PORT_SERIAL) {
return win32_serial_select(n, readfds, writefds, exceptfds, timeout); return win32_serial_select(n, readfds, writefds, exceptfds, timeout);
else } else {
return select(n, readfds, writefds, exceptfds, timeout); return select(n, readfds, writefds, exceptfds, timeout);
}
} }
@ -247,21 +301,23 @@ static int port_select(hamlib_port_t *p, int n, fd_set *readfds, fd_set *writefd
static ssize_t port_read(hamlib_port_t *p, void *buf, size_t count) static ssize_t port_read(hamlib_port_t *p, void *buf, size_t count)
{ {
int i; int i;
ssize_t ret; ssize_t ret;
if (p->type.rig == RIG_PORT_SERIAL && p->parm.serial.data_bits == 7) { if (p->type.rig == RIG_PORT_SERIAL && p->parm.serial.data_bits == 7) {
unsigned char *pbuf = buf; unsigned char *pbuf = buf;
ret = read(p->fd, buf, count); ret = read(p->fd, buf, count);
/* clear MSB */
for (i=0; i<ret; i++) { /* clear MSB */
pbuf[i] &= ~0x80; for (i = 0; i < ret; i++) {
pbuf[i] &= ~0x80;
}
return ret;
} else {
return read(p->fd, buf, count);
} }
return ret;
} else {
return read(p->fd, buf, count);
}
} }
#define port_write(p,b,c) write((p)->fd,(b),(c)) #define port_write(p,b,c) write((p)->fd,(b),(c))
@ -300,67 +356,77 @@ static ssize_t port_read(hamlib_port_t *p, void *buf, size_t count)
int HAMLIB_API write_block(hamlib_port_t *p, const char *txbuffer, size_t count) int HAMLIB_API write_block(hamlib_port_t *p, const char *txbuffer, size_t count)
{ {
int i, ret; int i, ret;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
#ifdef WANT_NON_ACTIVE_POST_WRITE_DELAY #ifdef WANT_NON_ACTIVE_POST_WRITE_DELAY
if (p->post_write_date.tv_sec != 0) {
signed int date_delay; /* in us */
struct timeval tv;
/* FIXME in Y2038 ... */ if (p->post_write_date.tv_sec != 0) {
gettimeofday(&tv, NULL); signed int date_delay; /* in us */
date_delay = p->post_write_delay*1000 - struct timeval tv;
((tv.tv_sec - p->post_write_date.tv_sec)*1000000 +
(tv.tv_usec - p->post_write_date.tv_usec)); /* FIXME in Y2038 ... */
if (date_delay > 0) { gettimeofday(&tv, NULL);
/* date_delay = p->post_write_delay * 1000 -
* optional delay after last write ((tv.tv_sec - p->post_write_date.tv_sec) * 1000000 +
*/ (tv.tv_usec - p->post_write_date.tv_usec));
usleep(date_delay);
} if (date_delay > 0) {
p->post_write_date.tv_sec = 0; /*
} * optional delay after last write
*/
usleep(date_delay);
}
p->post_write_date.tv_sec = 0;
}
#endif #endif
if (p->write_delay > 0) { if (p->write_delay > 0) {
for (i=0; i < count; i++) { for (i = 0; i < count; i++) {
ret = port_write(p, txbuffer+i, 1); ret = port_write(p, txbuffer + i, 1);
if (ret != 1) {
rig_debug(RIG_DEBUG_ERR,"%s():%d failed %d - %s\n",
__func__, __LINE__, ret, strerror(errno));
return -RIG_EIO;
}
usleep(p->write_delay*1000);
}
} else {
ret = port_write(p, txbuffer, count);
if (ret != count) {
rig_debug(RIG_DEBUG_ERR,"%s():%d failed %d - %s\n",
__func__, __LINE__, ret, strerror(errno));
return -RIG_EIO;
}
}
if (p->post_write_delay > 0) { if (ret != 1) {
rig_debug(RIG_DEBUG_ERR, "%s():%d failed %d - %s\n",
__func__, __LINE__, ret, strerror(errno));
return -RIG_EIO;
}
usleep(p->write_delay * 1000);
}
} else {
ret = port_write(p, txbuffer, count);
if (ret != count) {
rig_debug(RIG_DEBUG_ERR, "%s():%d failed %d - %s\n",
__func__, __LINE__, ret, strerror(errno));
return -RIG_EIO;
}
}
if (p->post_write_delay > 0) {
#ifdef WANT_NON_ACTIVE_POST_WRITE_DELAY #ifdef WANT_NON_ACTIVE_POST_WRITE_DELAY
#define POST_WRITE_DELAY_TRSHLD 10 #define POST_WRITE_DELAY_TRSHLD 10
if (p->post_write_delay > POST_WRITE_DELAY_TRSHLD) { if (p->post_write_delay > POST_WRITE_DELAY_TRSHLD) {
struct timeval tv; struct timeval tv;
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
p->post_write_date.tv_sec = tv.tv_sec; p->post_write_date.tv_sec = tv.tv_sec;
p->post_write_date.tv_usec = tv.tv_usec; p->post_write_date.tv_usec = tv.tv_usec;
} } else
else
#endif #endif
usleep(p->post_write_delay*1000); /* optional delay after last write */ usleep(p->post_write_delay * 1000); /* optional delay after last write */
/* otherwise some yaesu rigs get confused */
/* with sequential fast writes*/
}
rig_debug(RIG_DEBUG_TRACE,"%s(): TX %d bytes\n", __func__, count);
dump_hex((unsigned char *) txbuffer,count);
return RIG_OK; /* otherwise some yaesu rigs get confused */
/* with sequential fast writes*/
}
rig_debug(RIG_DEBUG_TRACE, "%s(): TX %d bytes\n", __func__, count);
dump_hex((unsigned char *) txbuffer, count);
return RIG_OK;
} }
@ -384,73 +450,90 @@ int HAMLIB_API write_block(hamlib_port_t *p, const char *txbuffer, size_t count)
int HAMLIB_API read_block(hamlib_port_t *p, char *rxbuffer, size_t count) int HAMLIB_API read_block(hamlib_port_t *p, char *rxbuffer, size_t count)
{ {
fd_set rfds, efds; fd_set rfds, efds;
struct timeval tv, tv_timeout, start_time, end_time, elapsed_time; struct timeval tv, tv_timeout, start_time, end_time, elapsed_time;
int rd_count, total_count = 0; int rd_count, total_count = 0;
int retval; int retval;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
/* /*
* Wait up to timeout ms. * Wait up to timeout ms.
*/ */
tv_timeout.tv_sec = p->timeout/1000; tv_timeout.tv_sec = p->timeout / 1000;
tv_timeout.tv_usec = (p->timeout%1000)*1000; tv_timeout.tv_usec = (p->timeout % 1000) * 1000;
/* Store the time of the read loop start */ /* Store the time of the read loop start */
gettimeofday(&start_time, NULL); gettimeofday(&start_time, NULL);
while (count > 0) { while (count > 0) {
tv = tv_timeout; /* select may have updated it */ tv = tv_timeout; /* select may have updated it */
FD_ZERO(&rfds); FD_ZERO(&rfds);
FD_SET(p->fd, &rfds); FD_SET(p->fd, &rfds);
efds = rfds; efds = rfds;
retval = port_select(p, p->fd+1, &rfds, NULL, &efds, &tv); retval = port_select(p, p->fd + 1, &rfds, NULL, &efds, &tv);
if (retval == 0) {
/* Record timeout time and caculate elapsed time */
gettimeofday(&end_time, NULL);
timersub(&end_time, &start_time, &elapsed_time);
dump_hex((unsigned char *) rxbuffer, total_count); if (retval == 0) {
rig_debug(RIG_DEBUG_WARN, "%s(): Timed out %d.%d seconds after %d chars\n", /* Record timeout time and caculate elapsed time */
__func__, elapsed_time.tv_sec, elapsed_time.tv_usec, total_count); gettimeofday(&end_time, NULL);
timersub(&end_time, &start_time, &elapsed_time);
return -RIG_ETIMEOUT; dump_hex((unsigned char *) rxbuffer, total_count);
} rig_debug(RIG_DEBUG_WARN,
if (retval < 0) { "%s(): Timed out %d.%d seconds after %d chars\n",
dump_hex((unsigned char *) rxbuffer, total_count); __func__,
rig_debug(RIG_DEBUG_ERR,"%s(): select() error after %d chars: %s\n", elapsed_time.tv_sec,
__func__, total_count, strerror(errno)); elapsed_time.tv_usec,
total_count);
return -RIG_EIO; return -RIG_ETIMEOUT;
} }
if (FD_ISSET(p->fd, &efds)) {
rig_debug(RIG_DEBUG_ERR, "%s(): fd error after %d chars\n",
__func__, total_count);
return -RIG_EIO; if (retval < 0) {
} dump_hex((unsigned char *) rxbuffer, total_count);
rig_debug(RIG_DEBUG_ERR,
"%s(): select() error after %d chars: %s\n",
__func__,
total_count,
strerror(errno));
/* return -RIG_EIO;
* grab bytes from the rig }
* The file descriptor must have been set up non blocking.
*/
rd_count = port_read(p, rxbuffer+total_count, count);
if (rd_count < 0) {
rig_debug(RIG_DEBUG_ERR, "%s(): read() failed - %s\n",
__func__, strerror(errno));
return -RIG_EIO; if (FD_ISSET(p->fd, &efds)) {
} rig_debug(RIG_DEBUG_ERR,
total_count += rd_count; "%s(): fd error after %d chars\n",
count -= rd_count; __func__,
} total_count);
rig_debug(RIG_DEBUG_TRACE,"%s(): RX %d bytes\n", __func__, total_count); return -RIG_EIO;
dump_hex((unsigned char *) rxbuffer, total_count); }
return total_count; /* return bytes count read */ /*
* grab bytes from the rig
* The file descriptor must have been set up non blocking.
*/
rd_count = port_read(p, rxbuffer + total_count, count);
if (rd_count < 0) {
rig_debug(RIG_DEBUG_ERR,
"%s(): read() failed - %s\n",
__func__,
strerror(errno));
return -RIG_EIO;
}
total_count += rd_count;
count -= rd_count;
}
rig_debug(RIG_DEBUG_TRACE, "%s(): RX %d bytes\n", __func__, total_count);
dump_hex((unsigned char *) rxbuffer, total_count);
return total_count; /* return bytes count read */
} }
@ -479,89 +562,119 @@ int HAMLIB_API read_block(hamlib_port_t *p, char *rxbuffer, size_t count)
* *
* Assumes rxbuffer!=NULL * Assumes rxbuffer!=NULL
*/ */
int HAMLIB_API read_string(hamlib_port_t *p, char *rxbuffer, size_t rxmax, const char *stopset, int HAMLIB_API read_string(hamlib_port_t *p, char *rxbuffer, size_t rxmax,
int stopset_len) const char *stopset,
int stopset_len)
{ {
fd_set rfds, efds; fd_set rfds, efds;
struct timeval tv, tv_timeout, start_time, end_time, elapsed_time; struct timeval tv, tv_timeout, start_time, end_time, elapsed_time;
int rd_count, total_count = 0; int rd_count, total_count = 0;
int retval; int retval;
if (!p || !rxbuffer) return -RIG_EINVAL; rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (rxmax < 1) return 0;
/* if (!p || !rxbuffer) {
* Wait up to timeout ms. return -RIG_EINVAL;
*/
tv_timeout.tv_sec = p->timeout/1000;
tv_timeout.tv_usec = (p->timeout%1000)*1000;
/* Store the time of the read loop start */
gettimeofday(&start_time, NULL);
while (total_count < rxmax-1) {
tv = tv_timeout; /* select may have updated it */
FD_ZERO(&rfds);
FD_SET(p->fd, &rfds);
efds = rfds;
retval = port_select(p, p->fd+1, &rfds, NULL, &efds, &tv);
if (retval == 0) {
if (0 == total_count) {
/* Record timeout time and caculate elapsed time */
gettimeofday(&end_time, NULL);
timersub(&end_time, &start_time, &elapsed_time);
dump_hex((unsigned char *) rxbuffer, total_count);
rig_debug(RIG_DEBUG_WARN, "%s(): Timed out %d.%d seconds after %d chars\n",
__func__, elapsed_time.tv_sec, elapsed_time.tv_usec, total_count);
return -RIG_ETIMEOUT;
} }
break; /* return what we have read */
}
if (retval < 0) { if (rxmax < 1) {
dump_hex((unsigned char *) rxbuffer, total_count); return 0;
rig_debug(RIG_DEBUG_ERR, "%s(): select() error after %d chars: %s\n", }
__func__, total_count, strerror(errno));
return -RIG_EIO; /*
} * Wait up to timeout ms.
if (FD_ISSET(p->fd, &efds)) { */
rig_debug(RIG_DEBUG_ERR, "%s(): fd error after %d chars\n", tv_timeout.tv_sec = p->timeout / 1000;
__func__, total_count); tv_timeout.tv_usec = (p->timeout % 1000) * 1000;
return -RIG_EIO; /* Store the time of the read loop start */
} gettimeofday(&start_time, NULL);
/* while (total_count < rxmax - 1) {
* read 1 character from the rig, (check if in stop set) tv = tv_timeout; /* select may have updated it */
* The file descriptor must have been set up non blocking.
*/ FD_ZERO(&rfds);
FD_SET(p->fd, &rfds);
efds = rfds;
retval = port_select(p, p->fd + 1, &rfds, NULL, &efds, &tv);
if (retval == 0) {
if (0 == total_count) {
/* Record timeout time and caculate elapsed time */
gettimeofday(&end_time, NULL);
timersub(&end_time, &start_time, &elapsed_time);
dump_hex((unsigned char *) rxbuffer, total_count);
rig_debug(RIG_DEBUG_WARN,
"%s(): Timed out %d.%d seconds after %d chars\n",
__func__,
elapsed_time.tv_sec,
elapsed_time.tv_usec,
total_count);
return -RIG_ETIMEOUT;
}
break; /* return what we have read */
}
if (retval < 0) {
dump_hex((unsigned char *) rxbuffer, total_count);
rig_debug(RIG_DEBUG_ERR,
"%s(): select() error after %d chars: %s\n",
__func__,
total_count,
strerror(errno));
return -RIG_EIO;
}
if (FD_ISSET(p->fd, &efds)) {
rig_debug(RIG_DEBUG_ERR,
"%s(): fd error after %d chars\n",
__func__,
total_count);
return -RIG_EIO;
}
/*
* read 1 character from the rig, (check if in stop set)
* The file descriptor must have been set up non blocking.
*/
rd_count = port_read(p, &rxbuffer[total_count], 1); rd_count = port_read(p, &rxbuffer[total_count], 1);
if (rd_count < 0) {
dump_hex((unsigned char *) rxbuffer, total_count);
rig_debug(RIG_DEBUG_ERR, "%s(): read() failed - %s\n",
__func__, strerror(errno));
return -RIG_EIO; if (rd_count < 0) {
} dump_hex((unsigned char *) rxbuffer, total_count);
rig_debug(RIG_DEBUG_ERR,
"%s(): read() failed - %s\n",
__func__,
strerror(errno));
return -RIG_EIO;
}
++total_count; ++total_count;
if (stopset && memchr(stopset, rxbuffer[total_count-1], stopset_len))
break;
}
/*
* Doesn't hurt anyway. But be aware, some binary protocols may have
* null chars within th received buffer.
*/
rxbuffer[total_count] = '\000';
rig_debug(RIG_DEBUG_TRACE,"%s(): RX %d characters\n", __func__, total_count); if (stopset && memchr(stopset, rxbuffer[total_count - 1], stopset_len)) {
dump_hex((unsigned char *) rxbuffer, total_count); break;
}
}
return total_count; /* return bytes count read */ /*
* Doesn't hurt anyway. But be aware, some binary protocols may have
* null chars within th received buffer.
*/
rxbuffer[total_count] = '\000';
rig_debug(RIG_DEBUG_TRACE,
"%s(): RX %d characters\n",
__func__,
total_count);
dump_hex((unsigned char *) rxbuffer, total_count);
return total_count; /* return bytes count read */
} }
/** @} */ /** @} */

Wyświetl plik

@ -29,9 +29,19 @@
extern HAMLIB_EXPORT(int) port_open(hamlib_port_t *p); extern HAMLIB_EXPORT(int) port_open(hamlib_port_t *p);
extern HAMLIB_EXPORT(int) port_close(hamlib_port_t *p, rig_port_t port_type); extern HAMLIB_EXPORT(int) port_close(hamlib_port_t *p, rig_port_t port_type);
extern HAMLIB_EXPORT(int) read_block(hamlib_port_t *p, char *rxbuffer, size_t count);
extern HAMLIB_EXPORT(int) write_block(hamlib_port_t *p, const char *txbuffer, size_t count); extern HAMLIB_EXPORT(int) read_block(hamlib_port_t *p,
extern HAMLIB_EXPORT(int) read_string(hamlib_port_t *p, char *rxbuffer, size_t rxmax, const char *stopset, int stopset_len); char *rxbuffer,
size_t count);
extern HAMLIB_EXPORT(int) write_block(hamlib_port_t *p,
const char *txbuffer,
size_t count);
extern HAMLIB_EXPORT(int) read_string(hamlib_port_t *p,
char *rxbuffer,
size_t rxmax,
const char *stopset,
int stopset_len);
#endif /* _IOFUNC_H */ #endif /* _IOFUNC_H */

Wyświetl plik

@ -28,7 +28,7 @@
* taken from wwl, by IK0ZSN Mirko Caserta. * taken from wwl, by IK0ZSN Mirko Caserta.
* *
* New bearing code added by N0NB was found at: * New bearing code added by N0NB was found at:
* http://williams.best.vwh.net/avform.htm#Crs * http://williams.best.vwh.net/avform.htm#Crs
* *
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
@ -88,7 +88,7 @@
* locators described in section 3L of "The IARU region 1 VHF managers * locators described in section 3L of "The IARU region 1 VHF managers
* handbook". Values of 5 and 6 will extent the format even more, to the * handbook". Values of 5 and 6 will extent the format even more, to the
* longest definition I have seen for locators, see * longest definition I have seen for locators, see
* http://www.btinternet.com/~g8yoa/geog/non-ra.html * http://www.btinternet.com/~g8yoa/geog/non-ra.html
* Beware that there seems to be no universally accepted standard for 10 & 12 * Beware that there seems to be no universally accepted standard for 10 & 12
* character locators. * character locators.
* *
@ -115,14 +115,15 @@ const static int loc_char_range[] = { 18, 10, 24, 10, 24, 10 };
/* end dph */ /* end dph */
#endif /* !DOC_HIDDEN */ #endif /* !DOC_HIDDEN */
/** /**
* \brief Convert DMS to decimal degrees * \brief Convert DMS to decimal degrees
* \param degrees Degrees, whole degrees * \param degrees Degrees, whole degrees
* \param minutes Minutes, whole minutes * \param minutes Minutes, whole minutes
* \param seconds Seconds, decimal seconds * \param seconds Seconds, decimal seconds
* \param sw South or West * \param sw South or West
* *
* Convert degree/minute/second angle to decimal degrees angle. * Convert degree/minute/second angle to decimal degrees angle.
* \a degrees >360, \a minutes > 60, and \a seconds > 60.0 are allowed, * \a degrees >360, \a minutes > 60, and \a seconds > 60.0 are allowed,
@ -137,30 +138,39 @@ const static int loc_char_range[] = { 18, 10, 24, 10, 24, 10 };
* *
* \sa dec2dms() * \sa dec2dms()
*/ */
double HAMLIB_API dms2dec(int degrees, int minutes, double seconds, int sw)
{
double st;
double HAMLIB_API dms2dec(int degrees, int minutes, double seconds, int sw) { rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
double st;
if (degrees < 0) if (degrees < 0) {
degrees = abs(degrees); degrees = abs(degrees);
if (minutes < 0) }
minutes = abs(minutes);
if (seconds < 0)
seconds = fabs(seconds);
st = (double)degrees + (double)minutes / 60. + seconds / 3600.; if (minutes < 0) {
minutes = abs(minutes);
}
if (sw == 1) if (seconds < 0) {
return -st; seconds = fabs(seconds);
else }
return st;
st = (double)degrees + (double)minutes / 60. + seconds / 3600.;
if (sw == 1) {
return -st;
} else {
return st;
}
} }
/** /**
* \brief Convert D M.MMM notation to decimal degrees * \brief Convert D M.MMM notation to decimal degrees
* \param degrees Degrees, whole degrees * \param degrees Degrees, whole degrees
* \param minutes Minutes, decimal minutes * \param minutes Minutes, decimal minutes
* \param sw South or West * \param sw South or West
* *
* Convert a degrees, decimal minutes notation common on * Convert a degrees, decimal minutes notation common on
* many GPS units to its decimal degrees value. * many GPS units to its decimal degrees value.
@ -177,30 +187,37 @@ double HAMLIB_API dms2dec(int degrees, int minutes, double seconds, int sw) {
* *
* \sa dec2dmmm() * \sa dec2dmmm()
*/ */
double HAMLIB_API dmmm2dec(int degrees, double minutes, int sw)
{
double st;
double HAMLIB_API dmmm2dec(int degrees, double minutes, int sw) { rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
double st;
if (degrees < 0) if (degrees < 0) {
degrees = abs(degrees); degrees = abs(degrees);
if (minutes < 0) }
minutes = fabs(minutes);
st = (double)degrees + minutes / 60.; if (minutes < 0) {
minutes = fabs(minutes);
}
if (sw == 1) st = (double)degrees + minutes / 60.;
return -st;
else if (sw == 1) {
return st; return -st;
} else {
return st;
}
} }
/** /**
* \brief Convert decimal degrees angle into DMS notation * \brief Convert decimal degrees angle into DMS notation
* \param dec Decimal degrees * \param dec Decimal degrees
* \param degrees Pointer for the calculated whole Degrees * \param degrees Pointer for the calculated whole Degrees
* \param minutes Pointer for the calculated whole Minutes * \param minutes Pointer for the calculated whole Minutes
* \param seconds Pointer for the calculated decimal Seconds * \param seconds Pointer for the calculated decimal Seconds
* \param sw Pointer for the calculated SW flag * \param sw Pointer for the calculated SW flag
* *
* Convert decimal degrees angle into its degree/minute/second * Convert decimal degrees angle into its degree/minute/second
* notation. * notation.
@ -221,62 +238,69 @@ double HAMLIB_API dmmm2dec(int degrees, double minutes, int sw) {
* *
* \sa dms2dec() * \sa dms2dec()
*/ */
int HAMLIB_API dec2dms(double dec, int *degrees, int *minutes, double *seconds,
int *sw)
{
int deg, min;
double st;
int HAMLIB_API dec2dms(double dec, int *degrees, int *minutes, double *seconds, int *sw) { rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
int deg, min;
double st;
/* bail if NULL pointers passed */ /* bail if NULL pointers passed */
if (!degrees || !minutes || !seconds || !sw) if (!degrees || !minutes || !seconds || !sw) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
/* reverse the sign if dec has a magnitude greater /* reverse the sign if dec has a magnitude greater
* than 180 and factor out multiples of 360. * than 180 and factor out multiples of 360.
* e.g. when passed 270 st will be set to -90 * e.g. when passed 270 st will be set to -90
* and when passed -270 st will be set to 90. If * and when passed -270 st will be set to 90. If
* passed 361 st will be set to 1, etc. If passed * passed 361 st will be set to 1, etc. If passed
* a value > -180 || < 180, value will be unchanged. * a value > -180 || < 180, value will be unchanged.
*/ */
if (dec >= 0.0) if (dec >= 0.0) {
st = fmod(dec + 180, 360) - 180; st = fmod(dec + 180, 360) - 180;
else } else {
st = fmod(dec - 180, 360) + 180; st = fmod(dec - 180, 360) + 180;
}
/* if after all of that st is negative, we want deg /* if after all of that st is negative, we want deg
* to be negative as well except for 180 which we want * to be negative as well except for 180 which we want
* to be positive. * to be positive.
*/ */
if (st < 0.0 && st != -180) if (st < 0.0 && st != -180) {
*sw = 1; *sw = 1;
else } else {
*sw = 0; *sw = 0;
}
/* work on st as a positive value to remove a /* work on st as a positive value to remove a
* bug introduced by the effect of floor() when * bug introduced by the effect of floor() when
* passed a negative value. e.g. when passed * passed a negative value. e.g. when passed
* -96.8333 floor() returns -95! Also avoids * -96.8333 floor() returns -95! Also avoids
* a rounding error introduced on negative values. * a rounding error introduced on negative values.
*/ */
st = fabs(st); st = fabs(st);
deg = (int)floor(st); deg = (int)floor(st);
st = 60. * (st - (double)deg); st = 60. * (st - (double)deg);
min = (int)floor(st); min = (int)floor(st);
st = 60. * (st - (double)min); st = 60. * (st - (double)min);
*degrees = deg; *degrees = deg;
*minutes = min; *minutes = min;
*seconds = st; *seconds = st;
return RIG_OK; return RIG_OK;
} }
/** /**
* \brief Convert a decimal angle into D M.MMM notation * \brief Convert a decimal angle into D M.MMM notation
* \param dec Decimal degrees * \param dec Decimal degrees
* \param degrees Pointer for the calculated whole Degrees * \param degrees Pointer for the calculated whole Degrees
* \param minutes Pointer for the calculated decimal Minutes * \param minutes Pointer for the calculated decimal Minutes
* \param sw Pointer for the calculated SW flag * \param sw Pointer for the calculated SW flag
* *
* Convert a decimal angle into its degree, decimal minute * Convert a decimal angle into its degree, decimal minute
* notation common on many GPS units. * notation common on many GPS units.
@ -297,29 +321,35 @@ int HAMLIB_API dec2dms(double dec, int *degrees, int *minutes, double *seconds,
* *
* \sa dmmm2dec() * \sa dmmm2dec()
*/ */
int HAMLIB_API dec2dmmm(double dec, int *degrees, double *minutes, int *sw)
{
int r, min;
double sec;
int HAMLIB_API dec2dmmm(double dec, int *degrees, double *minutes, int *sw) { rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
int r, min;
double sec;
/* bail if NULL pointers passed */ /* bail if NULL pointers passed */
if (!degrees || !minutes || !sw) if (!degrees || !minutes || !sw) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
r = dec2dms(dec, degrees, &min, &sec, sw); r = dec2dms(dec, degrees, &min, &sec, sw);
if (r != RIG_OK)
return r;
*minutes = (double)min + sec / 60; if (r != RIG_OK) {
return r;
}
return RIG_OK; *minutes = (double)min + sec / 60;
return RIG_OK;
} }
/** /**
* \brief Convert Maidenhead grid locator to Longitude/Latitude * \brief Convert Maidenhead grid locator to Longitude/Latitude
* \param longitude Pointer for the calculated Longitude * \param longitude Pointer for the calculated Longitude
* \param latitude Pointer for the calculated Latitude * \param latitude Pointer for the calculated Latitude
* \param locator The Maidenhead grid locator--2 through 12 char + nul string * \param locator The Maidenhead grid locator--2 through 12 char + nul string
* *
* Convert Maidenhead grid locator to Longitude/Latitude (decimal degrees). * Convert Maidenhead grid locator to Longitude/Latitude (decimal degrees).
* The locator should be in 2 through 12 chars long format. * The locator should be in 2 through 12 chars long format.
@ -342,63 +372,71 @@ int HAMLIB_API dec2dmmm(double dec, int *degrees, double *minutes, int *sw) {
*/ */
/* begin dph */ /* begin dph */
int HAMLIB_API locator2longlat(double *longitude, double *latitude,
const char *locator)
{
int x_or_y, paircount;
int locvalue, pair;
int divisions;
double xy[2], ordinate;
int HAMLIB_API locator2longlat(double *longitude, double *latitude, const char *locator) { rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
int x_or_y, paircount;
int locvalue, pair;
int divisions;
double xy[2], ordinate;
/* bail if NULL pointers passed */ /* bail if NULL pointers passed */
if (!longitude || !latitude) if (!longitude || !latitude) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
paircount = strlen(locator) / 2; paircount = strlen(locator) / 2;
/* verify paircount is within limits */ /* verify paircount is within limits */
if (paircount > MAX_LOCATOR_PAIRS) if (paircount > MAX_LOCATOR_PAIRS) {
paircount = MAX_LOCATOR_PAIRS; paircount = MAX_LOCATOR_PAIRS;
else if (paircount < MIN_LOCATOR_PAIRS) } else if (paircount < MIN_LOCATOR_PAIRS) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
/* For x(=longitude) and y(=latitude) */ /* For x(=longitude) and y(=latitude) */
for (x_or_y = 0; x_or_y < 2; ++x_or_y) { for (x_or_y = 0; x_or_y < 2; ++x_or_y) {
ordinate = -90.0; ordinate = -90.0;
divisions = 1; divisions = 1;
for (pair = 0; pair < paircount; ++pair) { for (pair = 0; pair < paircount; ++pair) {
locvalue = locator[pair*2 + x_or_y]; locvalue = locator[pair * 2 + x_or_y];
/* Value of digit or letter */ /* Value of digit or letter */
locvalue -= (loc_char_range[pair] == 10) ? '0' : locvalue -= (loc_char_range[pair] == 10) ? '0' :
(isupper(locvalue)) ? 'A' : 'a'; (isupper(locvalue)) ? 'A' : 'a';
/* Check range for non-letter/digit or out of range */ /* Check range for non-letter/digit or out of range */
if ((locvalue < 0) || (locvalue >= loc_char_range[pair])) if ((locvalue < 0) || (locvalue >= loc_char_range[pair])) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
divisions *= loc_char_range[pair]; divisions *= loc_char_range[pair];
ordinate += locvalue * 180.0 / divisions; ordinate += locvalue * 180.0 / divisions;
} }
/* Center ordinate in the Maidenhead "square" or "subsquare" */
ordinate += 90.0 / divisions;
xy[x_or_y] = ordinate; /* Center ordinate in the Maidenhead "square" or "subsquare" */
} ordinate += 90.0 / divisions;
*longitude = xy[0] * 2.0; xy[x_or_y] = ordinate;
*latitude = xy[1]; }
return RIG_OK; *longitude = xy[0] * 2.0;
*latitude = xy[1];
return RIG_OK;
} }
/* end dph */ /* end dph */
/** /**
* \brief Convert longitude/latitude to Maidenhead grid locator * \brief Convert longitude/latitude to Maidenhead grid locator
* \param longitude Longitude, decimal degrees * \param longitude Longitude, decimal degrees
* \param latitude Latitude, decimal degrees * \param latitude Latitude, decimal degrees
* \param locator Pointer for the Maidenhead Locator * \param locator Pointer for the Maidenhead Locator
* \param pair_count Precision expressed as lon/lat pairs in the locator * \param pair_count Precision expressed as lon/lat pairs in the locator
* *
* Convert longitude/latitude (decimal degrees) to Maidenhead grid locator. * Convert longitude/latitude (decimal degrees) to Maidenhead grid locator.
* \a locator must point to an array at least \a pair_count * 2 char + '\\0'. * \a locator must point to an array at least \a pair_count * 2 char + '\\0'.
@ -416,55 +454,62 @@ int HAMLIB_API locator2longlat(double *longitude, double *latitude, const char *
*/ */
/* begin dph */ /* begin dph */
int HAMLIB_API longlat2locator(double longitude, double latitude, char *locator,
int pair_count)
{
int x_or_y, pair, locvalue, divisions;
double square_size, ordinate;
int HAMLIB_API longlat2locator(double longitude, double latitude, char *locator, int pair_count) { rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
int x_or_y, pair, locvalue, divisions;
double square_size, ordinate;
if (!locator) if (!locator) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
if (pair_count < MIN_LOCATOR_PAIRS || pair_count > MAX_LOCATOR_PAIRS) if (pair_count < MIN_LOCATOR_PAIRS || pair_count > MAX_LOCATOR_PAIRS) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
for (x_or_y = 0; x_or_y < 2; ++x_or_y) { for (x_or_y = 0; x_or_y < 2; ++x_or_y) {
ordinate = (x_or_y == 0) ? longitude / 2.0 : latitude; ordinate = (x_or_y == 0) ? longitude / 2.0 : latitude;
divisions = 1; divisions = 1;
/* The 1e-6 here guards against floating point rounding errors */ /* The 1e-6 here guards against floating point rounding errors */
ordinate = fmod(ordinate + 270.000001, 180.0); ordinate = fmod(ordinate + 270.000001, 180.0);
for (pair = 0; pair < pair_count; ++pair) {
divisions *= loc_char_range[pair];
square_size = 180.0 / divisions;
locvalue = (int) (ordinate / square_size); for (pair = 0; pair < pair_count; ++pair) {
ordinate -= square_size * locvalue; divisions *= loc_char_range[pair];
locvalue += (loc_char_range[pair] == 10) ? '0':'A'; square_size = 180.0 / divisions;
locator[pair * 2 + x_or_y] = locvalue;
}
}
locator[pair_count * 2] = '\0';
return RIG_OK; locvalue = (int)(ordinate / square_size);
ordinate -= square_size * locvalue;
locvalue += (loc_char_range[pair] == 10) ? '0' : 'A';
locator[pair * 2 + x_or_y] = locvalue;
}
}
locator[pair_count * 2] = '\0';
return RIG_OK;
} }
/* end dph */ /* end dph */
/** /**
* \brief Calculate the distance and bearing between two points. * \brief Calculate the distance and bearing between two points.
* \param lon1 The local Longitude, decimal degrees * \param lon1 The local Longitude, decimal degrees
* \param lat1 The local Latitude, decimal degrees * \param lat1 The local Latitude, decimal degrees
* \param lon2 The remote Longitude, decimal degrees * \param lon2 The remote Longitude, decimal degrees
* \param lat2 The remote Latitude, decimal degrees * \param lat2 The remote Latitude, decimal degrees
* \param distance Pointer for the distance, km * \param distance Pointer for the distance, km
* \param azimuth Pointer for the bearing, decimal degrees * \param azimuth Pointer for the bearing, decimal degrees
* *
* Calculate the QRB between \a lon1, \a lat1 and \a lon2, \a lat2. * Calculate the QRB between \a lon1, \a lat1 and \a lon2, \a lat2.
* *
* This version will calculate the QRB to a precision sufficient * This version will calculate the QRB to a precision sufficient
* for 12 character locators. Antipodal points, which are easily * for 12 character locators. Antipodal points, which are easily
* calculated, are considered equidistant and the bearing is * calculated, are considered equidistant and the bearing is
* simply resolved to be true north (0.0°). * simply resolved to be true north (0.0°).
* *
* \retval -RIG_EINVAL if NULL pointer passed or lat and lon values * \retval -RIG_EINVAL if NULL pointer passed or lat and lon values
* exceed -90 to 90 or -180 to 180. * exceed -90 to 90 or -180 to 180.
@ -475,90 +520,99 @@ int HAMLIB_API longlat2locator(double longitude, double latitude, char *locator,
* *
* \sa distance_long_path(), azimuth_long_path() * \sa distance_long_path(), azimuth_long_path()
*/ */
int HAMLIB_API qrb(double lon1, double lat1, double lon2, double lat2,
double *distance, double *azimuth)
{
double delta_long, tmp, arc, az;
int HAMLIB_API qrb(double lon1, double lat1, double lon2, double lat2, double *distance, double *azimuth) { rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
double delta_long, tmp, arc, az;
/* bail if NULL pointers passed */ /* bail if NULL pointers passed */
if (!distance || !azimuth) if (!distance || !azimuth) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
if ((lat1 > 90.0 || lat1 < -90.0) || (lat2 > 90.0 || lat2 < -90.0)) if ((lat1 > 90.0 || lat1 < -90.0) || (lat2 > 90.0 || lat2 < -90.0)) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
if ((lon1 > 180.0 || lon1 < -180.0) || (lon2 > 180.0 || lon2 < -180.0)) if ((lon1 > 180.0 || lon1 < -180.0) || (lon2 > 180.0 || lon2 < -180.0)) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
/* Prevent ACOS() Domain Error */ /* Prevent ACOS() Domain Error */
if (lat1 == 90.0) if (lat1 == 90.0) {
lat1 = 89.999999999; lat1 = 89.999999999;
else if (lat1 == -90.0) } else if (lat1 == -90.0) {
lat1 = -89.999999999; lat1 = -89.999999999;
}
if (lat2 == 90.0) if (lat2 == 90.0) {
lat2 = 89.999999999; lat2 = 89.999999999;
else if (lat2 == -90.0) } else if (lat2 == -90.0) {
lat2 = -89.999999999; lat2 = -89.999999999;
}
/* Convert variables to Radians */ /* Convert variables to Radians */
lat1 /= RADIAN; lat1 /= RADIAN;
lon1 /= RADIAN; lon1 /= RADIAN;
lat2 /= RADIAN; lat2 /= RADIAN;
lon2 /= RADIAN; lon2 /= RADIAN;
delta_long = lon2 - lon1; delta_long = lon2 - lon1;
tmp = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(delta_long); tmp = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(delta_long);
if (tmp > .999999999999999) { if (tmp > .999999999999999) {
/* Station points coincide, use an Omni! */ /* Station points coincide, use an Omni! */
*distance = 0.0; *distance = 0.0;
*azimuth = 0.0; *azimuth = 0.0;
return RIG_OK; return RIG_OK;
} }
if (tmp < -.999999) { if (tmp < -.999999) {
/* /*
* points are antipodal, it's straight down. * points are antipodal, it's straight down.
* Station is equal distance in all Azimuths. * Station is equal distance in all Azimuths.
* So take 180 Degrees of arc times 60 nm, * So take 180 Degrees of arc times 60 nm,
* and you get 10800 nm, or whatever units... * and you get 10800 nm, or whatever units...
*/ */
*distance = 180.0 * ARC_IN_KM; *distance = 180.0 * ARC_IN_KM;
*azimuth = 0.0; *azimuth = 0.0;
return RIG_OK; return RIG_OK;
} }
arc = acos(tmp); arc = acos(tmp);
/* /*
* One degree of arc is 60 Nautical miles * One degree of arc is 60 Nautical miles
* at the surface of the earth, 111.2 km, or 69.1 sm * at the surface of the earth, 111.2 km, or 69.1 sm
* This method is easier than the one in the handbook * This method is easier than the one in the handbook
*/ */
*distance = ARC_IN_KM * RADIAN * arc;
/* Short Path */
/* Change to azimuth computation by Dave Freese, W1HKJ */
az = RADIAN * atan2(sin(lon2 - lon1) * cos(lat2),
(cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon2 - lon1)));
*distance = ARC_IN_KM * RADIAN * arc; az = fmod(360.0 + az, 360.0);
/* Short Path */ if (az < 0.0) {
/* Change to azimuth computation by Dave Freese, W1HKJ */ az += 360.0;
} else if (az >= 360.0) {
az -= 360.0;
}
az = RADIAN * atan2(sin(lon2 - lon1) * cos(lat2), *azimuth = floor(az + 0.5);
(cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon2 - lon1)));
az = fmod(360.0 + az, 360.0); return RIG_OK;
if (az < 0.0)
az += 360.0;
else if (az >= 360.0)
az -= 360.0;
*azimuth = floor(az + 0.5);
return RIG_OK;
} }
/** /**
* \brief Calculate the long path distance between two points. * \brief Calculate the long path distance between two points.
* \param distance The shortpath distance * \param distance The shortpath distance
* *
* Calculate the long path (respective of the short path) * Calculate the long path (respective of the short path)
* of a given distance. * of a given distance.
@ -567,14 +621,17 @@ int HAMLIB_API qrb(double lon1, double lat1, double lon2, double lat2, double *d
* *
* \sa qrb() * \sa qrb()
*/ */
double HAMLIB_API distance_long_path(double distance)
{
rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
double HAMLIB_API distance_long_path(double distance) { return (ARC_IN_KM * 360.0) - distance;
return (ARC_IN_KM * 360.0) - distance;
} }
/** /**
* \brief Calculate the long path bearing between two points. * \brief Calculate the long path bearing between two points.
* \param azimuth The shortpath bearing--0.0 to 360.0 degrees * \param azimuth The shortpath bearing--0.0 to 360.0 degrees
* *
* Calculate the long path (respective of the short path) * Calculate the long path (respective of the short path)
* of a given bearing. * of a given bearing.
@ -584,18 +641,21 @@ double HAMLIB_API distance_long_path(double distance) {
* *
* \sa qrb() * \sa qrb()
*/ */
double HAMLIB_API azimuth_long_path(double azimuth)
{
rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
double HAMLIB_API azimuth_long_path(double azimuth) { if (azimuth == 0.0 || azimuth == 360.0) {
if (azimuth == 0.0 || azimuth == 360.0)
return 180.0; return 180.0;
else if (azimuth > 0.0 && azimuth < 180.0) } else if (azimuth > 0.0 && azimuth < 180.0) {
return 180.0 + azimuth; return 180.0 + azimuth;
else if (azimuth == 180.0) } else if (azimuth == 180.0) {
return 0.0; return 0.0;
else if (azimuth > 180.0 && azimuth < 360.0) } else if (azimuth > 180.0 && azimuth < 360.0) {
return (180.0 - azimuth) * -1.0; return (180.0 - azimuth) * -1.0;
else } else {
return -RIG_EINVAL; return -RIG_EINVAL;
}
} }
/*! @} */ /*! @} */

1656
src/mem.c

Plik diff jest za duży Load Diff

Plik diff jest za duży Load Diff

Wyświetl plik

@ -26,7 +26,7 @@
/* /*
* Carefull!! These marcos are NOT reentrant! * Carefull!! These macros are NOT reentrant!
* ie. they may not be executed atomically, * ie. they may not be executed atomically,
* thus not ensure mutual exclusion. * thus not ensure mutual exclusion.
* Fix it when making Hamlib reentrant! --SF * Fix it when making Hamlib reentrant! --SF
@ -44,20 +44,31 @@ void dump_hex(const unsigned char ptr[], size_t size);
/* /*
* BCD conversion routines. * BCD conversion routines.
* to_bcd converts a long long int to a little endian BCD array, *
* and return a pointer to this array. * to_bcd() converts a long long int to a little endian BCD array,
* from_bcd converts a little endian BCD array to long long int * and return a pointer to this array.
*
* from_bcd() converts a little endian BCD array to long long int
* reprensentation, and return it. * reprensentation, and return it.
*
* bcd_len is the number of digits in the BCD array. * bcd_len is the number of digits in the BCD array.
*/ */
extern HAMLIB_EXPORT(unsigned char *) to_bcd(unsigned char bcd_data[], unsigned long long freq, unsigned bcd_len); extern HAMLIB_EXPORT(unsigned char *) to_bcd(unsigned char bcd_data[],
extern HAMLIB_EXPORT(unsigned long long) from_bcd(const unsigned char bcd_data[], unsigned bcd_len); unsigned long long freq,
unsigned bcd_len);
extern HAMLIB_EXPORT(unsigned long long) from_bcd(const unsigned char bcd_data[],
unsigned bcd_len);
/* /*
* same as to_bcd and from_bcd, but in Big Endian mode * same as to_bcd() and from_bcd(), but in Big Endian mode
*/ */
extern HAMLIB_EXPORT(unsigned char *) to_bcd_be(unsigned char bcd_data[], unsigned long long freq, unsigned bcd_len); extern HAMLIB_EXPORT(unsigned char *) to_bcd_be(unsigned char bcd_data[],
extern HAMLIB_EXPORT(unsigned long long) from_bcd_be(const unsigned char bcd_data[], unsigned bcd_len); unsigned long long freq,
unsigned bcd_len);
extern HAMLIB_EXPORT(unsigned long long) from_bcd_be(const unsigned char bcd_data[],
unsigned bcd_len);
extern HAMLIB_EXPORT(int) sprintf_freq(char *str, freq_t); extern HAMLIB_EXPORT(int) sprintf_freq(char *str, freq_t);
@ -77,7 +88,9 @@ extern int no_restore_ai;
#include <sys/time.h> #include <sys/time.h>
#endif #endif
extern HAMLIB_EXPORT(int) rig_check_cache_timeout(const struct timeval *tv, int timeout); extern HAMLIB_EXPORT(int) rig_check_cache_timeout(const struct timeval *tv,
int timeout);
extern HAMLIB_EXPORT(void) rig_force_cache_timeout(struct timeval *tv); extern HAMLIB_EXPORT(void) rig_force_cache_timeout(struct timeval *tv);

Wyświetl plik

@ -60,12 +60,12 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#elif HAVE_WS2TCPIP_H #elif HAVE_WS2TCPIP_H
#include <ws2tcpip.h> #include <ws2tcpip.h>
# if defined(HAVE_WSPIAPI_H) # if defined(HAVE_WSPIAPI_H)
# include <wspiapi.h> # include <wspiapi.h>
# endif # endif
#endif #endif
#include "hamlib/rig.h" #include <hamlib/rig.h>
#include "network.h" #include "network.h"
#include "misc.h" #include "misc.h"
@ -76,36 +76,37 @@ static int wsstarted;
#define NET_BUFFER_SIZE 64 #define NET_BUFFER_SIZE 64
static void handle_error (enum rig_debug_level_e lvl, const char *msg) static void handle_error(enum rig_debug_level_e lvl, const char *msg)
{ {
int e; int e;
#ifdef __MINGW32__ #ifdef __MINGW32__
LPVOID lpMsgBuf; LPVOID lpMsgBuf;
lpMsgBuf = (LPVOID)"Unknown error";
e = WSAGetLastError();
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, e,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
// Default language
(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);
}
lpMsgBuf = (LPVOID)"Unknown error";
e = WSAGetLastError();
if (FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, e,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
// Default language
(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 #else
e = errno; e = errno;
rig_debug (lvl, "%s: Network error %d: %s\n", msg, e, strerror (e)); rig_debug(lvl, "%s: Network error %d: %s\n", msg, e, strerror(e));
#endif #endif
} }
/** /**
* \brief Open network port using rig.state data * \brief Open network port using rig.state data
* *
@ -118,157 +119,184 @@ static void handle_error (enum rig_debug_level_e lvl, const char *msg)
*/ */
int network_open(hamlib_port_t *rp, int default_port) int network_open(hamlib_port_t *rp, int default_port)
{ {
int fd; /* File descriptor for the port */ int fd; /* File descriptor for the port */
int status; int status;
struct addrinfo hints, *res, *saved_res; struct addrinfo hints, *res, *saved_res;
char *hoststr = NULL, *portstr = NULL, *bracketstr1, *bracketstr2; char *hoststr = NULL, *portstr = NULL, *bracketstr1, *bracketstr2;
char hostname[FILPATHLEN]; char hostname[FILPATHLEN];
char defaultportstr[8]; char defaultportstr[8];
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
#ifdef __MINGW32__ #ifdef __MINGW32__
WSADATA wsadata; WSADATA wsadata;
if (!(wsstarted++) && WSAStartup(MAKEWORD(1,1), &wsadata) == SOCKET_ERROR) {
rig_debug(RIG_DEBUG_ERR, "Error creating socket\n"); if (!(wsstarted++) && WSAStartup(MAKEWORD(1, 1), &wsadata) == SOCKET_ERROR) {
return -RIG_EIO; rig_debug(RIG_DEBUG_ERR, "%s: error creating socket\n", __func__);
} return -RIG_EIO;
}
#endif #endif
if (!rp) if (!rp) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC; hints.ai_family = PF_UNSPEC;
if (rp->type.rig == RIG_PORT_UDP_NETWORK)
hints.ai_socktype = SOCK_DGRAM;
else
hints.ai_socktype = SOCK_STREAM;
hoststr = NULL; /* default of all local interfaces */ if (rp->type.rig == RIG_PORT_UDP_NETWORK) {
if (rp->pathname[0] == ':') hints.ai_socktype = SOCK_DGRAM;
{ } else {
portstr = rp->pathname + 1; hints.ai_socktype = SOCK_STREAM;
} }
else
{
if (strlen (rp->pathname))
{
strncpy(hostname, rp->pathname, FILPATHLEN-1);
hoststr = hostname;
/* look for IPv6 numeric form [<addr>] */
bracketstr1 = strchr(hoststr, '[');
bracketstr2 = strrchr(hoststr, ']');
if (bracketstr1 && bracketstr2 && bracketstr2 > bracketstr1)
{
hoststr = bracketstr1 + 1;
*bracketstr2 = '\0';
portstr = bracketstr2 + 1; /* possible port after ]: */
}
else
{
bracketstr2 = NULL;
portstr = hoststr; /* possible port after : */
}
/* search last ':' */
portstr = strrchr(portstr, ':');
if (portstr)
{
*portstr++ = '\0';
}
}
if (!portstr)
{
sprintf(defaultportstr, "%d", default_port);
portstr = defaultportstr;
}
}
status=getaddrinfo(hoststr, portstr, &hints, &res); /* default of all local interfaces */
if (status != 0) { hoststr = NULL;
rig_debug(RIG_DEBUG_ERR, "Cannot get host \"%s\": %s\n",
rp->pathname, gai_strerror(errno));
return -RIG_ECONF;
}
saved_res = res;
/* we don't want a signal when connection get broken */ if (rp->pathname[0] == ':') {
portstr = rp->pathname + 1;
} else {
if (strlen(rp->pathname)) {
strncpy(hostname, rp->pathname, FILPATHLEN - 1);
hoststr = hostname;
/* look for IPv6 numeric form [<addr>] */
bracketstr1 = strchr(hoststr, '[');
bracketstr2 = strrchr(hoststr, ']');
if (bracketstr1 && bracketstr2 && bracketstr2 > bracketstr1) {
hoststr = bracketstr1 + 1;
*bracketstr2 = '\0';
portstr = bracketstr2 + 1; /* possible port after ]: */
} else {
bracketstr2 = NULL;
portstr = hoststr; /* possible port after : */
}
/* search last ':' */
portstr = strrchr(portstr, ':');
if (portstr) {
*portstr++ = '\0';
}
}
if (!portstr) {
sprintf(defaultportstr, "%d", default_port);
portstr = defaultportstr;
}
}
status = getaddrinfo(hoststr, portstr, &hints, &res);
if (status != 0) {
rig_debug(RIG_DEBUG_ERR,
"%s: cannot get host \"%s\": %s\n",
__func__,
rp->pathname,
gai_strerror(errno));
return -RIG_ECONF;
}
saved_res = res;
/* we don't want a signal when connection get broken */
#ifdef SIGPIPE #ifdef SIGPIPE
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
#endif #endif
do do {
{ fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (fd < 0)
{
handle_error (RIG_DEBUG_ERR, "socket");
freeaddrinfo (saved_res);
return -RIG_EIO;
}
if ((status = connect(fd, res->ai_addr, res->ai_addrlen)) == 0) if (fd < 0) {
{ handle_error(RIG_DEBUG_ERR, "socket");
break; freeaddrinfo(saved_res);
} return -RIG_EIO;
handle_error (RIG_DEBUG_WARN, "connect (trying next interface)"); }
if ((status = connect(fd, res->ai_addr, res->ai_addrlen)) == 0) {
break;
}
handle_error(RIG_DEBUG_WARN, "connect (trying next interface)");
#ifdef __MINGW32__ #ifdef __MINGW32__
closesocket (fd); closesocket(fd);
#else #else
close (fd); close(fd);
#endif #endif
} while ((res = res->ai_next) != NULL); } while ((res = res->ai_next) != NULL);
freeaddrinfo (saved_res); freeaddrinfo(saved_res);
if (NULL == res) { if (NULL == res) {
rig_debug (RIG_DEBUG_ERR, "Failed to connect to %s\n" , rp->pathname); rig_debug(RIG_DEBUG_ERR,
return -RIG_EIO; "%s: failed to connect to %s\n",
} __func__,
rp->pathname);
return -RIG_EIO;
}
rp->fd = fd; rp->fd = fd;
return RIG_OK;
return RIG_OK;
} }
/** /**
* \brief Clears any data in the read buffer of the socket * \brief Clears any data in the read buffer of the socket
* *
* \param rp Port data structure * \param rp Port data structure
*/ */
void network_flush(hamlib_port_t* rp) void network_flush(hamlib_port_t *rp)
{ {
#ifdef __MINGW32__ #ifdef __MINGW32__
ULONG len = 0; ULONG len = 0;
#else #else
uint len = 0; uint len = 0;
#endif #endif
char buffer[NET_BUFFER_SIZE] = { 0 }; char buffer[NET_BUFFER_SIZE] = { 0 };
for (;;) {
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
for (;;) {
#ifdef __MINGW32__ #ifdef __MINGW32__
ioctlsocket (rp->fd, FIONREAD, &len); ioctlsocket(rp->fd, FIONREAD, &len);
#else #else
ioctl(rp->fd, FIONREAD, &len); ioctl(rp->fd, FIONREAD, &len);
#endif #endif
if (len > 0) {
len = read(rp->fd, &buffer, len < NET_BUFFER_SIZE ? len : NET_BUFFER_SIZE); if (len > 0) {
rig_debug(RIG_DEBUG_WARN, "Network data cleared: %s\n", buffer); len = read(rp->fd, &buffer, len < NET_BUFFER_SIZE ? len : NET_BUFFER_SIZE);
} else { rig_debug(RIG_DEBUG_WARN,
break; "%s: network data cleared: %s\n",
__func__,
buffer);
} else {
break;
}
} }
}
} }
int network_close(hamlib_port_t *rp) int network_close(hamlib_port_t *rp)
{ {
int ret; int ret;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
#ifdef __MINGW32__ #ifdef __MINGW32__
ret = closesocket(rp->fd); ret = closesocket(rp->fd);
if (--wsstarted)
WSACleanup(); if (--wsstarted) {
WSACleanup();
}
#else #else
ret = close(rp->fd); ret = close(rp->fd);
#endif #endif
return ret; return ret;
} }
/** @} */ /** @} */

Wyświetl plik

@ -1,12 +1,12 @@
/* NT Parport Access stuff - Matthew Duggan (2002) */ /* NT Parport Access stuff - Matthew Duggan (2002) */
/* /*
* ParallelVdm Device (0x2C) is mostly undocumented, used by VDM for parallel * ParallelVdm Device (0x2C) is mostly undocumented, used by VDM for parallel
* port compatibility. * port compatibility.
*/ */
/* /*
* Different from CTL_CODE in DDK, limited to ParallelVdm but makes this * Different from CTL_CODE in DDK, limited to ParallelVdm but makes this
* code cleaner. * code cleaner.
*/ */
@ -28,28 +28,26 @@
*/ */
/* The status pin functions operate in terms of these bits: */ /* The status pin functions operate in terms of these bits: */
enum ieee1284_status_bits enum ieee1284_status_bits {
{ S1284_NFAULT = 0x08,
S1284_NFAULT = 0x08, S1284_SELECT = 0x10,
S1284_SELECT = 0x10, S1284_PERROR = 0x20,
S1284_PERROR = 0x20, S1284_NACK = 0x40,
S1284_NACK = 0x40, S1284_BUSY = 0x80,
S1284_BUSY = 0x80, /* To convert those values into PC-style register values, use this: */
/* To convert those values into PC-style register values, use this: */ S1284_INVERTED = S1284_BUSY
S1284_INVERTED = S1284_BUSY
}; };
/* The control pin functions operate in terms of these bits: */ /* The control pin functions operate in terms of these bits: */
enum ieee1284_control_bits enum ieee1284_control_bits {
{ C1284_NSTROBE = 0x01,
C1284_NSTROBE = 0x01, C1284_NAUTOFD = 0x02,
C1284_NAUTOFD = 0x02, C1284_NINIT = 0x04,
C1284_NINIT = 0x04, C1284_NSELECTIN = 0x08,
C1284_NSELECTIN = 0x08, /* To convert those values into PC-style register values, use this: */
/* To convert those values into PC-style register values, use this: */ C1284_INVERTED = (C1284_NSTROBE
C1284_INVERTED = (C1284_NSTROBE| | C1284_NAUTOFD
C1284_NAUTOFD| | C1284_NSELECTIN)
C1284_NSELECTIN)
}; };
#endif /* _PAR_NT_H */ #endif /* _PAR_NT_H */

Wyświetl plik

@ -60,7 +60,7 @@
#include <winbase.h> #include <winbase.h>
#endif #endif
#include "hamlib/rig.h" #include <hamlib/rig.h>
#include "parallel.h" #include "parallel.h"
#ifdef HAVE_LINUX_PPDEV_H #ifdef HAVE_LINUX_PPDEV_H
@ -78,14 +78,14 @@
* We toggle them so that this weirdness doesn't get propagated * We toggle them so that this weirdness doesn't get propagated
* through our interface. * through our interface.
*/ */
#define CP_ACTIVE_LOW_BITS 0x0B #define CP_ACTIVE_LOW_BITS 0x0B
/* /*
* These status port bits are active low. * These status port bits are active low.
* We toggle them so that this weirdness doesn't get propagated * We toggle them so that this weirdness doesn't get propagated
* through our interface. * through our interface.
*/ */
#define SP_ACTIVE_LOW_BITS 0x80 #define SP_ACTIVE_LOW_BITS 0x80
/* /*
Pinout table of parallel port from http://en.wikipedia.org/wiki/Parallel_port#Pinouts Pinout table of parallel port from http://en.wikipedia.org/wiki/Parallel_port#Pinouts
@ -112,6 +112,7 @@
* means low true, e.g., *Strobe. * means low true, e.g., *Strobe.
*/ */
/** /**
* \brief Open Parallel Port * \brief Open Parallel Port
* \param port * \param port
@ -120,85 +121,107 @@
* TODO: to be called before exiting: atexit(parport_cleanup) * TODO: to be called before exiting: atexit(parport_cleanup)
* void parport_cleanup() { ioctl(fd, PPRELEASE); } * void parport_cleanup() { ioctl(fd, PPRELEASE); }
*/ */
int par_open(hamlib_port_t *port) int par_open(hamlib_port_t *port)
{ {
int fd; int fd;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
#ifdef HAVE_LINUX_PPDEV_H #ifdef HAVE_LINUX_PPDEV_H
int mode; int mode;
#endif #endif
#if defined (__WIN64__) || defined(__WIN32__) #if defined (__WIN64__) || defined(__WIN32__)
HANDLE handle; HANDLE handle;
#endif #endif
if (!port->pathname[0]) if (!port->pathname[0]) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
#ifdef HAVE_LINUX_PPDEV_H #ifdef HAVE_LINUX_PPDEV_H
/* TODO: open with O_NONBLOCK ? */ /* TODO: open with O_NONBLOCK ? */
fd = open(port->pathname, O_RDWR); fd = open(port->pathname, O_RDWR);
if (fd < 0) { if (fd < 0) {
rig_debug(RIG_DEBUG_ERR, "Opening device \"%s\": %s\n", port->pathname, strerror(errno)); rig_debug(RIG_DEBUG_ERR,
return -RIG_EIO; "%s: opening device \"%s\": %s\n",
} __func__,
port->pathname,
strerror(errno));
return -RIG_EIO;
}
mode = IEEE1284_MODE_COMPAT; mode = IEEE1284_MODE_COMPAT;
if (ioctl(fd, PPSETMODE, &mode) != 0) { if (ioctl(fd, PPSETMODE, &mode) != 0) {
rig_debug(RIG_DEBUG_ERR, "PPSETMODE \"%s\": %s\n", port->pathname, strerror(errno)); rig_debug(RIG_DEBUG_ERR, "%s: PPSETMODE \"%s\": %s\n",
close(fd); __func__,
return -RIG_EIO; port->pathname,
} strerror(errno));
close(fd);
return -RIG_EIO;
}
#elif defined(HAVE_DEV_PPBUS_PPI_H) #elif defined(HAVE_DEV_PPBUS_PPI_H)
fd = open(port->pathname, O_RDWR); fd = open(port->pathname, O_RDWR);
if (fd < 0) { if (fd < 0) {
rig_debug(RIG_DEBUG_ERR, "Opening device \"%s\": %s\n", port->pathname, strerror(errno)); rig_debug(RIG_DEBUG_ERR,
return -RIG_EIO; "%s: opening device \"%s\": %s\n",
} __func__,
port->pathname,
strerror(errno));
return -RIG_EIO;
}
#elif defined(__WIN64__) || defined(__WIN32__) #elif defined(__WIN64__) || defined(__WIN32__)
handle = CreateFile(port->pathname, GENERIC_READ | GENERIC_WRITE, handle = CreateFile(port->pathname, GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL); 0, NULL, OPEN_EXISTING, 0, NULL);
if (handle == INVALID_HANDLE_VALUE) { if (handle == INVALID_HANDLE_VALUE) {
rig_debug(RIG_DEBUG_ERR, "Opening device \"%s\"\n", port->pathname); rig_debug(RIG_DEBUG_ERR,
CloseHandle(handle); "%s: opening device \"%s\"\n",
return -RIG_EIO; __func__,
} else { port->pathname);
fd = _open_osfhandle((intptr_t)handle, _O_APPEND | _O_RDONLY); CloseHandle(handle);
return -RIG_EIO;
} else {
fd = _open_osfhandle((intptr_t)handle, _O_APPEND | _O_RDONLY);
if (fd == -1) if (fd == -1) {
return -RIG_EIO; return -RIG_EIO;
} }
}
#else #else
return -RIG_ENIMPL; return -RIG_ENIMPL;
#endif #endif
port->fd = fd; port->fd = fd;
return fd; return fd;
} }
/** /**
* \brief Close Parallel Port * \brief Close Parallel Port
* \param port * \param port
*/ */
int par_close(hamlib_port_t *port) int par_close(hamlib_port_t *port)
{ {
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
#ifdef HAVE_LINUX_PPDEV_H #ifdef HAVE_LINUX_PPDEV_H
#elif defined(HAVE_DEV_PPBUS_PPI_H) #elif defined(HAVE_DEV_PPBUS_PPI_H)
#elif defined(__WIN64__) || defined(__WIN32__) #elif defined(__WIN64__) || defined(__WIN32__)
_close(port->fd); _close(port->fd);
return RIG_OK; return RIG_OK;
#endif #endif
return close(port->fd); return close(port->fd);
} }
/** /**
* \brief Send data on Parallel port * \brief Send data on Parallel port
* \param port * \param port
@ -206,35 +229,38 @@ int par_close(hamlib_port_t *port)
*/ */
int HAMLIB_API par_write_data(hamlib_port_t *port, unsigned char data) int HAMLIB_API par_write_data(hamlib_port_t *port, unsigned char data)
{ {
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
#ifdef HAVE_LINUX_PPDEV_H #ifdef HAVE_LINUX_PPDEV_H
int status; int status;
status = ioctl(port->fd, PPWDATA, &data); status = ioctl(port->fd, PPWDATA, &data);
return status == 0 ? RIG_OK : -RIG_EIO; return status == 0 ? RIG_OK : -RIG_EIO;
#elif defined(HAVE_DEV_PPBUS_PPI_H) #elif defined(HAVE_DEV_PPBUS_PPI_H)
int status; int status;
status = ioctl(port->fd, PPISDATA, &data); status = ioctl(port->fd, PPISDATA, &data);
return status == 0 ? RIG_OK : -RIG_EIO; return status == 0 ? RIG_OK : -RIG_EIO;
#elif defined(__WIN64__) || defined(__WIN32__) #elif defined(__WIN64__) || defined(__WIN32__)
unsigned int dummy; unsigned int dummy;
intptr_t handle; intptr_t handle;
handle = _get_osfhandle(port->fd); handle = _get_osfhandle(port->fd);
if (handle != (intptr_t)INVALID_HANDLE_VALUE) { if (handle != (intptr_t)INVALID_HANDLE_VALUE) {
if (!(DeviceIoControl((HANDLE)handle, NT_IOCTL_DATA, &data, sizeof(data), if (!(DeviceIoControl((HANDLE)handle, NT_IOCTL_DATA, &data, sizeof(data),
NULL, 0, (LPDWORD)&dummy, NULL))) { NULL, 0, (LPDWORD)&dummy, NULL))) {
rig_debug(RIG_DEBUG_ERR, "%s: DeviceIoControl failed!\n", __FUNCTION__); rig_debug(RIG_DEBUG_ERR, "%s: DeviceIoControl failed!\n", __func__);
return -RIG_EIO; return -RIG_EIO;
} }
} }
return RIG_OK; return RIG_OK;
#else #else
return -RIG_ENIMPL; return -RIG_ENIMPL;
#endif #endif
} }
/** /**
* \brief Receive data on Parallel port * \brief Receive data on Parallel port
* \param port * \param port
@ -242,37 +268,40 @@ int HAMLIB_API par_write_data(hamlib_port_t *port, unsigned char data)
*/ */
int HAMLIB_API par_read_data(hamlib_port_t *port, unsigned char *data) int HAMLIB_API par_read_data(hamlib_port_t *port, unsigned char *data)
{ {
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
#ifdef HAVE_LINUX_PPDEV_H #ifdef HAVE_LINUX_PPDEV_H
int status; int status;
status = ioctl(port->fd, PPRDATA, data); status = ioctl(port->fd, PPRDATA, data);
return status == 0 ? RIG_OK : -RIG_EIO; return status == 0 ? RIG_OK : -RIG_EIO;
#elif defined(HAVE_DEV_PPBUS_PPI_H) #elif defined(HAVE_DEV_PPBUS_PPI_H)
int status; int status;
status = ioctl(port->fd, PPIGDATA, &data); status = ioctl(port->fd, PPIGDATA, &data);
return status == 0 ? RIG_OK : -RIG_EIO; return status == 0 ? RIG_OK : -RIG_EIO;
#elif defined(__WIN64__) || defined(__WIN32__) #elif defined(__WIN64__) || defined(__WIN32__)
unsigned char ret; unsigned char ret;
unsigned int dummy; unsigned int dummy;
intptr_t handle; intptr_t handle;
handle = _get_osfhandle(port->fd); handle = _get_osfhandle(port->fd);
if (handle != (intptr_t)INVALID_HANDLE_VALUE) { if (handle != (intptr_t)INVALID_HANDLE_VALUE) {
if (!(DeviceIoControl((HANDLE)handle, NT_IOCTL_STATUS, NULL, 0, &ret, if (!(DeviceIoControl((HANDLE)handle, NT_IOCTL_STATUS, NULL, 0, &ret,
sizeof(ret), (LPDWORD)&dummy, NULL))) { sizeof(ret), (LPDWORD)&dummy, NULL))) {
rig_debug(RIG_DEBUG_ERR, "%s: DeviceIoControl failed!\n", __FUNCTION__); rig_debug(RIG_DEBUG_ERR, "%s: DeviceIoControl failed!\n", __func__);
return -RIG_EIO; return -RIG_EIO;
} }
} }
*data = ret ^ S1284_INVERTED; *data = ret ^ S1284_INVERTED;
return RIG_OK; return RIG_OK;
#else #else
return -RIG_ENIMPL; return -RIG_ENIMPL;
#endif #endif
} }
/** /**
* \brief Set control data for Parallel Port * \brief Set control data for Parallel Port
* \param port * \param port
@ -280,54 +309,71 @@ int HAMLIB_API par_read_data(hamlib_port_t *port, unsigned char *data)
*/ */
int HAMLIB_API par_write_control(hamlib_port_t *port, unsigned char control) int HAMLIB_API par_write_control(hamlib_port_t *port, unsigned char control)
{ {
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
#ifdef HAVE_LINUX_PPDEV_H #ifdef HAVE_LINUX_PPDEV_H
int status; int status;
unsigned char ctrl = control ^ CP_ACTIVE_LOW_BITS; unsigned char ctrl = control ^ CP_ACTIVE_LOW_BITS;
status = ioctl(port->fd, PPWCONTROL, &ctrl); status = ioctl(port->fd, PPWCONTROL, &ctrl);
if (status < 0) if (status < 0) {
rig_debug(RIG_DEBUG_ERR, "ioctl(PPWCONTROL) failed: %s\n", strerror(errno)); rig_debug(RIG_DEBUG_ERR,
"%s: ioctl(PPWCONTROL) failed: %s\n",
__func__,
strerror(errno));
}
return status == 0 ? RIG_OK : -RIG_EIO; return status == 0 ? RIG_OK : -RIG_EIO;
#elif defined(HAVE_DEV_PPBUS_PPI_H) #elif defined(HAVE_DEV_PPBUS_PPI_H)
int status; int status;
unsigned char ctrl = control ^ CP_ACTIVE_LOW_BITS; unsigned char ctrl = control ^ CP_ACTIVE_LOW_BITS;
status = ioctl(port->fd, PPISCTRL, &ctrl); status = ioctl(port->fd, PPISCTRL, &ctrl);
return status == 0 ? RIG_OK : -RIG_EIO; return status == 0 ? RIG_OK : -RIG_EIO;
#elif defined(__WIN64__) || defined(__WIN32__) #elif defined(__WIN64__) || defined(__WIN32__)
unsigned char ctr = control; unsigned char ctr = control;
unsigned char dummyc; unsigned char dummyc;
unsigned int dummy; unsigned int dummy;
const unsigned char wm = (C1284_NSTROBE | const unsigned char wm = (C1284_NSTROBE
C1284_NAUTOFD | | C1284_NAUTOFD
C1284_NINIT | | C1284_NINIT
C1284_NSELECTIN); | C1284_NSELECTIN);
intptr_t handle; intptr_t handle;
if (ctr & 0x20) { if (ctr & 0x20) {
rig_debug(RIG_DEBUG_WARN, "use ieee1284_data_dir to change data line direction!\n"); rig_debug(RIG_DEBUG_WARN,
} "%s: use ieee1284_data_dir to change data line direction!\n",
__func__);
}
/* Deal with inversion issues. */ /* Deal with inversion issues. */
ctr ^= wm & C1284_INVERTED; ctr ^= wm & C1284_INVERTED;
ctr = (ctr & ~wm) ^ (ctr & wm); ctr = (ctr & ~wm) ^ (ctr & wm);
handle = _get_osfhandle(port->fd); handle = _get_osfhandle(port->fd);
if (handle != (intptr_t)INVALID_HANDLE_VALUE) { if (handle != (intptr_t)INVALID_HANDLE_VALUE) {
if (!(DeviceIoControl((HANDLE)handle, NT_IOCTL_CONTROL, &ctr, if (!(DeviceIoControl((HANDLE)handle,
sizeof(ctr), &dummyc, sizeof(dummyc), (LPDWORD)&dummy, NULL))) { NT_IOCTL_CONTROL,
rig_debug(RIG_DEBUG_ERR, "frob_control: DeviceIoControl failed!\n"); &ctr,
return -RIG_EIO; sizeof(ctr),
} &dummyc,
} sizeof(dummyc),
(LPDWORD)&dummy,
NULL))) {
rig_debug(RIG_DEBUG_ERR,
"%s: frob_control: DeviceIoControl failed!\n",
__func__);
return -RIG_EIO;
}
}
return RIG_OK; return RIG_OK;
#else #else
return -RIG_ENIMPL; return -RIG_ENIMPL;
#endif #endif
} }
/** /**
* \brief Read control data for Parallel Port * \brief Read control data for Parallel Port
* \param port * \param port
@ -335,45 +381,53 @@ int HAMLIB_API par_write_control(hamlib_port_t *port, unsigned char control)
*/ */
int HAMLIB_API par_read_control(hamlib_port_t *port, unsigned char *control) int HAMLIB_API par_read_control(hamlib_port_t *port, unsigned char *control)
{ {
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
#ifdef HAVE_LINUX_PPDEV_H #ifdef HAVE_LINUX_PPDEV_H
int status; int status;
unsigned char ctrl; unsigned char ctrl;
status = ioctl(port->fd, PPRCONTROL, &ctrl); status = ioctl(port->fd, PPRCONTROL, &ctrl);
if (status < 0) if (status < 0) {
rig_debug(RIG_DEBUG_ERR, "ioctl(PPRCONTROL) failed: %s\n", strerror(errno)); rig_debug(RIG_DEBUG_ERR,
"%s: ioctl(PPRCONTROL) failed: %s\n",
__func__,
strerror(errno));
}
*control = ctrl ^ CP_ACTIVE_LOW_BITS; *control = ctrl ^ CP_ACTIVE_LOW_BITS;
return status == 0 ? RIG_OK : -RIG_EIO; return status == 0 ? RIG_OK : -RIG_EIO;
#elif defined(HAVE_DEV_PPBUS_PPI_H) #elif defined(HAVE_DEV_PPBUS_PPI_H)
int status; int status;
unsigned char ctrl; unsigned char ctrl;
status = ioctl(port->fd, PPIGCTRL, &ctrl); status = ioctl(port->fd, PPIGCTRL, &ctrl);
*control = ctrl ^ CP_ACTIVE_LOW_BITS; *control = ctrl ^ CP_ACTIVE_LOW_BITS;
return status == 0 ? RIG_OK : -RIG_EIO; return status == 0 ? RIG_OK : -RIG_EIO;
#elif defined(__WIN64__) || defined(__WIN32__) #elif defined(__WIN64__) || defined(__WIN32__)
unsigned char ret; unsigned char ret;
unsigned int dummy; unsigned int dummy;
intptr_t handle; intptr_t handle;
handle = _get_osfhandle(port->fd); handle = _get_osfhandle(port->fd);
if (handle != (intptr_t)INVALID_HANDLE_VALUE) { if (handle != (intptr_t)INVALID_HANDLE_VALUE) {
if (!(DeviceIoControl((HANDLE)handle, NT_IOCTL_CONTROL, NULL, 0, &ret, if (!(DeviceIoControl((HANDLE)handle, NT_IOCTL_CONTROL, NULL, 0, &ret,
sizeof(ret), (LPDWORD)&dummy, NULL))) { sizeof(ret), (LPDWORD)&dummy, NULL))) {
rig_debug(RIG_DEBUG_ERR, "%s: DeviceIoControl failed!\n", __FUNCTION__); rig_debug(RIG_DEBUG_ERR, "%s: DeviceIoControl failed!\n", __func__);
return -RIG_EIO; return -RIG_EIO;
} }
} }
*control = ret ^ S1284_INVERTED; *control = ret ^ S1284_INVERTED;
return RIG_OK;
return RIG_OK;
#else #else
return -RIG_ENIMPL; return -RIG_ENIMPL;
#endif #endif
} }
/** /**
* \brief Get parallel port status * \brief Get parallel port status
* \param port * \param port
@ -382,41 +436,45 @@ int HAMLIB_API par_read_control(hamlib_port_t *port, unsigned char *control)
*/ */
int HAMLIB_API par_read_status(hamlib_port_t *port, unsigned char *status) int HAMLIB_API par_read_status(hamlib_port_t *port, unsigned char *status)
{ {
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
#ifdef HAVE_LINUX_PPDEV_H #ifdef HAVE_LINUX_PPDEV_H
int ret; int ret;
unsigned char sta; unsigned char sta;
ret = ioctl(port->fd, PPRSTATUS, &sta); ret = ioctl(port->fd, PPRSTATUS, &sta);
*status = sta ^ SP_ACTIVE_LOW_BITS; *status = sta ^ SP_ACTIVE_LOW_BITS;
return ret == 0 ? RIG_OK : -RIG_EIO; return ret == 0 ? RIG_OK : -RIG_EIO;
#elif defined(HAVE_DEV_PPBUS_PPI_H) #elif defined(HAVE_DEV_PPBUS_PPI_H)
int ret; int ret;
unsigned char sta; unsigned char sta;
ret = ioctl(port->fd, PPIGSTATUS, &sta); ret = ioctl(port->fd, PPIGSTATUS, &sta);
*status = sta ^ SP_ACTIVE_LOW_BITS; *status = sta ^ SP_ACTIVE_LOW_BITS;
return ret == 0 ? RIG_OK : -RIG_EIO; return ret == 0 ? RIG_OK : -RIG_EIO;
#elif defined(__WIN64__) || defined(__WIN32__) #elif defined(__WIN64__) || defined(__WIN32__)
unsigned char ret; unsigned char ret;
unsigned int dummy; unsigned int dummy;
intptr_t handle; intptr_t handle;
handle = _get_osfhandle(port->fd); handle = _get_osfhandle(port->fd);
if (handle != (intptr_t)INVALID_HANDLE_VALUE) { if (handle != (intptr_t)INVALID_HANDLE_VALUE) {
if (!(DeviceIoControl((HANDLE)handle, NT_IOCTL_STATUS, NULL, 0, &ret, if (!(DeviceIoControl((HANDLE)handle, NT_IOCTL_STATUS, NULL, 0, &ret,
sizeof(ret), (LPDWORD)&dummy, NULL))) { sizeof(ret), (LPDWORD)&dummy, NULL))) {
rig_debug(RIG_DEBUG_ERR, "%s: DeviceIoControl failed!\n", __FUNCTION__); rig_debug(RIG_DEBUG_ERR, "%s: DeviceIoControl failed!\n", __func__);
return -RIG_EIO; return -RIG_EIO;
} }
} }
*status = ret ^ S1284_INVERTED; *status = ret ^ S1284_INVERTED;
return RIG_OK;
return RIG_OK;
#else #else
return -RIG_ENIMPL; return -RIG_ENIMPL;
#endif #endif
} }
/** /**
* \brief Get a lock on the Parallel Port * \brief Get a lock on the Parallel Port
* \param port * \param port
@ -424,23 +482,30 @@ int HAMLIB_API par_read_status(hamlib_port_t *port, unsigned char *status)
*/ */
int HAMLIB_API par_lock(hamlib_port_t *port) int HAMLIB_API par_lock(hamlib_port_t *port)
{ {
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
#ifdef HAVE_LINUX_PPDEV_H #ifdef HAVE_LINUX_PPDEV_H
if (ioctl(port->fd, PPCLAIM) < 0) { if (ioctl(port->fd, PPCLAIM) < 0) {
rig_debug(RIG_DEBUG_ERR, "Claiming device \"%s\": %s\n", port->pathname, strerror(errno)); rig_debug(RIG_DEBUG_ERR,
return -RIG_EIO; "%s: claiming device \"%s\": %s\n",
} __func__,
port->pathname,
strerror(errno));
return -RIG_EIO;
}
return RIG_OK; return RIG_OK;
#elif defined(HAVE_DEV_PPBUS_PPI_H) #elif defined(HAVE_DEV_PPBUS_PPI_H)
return RIG_OK; return RIG_OK;
#elif defined(__WIN64__) || defined(__WIN32__) #elif defined(__WIN64__) || defined(__WIN32__)
return RIG_OK; return RIG_OK;
#else #else
return -RIG_ENIMPL; return -RIG_ENIMPL;
#endif #endif
} }
/** /**
* \brief Release lock on Parallel Port * \brief Release lock on Parallel Port
* \param port * \param port
@ -448,23 +513,30 @@ int HAMLIB_API par_lock(hamlib_port_t *port)
*/ */
int HAMLIB_API par_unlock(hamlib_port_t *port) int HAMLIB_API par_unlock(hamlib_port_t *port)
{ {
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
#ifdef HAVE_LINUX_PPDEV_H #ifdef HAVE_LINUX_PPDEV_H
if (ioctl(port->fd, PPRELEASE) < 0) { if (ioctl(port->fd, PPRELEASE) < 0) {
rig_debug(RIG_DEBUG_ERR, "Releasing device \"%s\": %s\n", port->pathname, strerror(errno)); rig_debug(RIG_DEBUG_ERR,
return -RIG_EIO; "%s: releasing device \"%s\": %s\n",
} __func__,
port->pathname,
strerror(errno));
return -RIG_EIO;
}
return RIG_OK; return RIG_OK;
#elif defined(HAVE_DEV_PPBUS_PPI_H) #elif defined(HAVE_DEV_PPBUS_PPI_H)
return RIG_OK; return RIG_OK;
#elif defined(__WIN64__) || defined(__WIN32__) #elif defined(__WIN64__) || defined(__WIN32__)
return RIG_OK; return RIG_OK;
#else #else
return -RIG_ENIMPL; return -RIG_ENIMPL;
#endif #endif
} }
#ifndef PARPORT_CONTROL_STROBE #ifndef PARPORT_CONTROL_STROBE
#define PARPORT_CONTROL_STROBE 0x1 #define PARPORT_CONTROL_STROBE 0x1
#endif #endif
@ -472,6 +544,7 @@ int HAMLIB_API par_unlock(hamlib_port_t *port)
#define PARPORT_CONTROL_INIT 0x4 #define PARPORT_CONTROL_INIT 0x4
#endif #endif
/** /**
* \brief Set or unset Push to talk bit on Parallel Port * \brief Set or unset Push to talk bit on Parallel Port
* \param p * \param p
@ -480,42 +553,49 @@ int HAMLIB_API par_unlock(hamlib_port_t *port)
*/ */
int par_ptt_set(hamlib_port_t *p, ptt_t pttx) int par_ptt_set(hamlib_port_t *p, ptt_t pttx)
{ {
switch (p->type.ptt) { rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
case RIG_PTT_PARALLEL: {
unsigned char ctl;
int status;
par_lock(p); switch (p->type.ptt) {
status = par_read_control(p, &ctl); case RIG_PTT_PARALLEL: {
unsigned char ctl;
int status;
if (status != RIG_OK) par_lock(p);
return status; status = par_read_control(p, &ctl);
/* Enable CW & PTT - /STROBE bit (pin 1) */ if (status != RIG_OK) {
ctl &= ~PARPORT_CONTROL_STROBE; return status;
}
/* TODO: kill parm.parallel.pin? */ /* Enable CW & PTT - /STROBE bit (pin 1) */
ctl &= ~PARPORT_CONTROL_STROBE;
/* PTT keying - /INIT bit (pin 16) (inverted) */ /* TODO: kill parm.parallel.pin? */
if (pttx == RIG_PTT_ON)
ctl |= PARPORT_CONTROL_INIT;
else
ctl &= ~PARPORT_CONTROL_INIT;
status = par_write_control(p, ctl); /* PTT keying - /INIT bit (pin 16) (inverted) */
par_unlock(p); if (pttx == RIG_PTT_ON) {
return status; ctl |= PARPORT_CONTROL_INIT;
} } else {
ctl &= ~PARPORT_CONTROL_INIT;
}
default: status = par_write_control(p, ctl);
rig_debug(RIG_DEBUG_ERR, "Unsupported PTT type %d\n", par_unlock(p);
p->type.ptt); return status;
return -RIG_EINVAL; }
}
return RIG_OK; default:
rig_debug(RIG_DEBUG_ERR,
"%s: unsupported PTT type %d\n",
__func__,
p->type.ptt);
return -RIG_EINVAL;
}
return RIG_OK;
} }
/** /**
* \brief Get state of Push to Talk from Parallel Port * \brief Get state of Push to Talk from Parallel Port
* \param p * \param p
@ -524,30 +604,35 @@ int par_ptt_set(hamlib_port_t *p, ptt_t pttx)
*/ */
int par_ptt_get(hamlib_port_t *p, ptt_t *pttx) int par_ptt_get(hamlib_port_t *p, ptt_t *pttx)
{ {
switch (p->type.ptt) { rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
case RIG_PTT_PARALLEL: {
unsigned char ctl;
int status;
par_lock(p); switch (p->type.ptt) {
status = par_read_control(p, &ctl); case RIG_PTT_PARALLEL: {
par_unlock(p); unsigned char ctl;
int status;
*pttx = (ctl & PARPORT_CONTROL_INIT) && par_lock(p);
!(ctl & PARPORT_CONTROL_STROBE) ? status = par_read_control(p, &ctl);
RIG_PTT_ON : RIG_PTT_OFF; par_unlock(p);
return status;
}
default: *pttx = (ctl & PARPORT_CONTROL_INIT) &&
rig_debug(RIG_DEBUG_ERR, "Unsupported PTT type %d\n", !(ctl & PARPORT_CONTROL_STROBE) ?
p->type.ptt); RIG_PTT_ON : RIG_PTT_OFF;
return -RIG_ENAVAIL; return status;
} }
return RIG_OK; default:
rig_debug(RIG_DEBUG_ERR,
"Unsupported PTT type %d\n",
__func__,
p->type.ptt);
return -RIG_ENAVAIL;
}
return RIG_OK;
} }
/** /**
* \brief get Data Carrier Detect (squelch) from Parallel Port * \brief get Data Carrier Detect (squelch) from Parallel Port
* \param p * \param p
@ -556,24 +641,28 @@ int par_ptt_get(hamlib_port_t *p, ptt_t *pttx)
*/ */
int par_dcd_get(hamlib_port_t *p, dcd_t *dcdx) int par_dcd_get(hamlib_port_t *p, dcd_t *dcdx)
{ {
switch (p->type.dcd) { rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
case RIG_DCD_PARALLEL: {
unsigned char reg;
int status;
status = par_read_data(p, &reg); switch (p->type.dcd) {
*dcdx = reg & (1 << p->parm.parallel.pin) ? case RIG_DCD_PARALLEL: {
RIG_DCD_ON : RIG_DCD_OFF; unsigned char reg;
return status; int status;
}
default: status = par_read_data(p, &reg);
rig_debug(RIG_DEBUG_ERR, "Unsupported DCD type %d\n", *dcdx = reg & (1 << p->parm.parallel.pin) ?
p->type.dcd); RIG_DCD_ON : RIG_DCD_OFF;
return -RIG_ENAVAIL; return status;
} }
return RIG_OK; default:
rig_debug(RIG_DEBUG_ERR,
"%s: unsupported DCD type %d\n",
__func__,
p->type.dcd);
return -RIG_ENAVAIL;
}
return RIG_OK;
} }
/** @} */ /** @} */

Wyświetl plik

@ -69,10 +69,16 @@ int par_ptt_get(hamlib_port_t *p, ptt_t *pttx);
int par_dcd_get(hamlib_port_t *p, dcd_t *dcdx); int par_dcd_get(hamlib_port_t *p, dcd_t *dcdx);
extern HAMLIB_EXPORT(int) par_write_data(hamlib_port_t *p, unsigned char data); extern HAMLIB_EXPORT(int) par_write_data(hamlib_port_t *p, unsigned char data);
extern HAMLIB_EXPORT(int) par_write_control(hamlib_port_t *p, unsigned char control); extern HAMLIB_EXPORT(int) par_write_control(hamlib_port_t *p,
unsigned char control);
extern HAMLIB_EXPORT(int) par_read_data(hamlib_port_t *p, unsigned char *data); extern HAMLIB_EXPORT(int) par_read_data(hamlib_port_t *p, unsigned char *data);
extern HAMLIB_EXPORT(int) par_read_control(hamlib_port_t *p, unsigned char *control); extern HAMLIB_EXPORT(int) par_read_control(hamlib_port_t *p,
extern HAMLIB_EXPORT(int) par_read_status(hamlib_port_t *p, unsigned char *status); unsigned char *control);
extern HAMLIB_EXPORT(int) par_read_status(hamlib_port_t *p,
unsigned char *status);
extern HAMLIB_EXPORT(int) par_lock(hamlib_port_t *p); extern HAMLIB_EXPORT(int) par_lock(hamlib_port_t *p);
extern HAMLIB_EXPORT(int) par_unlock(hamlib_port_t *p); extern HAMLIB_EXPORT(int) par_unlock(hamlib_port_t *p);

Wyświetl plik

@ -48,8 +48,8 @@
#define RIG_BACKEND_MAX 32 #define RIG_BACKEND_MAX 32
#define DEFINE_INITRIG_BACKEND(backend) \ #define DEFINE_INITRIG_BACKEND(backend) \
int MAKE_VERSIONED_FN(PREFIX_INITRIG, ABI_VERSION, backend(void *be_handle)); \ int MAKE_VERSIONED_FN(PREFIX_INITRIG, ABI_VERSION, backend(void *be_handle)); \
rig_model_t MAKE_VERSIONED_FN(PREFIX_PROBERIG, ABI_VERSION, backend(hamlib_port_t *port, rig_probe_func_t cfunc, rig_ptr_t data)) rig_model_t MAKE_VERSIONED_FN(PREFIX_PROBERIG, ABI_VERSION, backend(hamlib_port_t *port, rig_probe_func_t cfunc, rig_ptr_t data))
#define RIG_FUNCNAMA(backend) MAKE_VERSIONED_FN(PREFIX_INITRIG, ABI_VERSION, backend) #define RIG_FUNCNAMA(backend) MAKE_VERSIONED_FN(PREFIX_INITRIG, ABI_VERSION, backend)
#define RIG_FUNCNAMB(backend) MAKE_VERSIONED_FN(PREFIX_PROBERIG, ABI_VERSION, backend) #define RIG_FUNCNAMB(backend) MAKE_VERSIONED_FN(PREFIX_PROBERIG, ABI_VERSION, backend)
@ -57,11 +57,8 @@
#define RIG_FUNCNAM(backend) RIG_FUNCNAMA(backend),RIG_FUNCNAMB(backend) #define RIG_FUNCNAM(backend) RIG_FUNCNAMA(backend),RIG_FUNCNAMB(backend)
/* /*
* RIG_BACKEND_LIST is defined here, please keep it up to data, * RIG_BACKEND_LIST is defined here, please keep it up to date,
* ie. each time you give birth to a new backend * i.e. each time you implement a new backend.
* Also, it should be possible to register "external" backend,
* that is backend that were not known by Hamlib at compile time.
* Maybe, riglist.h should reserve some numbers for them? --SF
*/ */
DEFINE_INITRIG_BACKEND(dummy); DEFINE_INITRIG_BACKEND(dummy);
DEFINE_INITRIG_BACKEND(yaesu); DEFINE_INITRIG_BACKEND(yaesu);
@ -104,95 +101,109 @@ DEFINE_INITRIG_BACKEND(winradio);
* and the branch name, which is a character string. * and the branch name, which is a character string.
*/ */
static struct { static struct {
int be_num; int be_num;
const char *be_name; const char *be_name;
int (* be_init_all)(void * handle); int (* be_init_all)(void *handle);
rig_model_t (* be_probe_all)(hamlib_port_t*, rig_probe_func_t, rig_ptr_t); rig_model_t (* be_probe_all)(hamlib_port_t *, rig_probe_func_t, rig_ptr_t);
} rig_backend_list[RIG_BACKEND_MAX] = } rig_backend_list[RIG_BACKEND_MAX] = {
{ { RIG_DUMMY, RIG_BACKEND_DUMMY, RIG_FUNCNAMA(dummy) },
{ RIG_DUMMY, RIG_BACKEND_DUMMY, RIG_FUNCNAMA(dummy) }, { RIG_YAESU, RIG_BACKEND_YAESU, RIG_FUNCNAM(yaesu) },
{ RIG_YAESU, RIG_BACKEND_YAESU, RIG_FUNCNAM(yaesu) }, { RIG_KENWOOD, RIG_BACKEND_KENWOOD, RIG_FUNCNAM(kenwood) },
{ RIG_KENWOOD, RIG_BACKEND_KENWOOD, RIG_FUNCNAM(kenwood) }, { RIG_ICOM, RIG_BACKEND_ICOM, RIG_FUNCNAM(icom) },
{ RIG_ICOM, RIG_BACKEND_ICOM, RIG_FUNCNAM(icom) }, { RIG_ICMARINE, RIG_BACKEND_ICMARINE, RIG_FUNCNAMA(icmarine) },
{ RIG_ICMARINE, RIG_BACKEND_ICMARINE, RIG_FUNCNAMA(icmarine) }, { RIG_PCR, RIG_BACKEND_PCR, RIG_FUNCNAMA(pcr) },
{ RIG_PCR, RIG_BACKEND_PCR, RIG_FUNCNAMA(pcr) }, { RIG_AOR, RIG_BACKEND_AOR, RIG_FUNCNAMA(aor) },
{ RIG_AOR, RIG_BACKEND_AOR, RIG_FUNCNAMA(aor) }, { RIG_JRC, RIG_BACKEND_JRC, RIG_FUNCNAMA(jrc) },
{ RIG_JRC, RIG_BACKEND_JRC, RIG_FUNCNAMA(jrc) }, { RIG_UNIDEN, RIG_BACKEND_UNIDEN, RIG_FUNCNAM(uniden) },
{ RIG_UNIDEN, RIG_BACKEND_UNIDEN, RIG_FUNCNAM(uniden) }, { RIG_DRAKE, RIG_BACKEND_DRAKE, RIG_FUNCNAM(drake) },
{ RIG_DRAKE, RIG_BACKEND_DRAKE, RIG_FUNCNAM(drake) }, { RIG_LOWE, RIG_BACKEND_LOWE, RIG_FUNCNAM(lowe) },
{ RIG_LOWE, RIG_BACKEND_LOWE, RIG_FUNCNAM(lowe) }, { RIG_RACAL, RIG_BACKEND_RACAL, RIG_FUNCNAMA(racal) },
{ RIG_RACAL, RIG_BACKEND_RACAL, RIG_FUNCNAMA(racal) }, { RIG_WJ, RIG_BACKEND_WJ, RIG_FUNCNAMA(wj) },
{ RIG_WJ, RIG_BACKEND_WJ, RIG_FUNCNAMA(wj) }, { RIG_SKANTI, RIG_BACKEND_SKANTI, RIG_FUNCNAMA(skanti) },
{ RIG_SKANTI, RIG_BACKEND_SKANTI, RIG_FUNCNAMA(skanti) },
#ifdef HAVE_WINRADIO #ifdef HAVE_WINRADIO
{ RIG_WINRADIO, RIG_BACKEND_WINRADIO, RIG_FUNCNAMA(winradio) }, { RIG_WINRADIO, RIG_BACKEND_WINRADIO, RIG_FUNCNAMA(winradio) },
#endif /* HAVE_WINRADIO */ #endif /* HAVE_WINRADIO */
{ RIG_TENTEC, RIG_BACKEND_TENTEC, RIG_FUNCNAMA(tentec) }, { RIG_TENTEC, RIG_BACKEND_TENTEC, RIG_FUNCNAMA(tentec) },
{ RIG_ALINCO, RIG_BACKEND_ALINCO, RIG_FUNCNAMA(alinco) }, { RIG_ALINCO, RIG_BACKEND_ALINCO, RIG_FUNCNAMA(alinco) },
{ RIG_KACHINA, RIG_BACKEND_KACHINA, RIG_FUNCNAMA(kachina) }, { RIG_KACHINA, RIG_BACKEND_KACHINA, RIG_FUNCNAMA(kachina) },
{ RIG_TAPR, RIG_BACKEND_TAPR, RIG_FUNCNAMA(tapr) }, { RIG_TAPR, RIG_BACKEND_TAPR, RIG_FUNCNAMA(tapr) },
{ RIG_FLEXRADIO, RIG_BACKEND_FLEXRADIO, RIG_FUNCNAMA(flexradio) }, { RIG_FLEXRADIO, RIG_BACKEND_FLEXRADIO, RIG_FUNCNAMA(flexradio) },
{ RIG_RFT, RIG_BACKEND_RFT, RIG_FUNCNAMA(rft) }, { RIG_RFT, RIG_BACKEND_RFT, RIG_FUNCNAMA(rft) },
{ RIG_KIT, RIG_BACKEND_KIT, RIG_FUNCNAMA(kit) }, { RIG_KIT, RIG_BACKEND_KIT, RIG_FUNCNAMA(kit) },
{ RIG_TUNER, RIG_BACKEND_TUNER, RIG_FUNCNAMA(tuner) }, { RIG_TUNER, RIG_BACKEND_TUNER, RIG_FUNCNAMA(tuner) },
{ RIG_RS, RIG_BACKEND_RS, RIG_FUNCNAMA(rs) }, { RIG_RS, RIG_BACKEND_RS, RIG_FUNCNAMA(rs) },
{ RIG_PRM80, RIG_BACKEND_PRM80, RIG_FUNCNAMA(prm80) }, { RIG_PRM80, RIG_BACKEND_PRM80, RIG_FUNCNAMA(prm80) },
{ RIG_ADAT, RIG_BACKEND_ADAT, RIG_FUNCNAM(adat) }, { RIG_ADAT, RIG_BACKEND_ADAT, RIG_FUNCNAM(adat) },
{ RIG_DORJI, RIG_BACKEND_DORJI, RIG_FUNCNAMA(dorji) }, { RIG_DORJI, RIG_BACKEND_DORJI, RIG_FUNCNAMA(dorji) },
{ RIG_BARRETT, RIG_BACKEND_BARRETT, RIG_FUNCNAMA(barrett) }, { RIG_BARRETT, RIG_BACKEND_BARRETT, RIG_FUNCNAMA(barrett) },
{ 0, NULL }, /* end */ { 0, NULL }, /* end */
}; };
/* /*
* This struct to keep track of known rig models. * This struct to keep track of known rig models.
* It is chained, and used in a hash table, see below. * It is chained, and used in a hash table, see below.
*/ */
struct rig_list { struct rig_list {
const struct rig_caps *caps; const struct rig_caps *caps;
struct rig_list *next; struct rig_list *next;
}; };
#define RIGLSTHASHSZ 16 #define RIGLSTHASHSZ 16
#define HASH_FUNC(a) ((a)%RIGLSTHASHSZ) #define HASH_FUNC(a) ((a)%RIGLSTHASHSZ)
/* /*
* The rig_hash_table is a hash table pointing to a list of next==NULL * The rig_hash_table is a hash table pointing to a list of next==NULL
* terminated caps. * terminated caps.
*/ */
static struct rig_list *rig_hash_table[RIGLSTHASHSZ] = { NULL, }; static struct rig_list *rig_hash_table[RIGLSTHASHSZ] = { NULL, };
static int rig_lookup_backend(rig_model_t rig_model); static int rig_lookup_backend(rig_model_t rig_model);
/* /*
* Basically, this is a hash insert function that doesn't check for dup! * Basically, this is a hash insert function that doesn't check for dup!
*/ */
int HAMLIB_API rig_register(const struct rig_caps *caps) int HAMLIB_API rig_register(const struct rig_caps *caps)
{ {
int hval; int hval;
struct rig_list *p; struct rig_list *p;
if (!caps) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
rig_debug(RIG_DEBUG_VERBOSE, "rig_register (%d)\n",caps->rig_model); if (!caps) {
return -RIG_EINVAL;
}
rig_debug(RIG_DEBUG_VERBOSE,
"%s: rig_register (%d)\n",
__func__,
caps->rig_model);
#ifndef DONT_WANT_DUP_CHECK #ifndef DONT_WANT_DUP_CHECK
if (rig_get_caps(caps->rig_model)!=NULL)
return -RIG_EINVAL; if (rig_get_caps(caps->rig_model) != NULL) {
return -RIG_EINVAL;
}
#endif #endif
p = (struct rig_list*)malloc(sizeof(struct rig_list)); p = (struct rig_list *)malloc(sizeof(struct rig_list));
if (!p)
return -RIG_ENOMEM;
hval = HASH_FUNC(caps->rig_model); if (!p) {
p->caps = caps; return -RIG_ENOMEM;
// p->handle = NULL; }
p->next = rig_hash_table[hval];
rig_hash_table[hval] = p;
return RIG_OK; hval = HASH_FUNC(caps->rig_model);
p->caps = caps;
// p->handle = NULL;
p->next = rig_hash_table[hval];
rig_hash_table[hval] = p;
return RIG_OK;
} }
/* /*
@ -200,16 +211,17 @@ int HAMLIB_API rig_register(const struct rig_caps *caps)
* ie. rig_hash_table lookup * ie. rig_hash_table lookup
*/ */
const struct rig_caps * HAMLIB_API rig_get_caps(rig_model_t rig_model) const struct rig_caps *HAMLIB_API rig_get_caps(rig_model_t rig_model)
{ {
struct rig_list *p; struct rig_list *p;
for (p = rig_hash_table[HASH_FUNC(rig_model)]; p; p=p->next) { for (p = rig_hash_table[HASH_FUNC(rig_model)]; p; p = p->next) {
if (p->caps->rig_model == rig_model) if (p->caps->rig_model == rig_model) {
return p->caps; return p->caps;
} }
}
return NULL; /* sorry, caps not registered! */ return NULL; /* sorry, caps not registered! */
} }
/* /*
@ -219,15 +231,16 @@ const struct rig_caps * HAMLIB_API rig_get_caps(rig_model_t rig_model)
*/ */
static int rig_lookup_backend(rig_model_t rig_model) static int rig_lookup_backend(rig_model_t rig_model)
{ {
int i; int i;
for (i=0; i<RIG_BACKEND_MAX && rig_backend_list[i].be_name; i++) { for (i = 0; i < RIG_BACKEND_MAX && rig_backend_list[i].be_name; i++) {
if (RIG_BACKEND_NUM(rig_model) == if (RIG_BACKEND_NUM(rig_model) ==
rig_backend_list[i].be_num) rig_backend_list[i].be_num) {
return i; return i;
} }
}
return -1; return -1;
} }
/* /*
@ -238,85 +251,96 @@ static int rig_lookup_backend(rig_model_t rig_model)
*/ */
int HAMLIB_API rig_check_backend(rig_model_t rig_model) int HAMLIB_API rig_check_backend(rig_model_t rig_model)
{ {
const struct rig_caps *caps; const struct rig_caps *caps;
int be_idx; int be_idx;
int retval; int retval;
/* already loaded ? */ /* already loaded ? */
caps = rig_get_caps(rig_model); caps = rig_get_caps(rig_model);
if (caps)
return RIG_OK;
be_idx = rig_lookup_backend(rig_model); if (caps) {
return RIG_OK;
}
/* be_idx = rig_lookup_backend(rig_model);
* Never heard about this backend family!
*/
if (be_idx == -1) {
rig_debug(RIG_DEBUG_VERBOSE, "rig_check_backend: unsupported "
"backend %d for model %d\n",
RIG_BACKEND_NUM(rig_model), rig_model);
return -RIG_ENAVAIL;
}
retval = rig_load_backend(rig_backend_list[be_idx].be_name); /*
* Never heard about this backend family!
*/
if (be_idx == -1) {
rig_debug(RIG_DEBUG_VERBOSE, "rig_check_backend: unsupported "
"backend %d for model %d\n",
RIG_BACKEND_NUM(rig_model), rig_model);
return -RIG_ENAVAIL;
}
return retval; retval = rig_load_backend(rig_backend_list[be_idx].be_name);
return retval;
} }
int HAMLIB_API rig_unregister(rig_model_t rig_model) int HAMLIB_API rig_unregister(rig_model_t rig_model)
{ {
int hval; int hval;
struct rig_list *p,*q; struct rig_list *p, *q;
hval = HASH_FUNC(rig_model); hval = HASH_FUNC(rig_model);
q = NULL; q = NULL;
for (p = rig_hash_table[hval]; p; p=p->next) {
if (p->caps->rig_model == rig_model) {
if (q == NULL)
rig_hash_table[hval] = p->next;
else
q->next = p->next;
free(p); for (p = rig_hash_table[hval]; p; p = p->next) {
return RIG_OK; if (p->caps->rig_model == rig_model) {
} if (q == NULL) {
q = p; rig_hash_table[hval] = p->next;
} } else {
q->next = p->next;
}
return -RIG_EINVAL; /* sorry, caps not registered! */ free(p);
return RIG_OK;
}
q = p;
}
return -RIG_EINVAL; /* sorry, caps not registered! */
} }
/* /*
* rig_list_foreach * rig_list_foreach
* executes cfunc on all the elements stored in the rig hash list * executes cfunc on all the elements stored in the rig hash list
*/ */
int HAMLIB_API rig_list_foreach(int (*cfunc)(const struct rig_caps*, rig_ptr_t),rig_ptr_t data) int HAMLIB_API rig_list_foreach(int (*cfunc)(const struct rig_caps *,
rig_ptr_t), rig_ptr_t data)
{ {
struct rig_list *p; struct rig_list *p;
int i; int i;
if (!cfunc) if (!cfunc) {
return -RIG_EINVAL; return -RIG_EINVAL;
for (i=0; i<RIGLSTHASHSZ; i++) {
struct rig_list * next = NULL;
for (p=rig_hash_table[i]; p; p=next) {
next = p->next; /* read before call in case it is unregistered */
if ((*cfunc)(p->caps,data) == 0)
return RIG_OK;
} }
}
return RIG_OK; for (i = 0; i < RIGLSTHASHSZ; i++) {
struct rig_list *next = NULL;
for (p = rig_hash_table[i]; p; p = next) {
next = p->next; /* read before call in case it is unregistered */
if ((*cfunc)(p->caps, data) == 0) {
return RIG_OK;
}
}
}
return RIG_OK;
} }
static int dummy_rig_probe(const hamlib_port_t *p, rig_model_t model, rig_ptr_t data) static int dummy_rig_probe(const hamlib_port_t *p, rig_model_t model,
rig_ptr_t data)
{ {
rig_debug(RIG_DEBUG_TRACE, "Found rig, model %d\n", model); rig_debug(RIG_DEBUG_TRACE, "Found rig, model %d\n", model);
return RIG_OK; return RIG_OK;
} }
/* /*
@ -325,46 +349,52 @@ static int dummy_rig_probe(const hamlib_port_t *p, rig_model_t model, rig_ptr_t
*/ */
rig_model_t rig_probe_first(hamlib_port_t *p) rig_model_t rig_probe_first(hamlib_port_t *p)
{ {
int i; int i;
rig_model_t model; rig_model_t model;
for (i=0; i<RIG_BACKEND_MAX && rig_backend_list[i].be_name; i++) { for (i = 0; i < RIG_BACKEND_MAX && rig_backend_list[i].be_name; i++) {
if (rig_backend_list[i].be_probe_all) { if (rig_backend_list[i].be_probe_all) {
model = (*rig_backend_list[i].be_probe_all)(p, dummy_rig_probe, (rig_ptr_t)NULL); model = (*rig_backend_list[i].be_probe_all)(p, dummy_rig_probe,
/* stop at first one found */ (rig_ptr_t)NULL);
if (model != RIG_MODEL_NONE)
return model; /* stop at first one found */
} if (model != RIG_MODEL_NONE) {
} return model;
return RIG_MODEL_NONE; }
}
}
return RIG_MODEL_NONE;
} }
/* /*
* rig_probe_all_backends * rig_probe_all_backends
* called straight by rig_probe_all * called straight by rig_probe_all
*/ */
int rig_probe_all_backends(hamlib_port_t *p, rig_probe_func_t cfunc, rig_ptr_t data) int rig_probe_all_backends(hamlib_port_t *p, rig_probe_func_t cfunc,
rig_ptr_t data)
{ {
int i; int i;
for (i=0; i<RIG_BACKEND_MAX && rig_backend_list[i].be_name; i++) { for (i = 0; i < RIG_BACKEND_MAX && rig_backend_list[i].be_name; i++) {
if (rig_backend_list[i].be_probe_all) { if (rig_backend_list[i].be_probe_all) {
(*rig_backend_list[i].be_probe_all)(p, cfunc, data); (*rig_backend_list[i].be_probe_all)(p, cfunc, data);
} }
} }
return RIG_OK;
return RIG_OK;
} }
int rig_load_all_backends() int rig_load_all_backends()
{ {
int i; int i;
for (i=0; i<RIG_BACKEND_MAX && rig_backend_list[i].be_name; i++) { for (i = 0; i < RIG_BACKEND_MAX && rig_backend_list[i].be_name; i++) {
rig_load_backend(rig_backend_list[i].be_name); rig_load_backend(rig_backend_list[i].be_name);
} }
return RIG_OK; return RIG_OK;
} }
@ -375,22 +405,20 @@ typedef int (*backend_init_t)(rig_ptr_t);
*/ */
int HAMLIB_API rig_load_backend(const char *be_name) int HAMLIB_API rig_load_backend(const char *be_name)
{ {
int i; int i;
backend_init_t be_init; backend_init_t be_init;
for (i=0; i<RIG_BACKEND_MAX && rig_backend_list[i].be_name; i++) { for (i = 0; i < RIG_BACKEND_MAX && rig_backend_list[i].be_name; i++) {
if (!strcmp(be_name, rig_backend_list[i].be_name)) { if (!strcmp(be_name, rig_backend_list[i].be_name)) {
be_init = rig_backend_list[i].be_init_all ; be_init = rig_backend_list[i].be_init_all ;
if(be_init)
{
return (*be_init)(NULL);
}
else
{
return -RIG_EINVAL;
}
}
}
return -RIG_EINVAL; if (be_init) {
return (*be_init)(NULL);
} else {
return -RIG_EINVAL;
}
}
}
return -RIG_EINVAL;
} }

Wyświetl plik

@ -42,15 +42,31 @@
#define PREFIX_INITRIG initrigs #define PREFIX_INITRIG initrigs
#define PREFIX_PROBERIG probeallrigs #define PREFIX_PROBERIG probeallrigs
#define DECLARE_INITRIG_BACKEND(backend) EXTERN_C BACKEND_EXPORT(int) MAKE_VERSIONED_FN(PREFIX_INITRIG, ABI_VERSION, backend(void *be_handle)) #define DECLARE_INITRIG_BACKEND(backend) \
EXTERN_C BACKEND_EXPORT(int) \
MAKE_VERSIONED_FN(PREFIX_INITRIG, ABI_VERSION, backend(void *be_handle))
#define DECLARE_PROBERIG_BACKEND(backend) EXTERN_C BACKEND_EXPORT(rig_model_t) MAKE_VERSIONED_FN(PREFIX_PROBERIG, ABI_VERSION, backend(hamlib_port_t *port, rig_probe_func_t cfunc, rig_ptr_t data)) #define DECLARE_PROBERIG_BACKEND(backend) \
EXTERN_C BACKEND_EXPORT(rig_model_t) \
MAKE_VERSIONED_FN(PREFIX_PROBERIG, \
ABI_VERSION, \
backend(hamlib_port_t *port, \
rig_probe_func_t cfunc, \
rig_ptr_t data))
#define PREFIX_INITROTS initrots #define PREFIX_INITROTS initrots
#define PREFIX_PROBEROTS probeallrots #define PREFIX_PROBEROTS probeallrots
#define DECLARE_INITROT_BACKEND(backend) EXTERN_C BACKEND_EXPORT(int) MAKE_VERSIONED_FN(PREFIX_INITROTS, ABI_VERSION, backend(void *be_handle)) #define DECLARE_INITROT_BACKEND(backend) \
EXTERN_C BACKEND_EXPORT(int) \
MAKE_VERSIONED_FN(PREFIX_INITROTS, ABI_VERSION, backend(void *be_handle))
#define DECLARE_PROBEROT_BACKEND(backend) EXTERN_C BACKEND_EXPORT(rot_model_t) MAKE_VERSIONED_FN(PREFIX_PROBEROTS, ABI_VERSION, backend(hamlib_port_t *port, rig_probe_func_t cfunc, rig_ptr_t data)) #define DECLARE_PROBEROT_BACKEND(backend) \
EXTERN_C BACKEND_EXPORT(rot_model_t) \
MAKE_VERSIONED_FN(PREFIX_PROBEROTS, \
ABI_VERSION, \
backend(hamlib_port_t *port, \
rig_probe_func_t cfunc, \
rig_ptr_t data))
#endif /* _REGISTER_H */ #endif /* _REGISTER_H */

4646
src/rig.c

Plik diff jest za duży Load Diff

Wyświetl plik

@ -49,70 +49,86 @@
* Configuration options available in the rot->state struct. * Configuration options available in the rot->state struct.
*/ */
static const struct confparams rotfrontend_cfg_params[] = { static const struct confparams rotfrontend_cfg_params[] = {
{ TOK_PATHNAME, "rot_pathname", "Rig path name", {
"Path name to the device file of the rotator", TOK_PATHNAME, "rot_pathname", "Rig path name",
"/dev/rotator", RIG_CONF_STRING, "Path name to the device file of the rotator",
}, "/dev/rotator", 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_WRITE_DELAY, "write_delay", "Write delay",
}, "Delay in ms between each byte sent out",
{ TOK_POST_WRITE_DELAY, "post_write_delay", "Post write delay", "0", RIG_CONF_NUMERIC, { .n = { 0, 1000, 1 } }
"Delay in ms between each command sent out", },
"0", RIG_CONF_NUMERIC, { .n = { 0, 1000, 1 } } {
}, TOK_POST_WRITE_DELAY, "post_write_delay", "Post write delay",
{ TOK_TIMEOUT, "timeout", "Timeout", "Timeout in ms", "Delay in ms between each command sent out",
"0", RIG_CONF_NUMERIC, { .n = { 0, 10000, 1 } } "0", RIG_CONF_NUMERIC, { .n = { 0, 1000, 1 } }
}, },
{ TOK_RETRY, "retry", "Retry", "Max number of retry", {
"0", RIG_CONF_NUMERIC, { .n = { 0, 10, 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 rotator azimuth in degrees", TOK_MIN_AZ, "min_az", "Minimum azimuth",
"-180", RIG_CONF_NUMERIC, { .n = { -360, 360, .001 } } "Minimum rotator azimuth in degrees",
}, "-180", RIG_CONF_NUMERIC, { .n = { -360, 360, .001 } }
{ TOK_MAX_AZ, "max_az", "Maximum azimuth", },
"Maximum rotator azimuth in degrees", {
"180", RIG_CONF_NUMERIC, { .n = { -360, 360, .001 } } TOK_MAX_AZ, "max_az", "Maximum azimuth",
}, "Maximum rotator azimuth in degrees",
{ TOK_MIN_EL, "min_el", "Minimum elevation", "180", RIG_CONF_NUMERIC, { .n = { -360, 360, .001 } }
"Minimum rotator elevation in degrees", },
"0", RIG_CONF_NUMERIC, { .n = { -90, 180, .001 } } {
}, TOK_MIN_EL, "min_el", "Minimum elevation",
{ TOK_MAX_EL, "max_el", "Maximum elevation", "Minimum rotator elevation in degrees",
"Maximum rotator elevation in degrees", "0", RIG_CONF_NUMERIC, { .n = { -90, 180, .001 } }
"90", RIG_CONF_NUMERIC, { .n = { -90, 180, .001 } } },
}, {
TOK_MAX_EL, "max_el", "Maximum elevation",
"Maximum rotator elevation in degrees",
"90", RIG_CONF_NUMERIC, { .n = { -90, 180, .001 } }
},
{ RIG_CONF_END, NULL, } { RIG_CONF_END, NULL, }
}; };
static const struct confparams rotfrontend_serial_cfg_params[] = { static const struct confparams rotfrontend_serial_cfg_params[] = {
{ TOK_SERIAL_SPEED, "serial_speed", "Serial speed", {
"Serial port baud rate", TOK_SERIAL_SPEED, "serial_speed", "Serial speed",
"0", RIG_CONF_NUMERIC, { .n = { 300, 115200, 1 } } "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_DATA_BITS, "data_bits", "Serial data bits",
}, "Serial port data bits",
{ TOK_STOP_BITS, "stop_bits", "Serial stop bits", "8", RIG_CONF_NUMERIC, { .n = { 5, 8, 1 } }
"Serial port stop bits", },
"1", RIG_CONF_NUMERIC, { .n = { 0, 3, 1 } } {
}, TOK_STOP_BITS, "stop_bits", "Serial stop bits",
{ TOK_PARITY, "serial_parity", "Serial parity", "Serial port stop bits",
"Serial port parity", "1", RIG_CONF_NUMERIC, { .n = { 0, 3, 1 } }
"None", RIG_CONF_COMBO, { .c = {{ "None", "Odd", "Even", "Mark", "Space", NULL }} } },
}, {
{ TOK_HANDSHAKE, "serial_handshake", "Serial handshake", TOK_PARITY, "serial_parity", "Serial parity",
"Serial port handshake", "Serial port parity",
"None", RIG_CONF_COMBO, { .c = {{ "None", "XONXOFF", "Hardware", NULL }} } "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, } { RIG_CONF_END, NULL, }
}; };
/** /**
* \brief Set rotator state info from alpha input * \brief Set rotator state info from alpha input
* \param rot * \param rot
@ -124,105 +140,148 @@ static const struct confparams rotfrontend_serial_cfg_params[] = {
*/ */
int frontrot_set_conf(ROT *rot, token_t token, const char *val) int frontrot_set_conf(ROT *rot, token_t token, const char *val)
{ {
struct rot_state *rs; struct rot_state *rs;
int val_i; int val_i;
rs = &rot->state; rs = &rot->state;
switch(token) { rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
case TOK_PATHNAME:
strncpy(rs->rotport.pathname, val, FILPATHLEN-1);
break;
case TOK_WRITE_DELAY:
if (1 != sscanf(val, "%d", &val_i))
return -RIG_EINVAL;
rs->rotport.write_delay = val_i;
break;
case TOK_POST_WRITE_DELAY:
if (1 != sscanf(val, "%d", &val_i))
return -RIG_EINVAL;
rs->rotport.post_write_delay = val_i;
break;
case TOK_TIMEOUT:
if (1 != sscanf(val, "%d", &val_i))
return -RIG_EINVAL;
rs->rotport.timeout = val_i;
break;
case TOK_RETRY:
if (1 != sscanf(val, "%d", &val_i))
return -RIG_EINVAL;
rs->rotport.retry = val_i;
break;
case TOK_SERIAL_SPEED: switch (token) {
if (rs->rotport.type.rig != RIG_PORT_SERIAL) case TOK_PATHNAME:
return -RIG_EINVAL; strncpy(rs->rotport.pathname, val, FILPATHLEN - 1);
if (1 != sscanf(val, "%d", &val_i)) break;
return -RIG_EINVAL;
rs->rotport.parm.serial.rate = val_i;
break;
case TOK_DATA_BITS:
if (rs->rotport.type.rig != RIG_PORT_SERIAL)
return -RIG_EINVAL;
if (1 != sscanf(val, "%d", &val_i))
return -RIG_EINVAL;
rs->rotport.parm.serial.data_bits = val_i;
break;
case TOK_STOP_BITS:
if (rs->rotport.type.rig != RIG_PORT_SERIAL)
return -RIG_EINVAL;
if (1 != sscanf(val, "%d", &val_i))
return -RIG_EINVAL;
rs->rotport.parm.serial.stop_bits = val_i;
break;
case TOK_PARITY:
if (rs->rotport.type.rig != RIG_PORT_SERIAL)
return -RIG_EINVAL;
if (!strcmp(val, "None"))
rs->rotport.parm.serial.parity = RIG_PARITY_NONE;
else if (!strcmp(val, "Odd"))
rs->rotport.parm.serial.parity = RIG_PARITY_ODD;
else if (!strcmp(val, "Even"))
rs->rotport.parm.serial.parity = RIG_PARITY_EVEN;
else if (!strcmp(val, "Mark"))
rs->rotport.parm.serial.parity = RIG_PARITY_MARK;
else if (!strcmp(val, "Space"))
rs->rotport.parm.serial.parity = RIG_PARITY_SPACE;
else
return -RIG_EINVAL;
break;
case TOK_HANDSHAKE:
if (rs->rotport.type.rig != RIG_PORT_SERIAL)
return -RIG_EINVAL;
if (!strcmp(val, "None"))
rs->rotport.parm.serial.handshake = RIG_HANDSHAKE_NONE;
else if (!strcmp(val, "XONXOFF"))
rs->rotport.parm.serial.handshake = RIG_HANDSHAKE_XONXOFF;
else if (!strcmp(val, "Hardware"))
rs->rotport.parm.serial.handshake = RIG_HANDSHAKE_HARDWARE;
else
return -RIG_EINVAL;
break;
case TOK_MIN_AZ: case TOK_WRITE_DELAY:
rs->min_az = atof(val); if (1 != sscanf(val, "%d", &val_i)) {
break; return -RIG_EINVAL;
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;
default: rs->rotport.write_delay = val_i;
return -RIG_EINVAL; break;
}
return RIG_OK; case TOK_POST_WRITE_DELAY:
if (1 != sscanf(val, "%d", &val_i)) {
return -RIG_EINVAL;
}
rs->rotport.post_write_delay = val_i;
break;
case TOK_TIMEOUT:
if (1 != sscanf(val, "%d", &val_i)) {
return -RIG_EINVAL;
}
rs->rotport.timeout = val_i;
break;
case TOK_RETRY:
if (1 != sscanf(val, "%d", &val_i)) {
return -RIG_EINVAL;
}
rs->rotport.retry = val_i;
break;
case TOK_SERIAL_SPEED:
if (rs->rotport.type.rig != RIG_PORT_SERIAL) {
return -RIG_EINVAL;
}
if (1 != sscanf(val, "%d", &val_i)) {
return -RIG_EINVAL;
}
rs->rotport.parm.serial.rate = val_i;
break;
case TOK_DATA_BITS:
if (rs->rotport.type.rig != RIG_PORT_SERIAL) {
return -RIG_EINVAL;
}
if (1 != sscanf(val, "%d", &val_i)) {
return -RIG_EINVAL;
}
rs->rotport.parm.serial.data_bits = val_i;
break;
case TOK_STOP_BITS:
if (rs->rotport.type.rig != RIG_PORT_SERIAL) {
return -RIG_EINVAL;
}
if (1 != sscanf(val, "%d", &val_i)) {
return -RIG_EINVAL;
}
rs->rotport.parm.serial.stop_bits = val_i;
break;
case TOK_PARITY:
if (rs->rotport.type.rig != RIG_PORT_SERIAL) {
return -RIG_EINVAL;
}
if (!strcmp(val, "None")) {
rs->rotport.parm.serial.parity = RIG_PARITY_NONE;
} else if (!strcmp(val, "Odd")) {
rs->rotport.parm.serial.parity = RIG_PARITY_ODD;
} else if (!strcmp(val, "Even")) {
rs->rotport.parm.serial.parity = RIG_PARITY_EVEN;
} else if (!strcmp(val, "Mark")) {
rs->rotport.parm.serial.parity = RIG_PARITY_MARK;
} else if (!strcmp(val, "Space")) {
rs->rotport.parm.serial.parity = RIG_PARITY_SPACE;
} else {
return -RIG_EINVAL;
}
break;
case TOK_HANDSHAKE:
if (rs->rotport.type.rig != RIG_PORT_SERIAL) {
return -RIG_EINVAL;
}
if (!strcmp(val, "None")) {
rs->rotport.parm.serial.handshake = RIG_HANDSHAKE_NONE;
} else if (!strcmp(val, "XONXOFF")) {
rs->rotport.parm.serial.handshake = RIG_HANDSHAKE_XONXOFF;
} else if (!strcmp(val, "Hardware")) {
rs->rotport.parm.serial.handshake = RIG_HANDSHAKE_HARDWARE;
} else {
return -RIG_EINVAL;
}
break;
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;
default:
return -RIG_EINVAL;
}
return RIG_OK;
} }
/** /**
* \brief Get data from rotator state in alpha form * \brief Get data from rotator state in alpha form
* \param rot non-null * \param rot non-null
@ -232,84 +291,140 @@ int frontrot_set_conf(ROT *rot, token_t token, const char *val)
*/ */
int frontrot_get_conf(ROT *rot, token_t token, char *val) int frontrot_get_conf(ROT *rot, token_t token, char *val)
{ {
struct rot_state *rs; struct rot_state *rs;
const char *s; const char *s;
rs = &rot->state; rs = &rot->state;
switch(token) { rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
case TOK_PATHNAME:
strcpy(val, rs->rotport.pathname); switch (token) {
break; case TOK_PATHNAME:
case TOK_WRITE_DELAY: strcpy(val, rs->rotport.pathname);
sprintf(val, "%d", rs->rotport.write_delay); break;
break;
case TOK_POST_WRITE_DELAY: case TOK_WRITE_DELAY:
sprintf(val, "%d", rs->rotport.post_write_delay); sprintf(val, "%d", rs->rotport.write_delay);
break; break;
case TOK_TIMEOUT:
sprintf(val, "%d", rs->rotport.timeout); case TOK_POST_WRITE_DELAY:
break; sprintf(val, "%d", rs->rotport.post_write_delay);
case TOK_RETRY: break;
sprintf(val, "%d", rs->rotport.retry);
break; case TOK_TIMEOUT:
case TOK_SERIAL_SPEED: sprintf(val, "%d", rs->rotport.timeout);
if (rs->rotport.type.rig != RIG_PORT_SERIAL) break;
return -RIG_EINVAL;
sprintf(val, "%d", rs->rotport.parm.serial.rate); case TOK_RETRY:
break; sprintf(val, "%d", rs->rotport.retry);
case TOK_DATA_BITS: break;
if (rs->rotport.type.rig != RIG_PORT_SERIAL)
return -RIG_EINVAL; case TOK_SERIAL_SPEED:
sprintf(val, "%d", rs->rotport.parm.serial.data_bits); if (rs->rotport.type.rig != RIG_PORT_SERIAL) {
break; return -RIG_EINVAL;
case TOK_STOP_BITS: }
if (rs->rotport.type.rig != RIG_PORT_SERIAL)
return -RIG_EINVAL; sprintf(val, "%d", rs->rotport.parm.serial.rate);
sprintf(val, "%d", rs->rotport.parm.serial.stop_bits); break;
break;
case TOK_PARITY: case TOK_DATA_BITS:
if (rs->rotport.type.rig != RIG_PORT_SERIAL) if (rs->rotport.type.rig != RIG_PORT_SERIAL) {
return -RIG_EINVAL; return -RIG_EINVAL;
switch (rs->rotport.parm.serial.parity) { }
case RIG_PARITY_NONE: s = "None"; break;
case RIG_PARITY_ODD: s = "Odd"; break; sprintf(val, "%d", rs->rotport.parm.serial.data_bits);
case RIG_PARITY_EVEN: s = "Even"; break; break;
case RIG_PARITY_MARK: s = "Mark"; break;
case RIG_PARITY_SPACE: s = "Space"; break; case TOK_STOP_BITS:
default: return -RIG_EINVAL; if (rs->rotport.type.rig != RIG_PORT_SERIAL) {
} return -RIG_EINVAL;
strcpy(val, s); }
break;
case TOK_HANDSHAKE: sprintf(val, "%d", rs->rotport.parm.serial.stop_bits);
if (rs->rotport.type.rig != RIG_PORT_SERIAL) break;
return -RIG_EINVAL;
switch (rs->rotport.parm.serial.handshake) { case TOK_PARITY:
case RIG_HANDSHAKE_NONE: s = "None"; break; if (rs->rotport.type.rig != RIG_PORT_SERIAL) {
case RIG_HANDSHAKE_XONXOFF: s = "XONXOFF"; break; return -RIG_EINVAL;
case RIG_HANDSHAKE_HARDWARE: s = "Hardware"; break; }
default: return -RIG_EINVAL;
} switch (rs->rotport.parm.serial.parity) {
strcpy(val, s); case RIG_PARITY_NONE:
break; s = "None";
case TOK_MIN_AZ: break;
sprintf(val, "%f", rs->min_az);
break; case RIG_PARITY_ODD:
case TOK_MAX_AZ: s = "Odd";
sprintf(val, "%f", rs->max_az); break;
break;
case TOK_MIN_EL: case RIG_PARITY_EVEN:
sprintf(val, "%f", rs->min_el); s = "Even";
break; break;
case TOK_MAX_EL:
sprintf(val, "%f", rs->max_el); case RIG_PARITY_MARK:
break; s = "Mark";
default: break;
return -RIG_EINVAL;
} case RIG_PARITY_SPACE:
return RIG_OK; s = "Space";
break;
default:
return -RIG_EINVAL;
}
strcpy(val, s);
break;
case TOK_HANDSHAKE:
if (rs->rotport.type.rig != RIG_PORT_SERIAL) {
return -RIG_EINVAL;
}
switch (rs->rotport.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;
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;
default:
return -RIG_EINVAL;
}
return RIG_OK;
} }
/** /**
* \brief Executes cfunc on all the elements stored in the conf table * \brief Executes cfunc on all the elements stored in the conf table
* \param rot non-null * \param rot non-null
@ -318,28 +433,39 @@ int frontrot_get_conf(ROT *rot, token_t token, char *val)
* *
* start first with backend conf table, then finish with frontend table * start first with backend conf table, then finish with frontend table
*/ */
int HAMLIB_API rot_token_foreach(ROT *rot, int (*cfunc)(const struct confparams *, rig_ptr_t), rig_ptr_t data) int HAMLIB_API rot_token_foreach(ROT *rot,
int (*cfunc)(const struct confparams *, rig_ptr_t),
rig_ptr_t data)
{ {
const struct confparams *cfp; const struct confparams *cfp;
if (!rot || !rot->caps || !cfunc) rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
for (cfp = rotfrontend_cfg_params; cfp->name; cfp++) if (!rot || !rot->caps || !cfunc) {
if ((*cfunc)(cfp, data) == 0) return -RIG_EINVAL;
return RIG_OK; }
if (rot->caps->port_type == RIG_PORT_SERIAL) { for (cfp = rotfrontend_cfg_params; cfp->name; cfp++) {
for (cfp = rotfrontend_serial_cfg_params; cfp->name; cfp++) if ((*cfunc)(cfp, data) == 0) {
if ((*cfunc)(cfp, data) == 0) return RIG_OK;
return RIG_OK; }
} }
for (cfp = rot->caps->cfgparams; cfp && cfp->name; cfp++) if (rot->caps->port_type == RIG_PORT_SERIAL) {
if ((*cfunc)(cfp, data) == 0) for (cfp = rotfrontend_serial_cfg_params; cfp->name; cfp++) {
return RIG_OK; if ((*cfunc)(cfp, data) == 0) {
return RIG_OK;
}
}
}
return RIG_OK; for (cfp = rot->caps->cfgparams; cfp && cfp->name; cfp++) {
if ((*cfunc)(cfp, data) == 0) {
return RIG_OK;
}
}
return RIG_OK;
} }
@ -352,31 +478,45 @@ int HAMLIB_API rot_token_foreach(ROT *rot, int (*cfunc)(const struct confparams
* lookup backend config table first, then fall back to frontend. * lookup backend config table first, then fall back to frontend.
* TODO: should use Lex to speed it up, strcmp hurts! * TODO: should use Lex to speed it up, strcmp hurts!
*/ */
const struct confparams * HAMLIB_API rot_confparam_lookup(ROT *rot, const char *name) const struct confparams * HAMLIB_API rot_confparam_lookup(ROT *rot,
const char *name)
{ {
const struct confparams *cfp; const struct confparams *cfp;
token_t token; token_t token;
if (!rot || !rot->caps) rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return NULL;
/* 0 returned for invalid format */ if (!rot || !rot->caps) {
token = strtol(name, NULL, 0); return NULL;
}
for (cfp = rot->caps->cfgparams; cfp && cfp->name; cfp++) /* 0 returned for invalid format */
if (!strcmp(cfp->name, name) || token == cfp->token) token = strtol(name, NULL, 0);
return cfp;
for (cfp = rotfrontend_cfg_params; cfp->name; cfp++) for (cfp = rot->caps->cfgparams; cfp && cfp->name; cfp++) {
if (!strcmp(cfp->name, name) || token == cfp->token) if (!strcmp(cfp->name, name) || token == cfp->token) {
return cfp; return cfp;
if (rot->caps->port_type == RIG_PORT_SERIAL) { }
for (cfp = rotfrontend_serial_cfg_params; cfp->name; cfp++) }
if (!strcmp(cfp->name, name) || token == cfp->token)
return cfp; for (cfp = rotfrontend_cfg_params; cfp->name; cfp++) {
} if (!strcmp(cfp->name, name) || token == cfp->token) {
return NULL; return cfp;
}
}
if (rot->caps->port_type == RIG_PORT_SERIAL) {
for (cfp = rotfrontend_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 * \brief Simple lookup returning token id associated with name
* \param rot * \param rot
@ -385,20 +525,25 @@ const struct confparams * HAMLIB_API rot_confparam_lookup(ROT *rot, const char *
*/ */
token_t HAMLIB_API rot_token_lookup(ROT *rot, const char *name) token_t HAMLIB_API rot_token_lookup(ROT *rot, const char *name)
{ {
const struct confparams *cfp; const struct confparams *cfp;
cfp = rot_confparam_lookup(rot, name); rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!cfp)
return RIG_CONF_END;
return cfp->token; cfp = rot_confparam_lookup(rot, name);
if (!cfp) {
return RIG_CONF_END;
}
return cfp->token;
} }
/** /**
* \brief set a rotator configuration parameter * \brief set a rotator configuration parameter
* \param rot The rot handle * \param rot The rot handle
* \param token The parameter * \param token The parameter
* \param val The value to set the parameter to * \param val The value to set the parameter to
* *
* Sets a configuration parameter. * Sets a configuration parameter.
* *
@ -410,33 +555,42 @@ token_t HAMLIB_API rot_token_lookup(ROT *rot, const char *name)
*/ */
int HAMLIB_API rot_set_conf(ROT *rot, token_t token, const char *val) int HAMLIB_API rot_set_conf(ROT *rot, token_t token, const char *val)
{ {
if (!rot || !rot->caps) rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
if (rig_need_debug(RIG_DEBUG_VERBOSE)) { if (!rot || !rot->caps) {
const struct confparams *cfp; return -RIG_EINVAL;
char tokenstr[12]; }
sprintf(tokenstr, "%ld", token);
cfp = rot_confparam_lookup(rot, tokenstr);
if (!cfp)
return -RIG_EINVAL;
rig_debug(RIG_DEBUG_VERBOSE, "%s: %s='%s'\n", __func__, cfp->name, val);
}
if (IS_TOKEN_FRONTEND(token)) if (rig_need_debug(RIG_DEBUG_VERBOSE)) {
return frontrot_set_conf(rot, token, val); const struct confparams *cfp;
char tokenstr[12];
sprintf(tokenstr, "%ld", token);
cfp = rot_confparam_lookup(rot, tokenstr);
if (rot->caps->set_conf == NULL) if (!cfp) {
return -RIG_ENAVAIL; return -RIG_EINVAL;
}
return rot->caps->set_conf(rot, token, val); rot_debug(RIG_DEBUG_VERBOSE, "%s: %s='%s'\n", __func__, cfp->name, val);
}
if (IS_TOKEN_FRONTEND(token)) {
return frontrot_set_conf(rot, token, val);
}
if (rot->caps->set_conf == NULL) {
return -RIG_ENAVAIL;
}
return rot->caps->set_conf(rot, token, val);
} }
/** /**
* \brief get the value of a configuration parameter * \brief get the value of a configuration parameter
* \param rot The rot handle * \param rot The rot handle
* \param token The parameter * \param token The parameter
* \param val The location where to store the value of config \a token * \param val The location where to store the value of config \a token
* *
* Retrieves the value of a configuration paramter associated with \a token. * Retrieves the value of a configuration paramter associated with \a token.
* *
@ -448,16 +602,21 @@ int HAMLIB_API rot_set_conf(ROT *rot, token_t token, const char *val)
*/ */
int HAMLIB_API rot_get_conf(ROT *rot, token_t token, char *val) int HAMLIB_API rot_get_conf(ROT *rot, token_t token, char *val)
{ {
if (!rot || !rot->caps || !val) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
if (IS_TOKEN_FRONTEND(token)) if (!rot || !rot->caps || !val) {
return frontrot_get_conf(rot, token, val); return -RIG_EINVAL;
}
if (rot->caps->get_conf == NULL) if (IS_TOKEN_FRONTEND(token)) {
return -RIG_ENAVAIL; return frontrot_get_conf(rot, token, val);
}
return rot->caps->get_conf(rot, token, val); if (rot->caps->get_conf == NULL) {
return -RIG_ENAVAIL;
}
return rot->caps->get_conf(rot, token, val);
} }
/** @} */ /** @} */

Wyświetl plik

@ -48,10 +48,15 @@
#define ROT_BACKEND_MAX 32 #define ROT_BACKEND_MAX 32
#define DEFINE_INITROT_BACKEND(backend) \ #define DEFINE_INITROT_BACKEND(backend) \
int MAKE_VERSIONED_FN(PREFIX_INITROTS, ABI_VERSION, backend(void *be_handle)); \ int MAKE_VERSIONED_FN(PREFIX_INITROTS, \
rig_model_t MAKE_VERSIONED_FN(PREFIX_PROBEROTS, ABI_VERSION, backend(hamlib_port_t *port, rig_probe_func_t cfunc, rig_ptr_t data)) ABI_VERSION, \
backend(void *be_handle)); \
rig_model_t MAKE_VERSIONED_FN(PREFIX_PROBEROTS, \
ABI_VERSION, \
backend(hamlib_port_t *port, \
rig_probe_func_t cfunc, \
rig_ptr_t data))
#define ROT_FUNCNAMA(backend) MAKE_VERSIONED_FN(PREFIX_INITROTS, ABI_VERSION, backend) #define ROT_FUNCNAMA(backend) MAKE_VERSIONED_FN(PREFIX_INITROTS, ABI_VERSION, backend)
#define ROT_FUNCNAMB(backend) MAKE_VERSIONED_FN(PREFIX_PROBEROTS, ABI_VERSION, backend) #define ROT_FUNCNAMB(backend) MAKE_VERSIONED_FN(PREFIX_PROBEROTS, ABI_VERSION, backend)
@ -77,6 +82,7 @@ DEFINE_INITROT_BACKEND(ether6);
DEFINE_INITROT_BACKEND(cnctrk); DEFINE_INITROT_BACKEND(cnctrk);
DEFINE_INITROT_BACKEND(prosistel); DEFINE_INITROT_BACKEND(prosistel);
/*! \def ROT_BACKEND_LIST /*! \def ROT_BACKEND_LIST
* \brief Static list of rotator models. * \brief Static list of rotator models.
* *
@ -87,40 +93,37 @@ DEFINE_INITROT_BACKEND(prosistel);
* in this array. * in this array.
*/ */
static struct { static struct {
int be_num; int be_num;
const char *be_name; const char *be_name;
int (*be_init)(void *); int (*be_init)(void *);
rot_model_t (*be_probe)(hamlib_port_t *); rot_model_t (*be_probe)(hamlib_port_t *);
} rot_backend_list[ROT_BACKEND_MAX] = } rot_backend_list[ROT_BACKEND_MAX] = {
{ { ROT_DUMMY, ROT_BACKEND_DUMMY, ROT_FUNCNAMA(dummy) },
{ ROT_DUMMY, ROT_BACKEND_DUMMY, ROT_FUNCNAMA(dummy) }, { ROT_EASYCOMM, ROT_BACKEND_EASYCOMM, ROT_FUNCNAMA(easycomm) },
{ ROT_EASYCOMM, ROT_BACKEND_EASYCOMM, ROT_FUNCNAMA(easycomm) }, { ROT_FODTRACK, ROT_BACKEND_FODTRACK, ROT_FUNCNAMA(fodtrack) },
{ ROT_FODTRACK, ROT_BACKEND_FODTRACK, ROT_FUNCNAMA(fodtrack) }, { ROT_ROTOREZ, ROT_BACKEND_ROTOREZ, ROT_FUNCNAMA(rotorez) },
{ ROT_ROTOREZ, ROT_BACKEND_ROTOREZ, ROT_FUNCNAMA(rotorez) }, { ROT_SARTEK, ROT_BACKEND_SARTEK, ROT_FUNCNAMA(sartek) },
{ ROT_SARTEK, ROT_BACKEND_SARTEK, ROT_FUNCNAMA(sartek) }, { ROT_GS232A, ROT_BACKEND_GS232A, ROT_FUNCNAMA(gs232a) },
{ ROT_GS232A, ROT_BACKEND_GS232A, ROT_FUNCNAMA(gs232a) }, { ROT_KIT, ROT_BACKEND_KIT, ROT_FUNCNAMA(kit) },
{ ROT_KIT, ROT_BACKEND_KIT, ROT_FUNCNAMA(kit) }, { ROT_HEATHKIT, ROT_BACKEND_HEATHKIT, ROT_FUNCNAMA(heathkit) },
{ ROT_HEATHKIT, ROT_BACKEND_HEATHKIT, ROT_FUNCNAMA(heathkit) }, { ROT_SPID, ROT_BACKEND_SPID, ROT_FUNCNAMA(spid) },
{ ROT_SPID, ROT_BACKEND_SPID, ROT_FUNCNAMA(spid) }, { ROT_M2, ROT_BACKEND_M2, ROT_FUNCNAMA(m2) },
{ ROT_M2, ROT_BACKEND_M2, ROT_FUNCNAMA(m2) }, { ROT_ARS, ROT_BACKEND_ARS, ROT_FUNCNAMA(ars) },
{ ROT_ARS, ROT_BACKEND_ARS, ROT_FUNCNAMA(ars) }, { ROT_AMSAT, ROT_BACKEND_AMSAT, ROT_FUNCNAMA(amsat) },
{ ROT_AMSAT, ROT_BACKEND_AMSAT, ROT_FUNCNAMA(amsat) }, { ROT_TS7400, ROT_BACKEND_TS7400, ROT_FUNCNAMA(ts7400) },
{ ROT_TS7400, ROT_BACKEND_TS7400, ROT_FUNCNAMA(ts7400) }, { ROT_CELESTRON, ROT_BACKEND_CELESTRON, ROT_FUNCNAMA(celestron) },
{ ROT_CELESTRON, ROT_BACKEND_CELESTRON, ROT_FUNCNAMA(celestron) }, { ROT_ETHER6, ROT_BACKEND_ETHER6, ROT_FUNCNAMA(ether6) },
{ ROT_ETHER6, ROT_BACKEND_ETHER6, ROT_FUNCNAMA(ether6) }, { ROT_CNCTRK, ROT_BACKEND_CNCTRK, ROT_FUNCNAMA(cnctrk) },
{ ROT_CNCTRK, ROT_BACKEND_CNCTRK, ROT_FUNCNAMA(cnctrk) }, { ROT_PROSISTEL, ROT_BACKEND_PROSISTEL, ROT_FUNCNAMA(prosistel) },
{ ROT_PROSISTEL, ROT_BACKEND_PROSISTEL, ROT_FUNCNAMA(prosistel) }, { 0, NULL }, /* end */
{ 0, NULL }, /* end */
}; };
// Apparently, no rotator can be probed. // Apparently, no rotator can be probed.
/* /*
* ROT_BACKEND_LIST is here, please keep it up to data, * ROT_BACKEND_LIST is here, please keep it up to date,
* ie. each time you give birth to a new backend * i.e. each time you implement a new backend.
* Also, it should be possible to register "external" backend,
* that is backend that were not known by Hamlib at compile time.
* Maybe, rotlist.h should reserve some numbers for them? --SF
*/ */
@ -129,69 +132,81 @@ static struct {
* It is chained, and used in a hash table, see below. * It is chained, and used in a hash table, see below.
*/ */
struct rot_list { struct rot_list {
const struct rot_caps *caps; const struct rot_caps *caps;
struct rot_list *next; struct rot_list *next;
}; };
#define ROTLSTHASHSZ 16 #define ROTLSTHASHSZ 16
#define HASH_FUNC(a) ((a)%ROTLSTHASHSZ) #define HASH_FUNC(a) ((a)%ROTLSTHASHSZ)
/* /*
* The rot_hash_table is a hash table pointing to a list of next==NULL * The rot_hash_table is a hash table pointing to a list of next==NULL
* terminated caps. * terminated caps.
*/ */
static struct rot_list *rot_hash_table[ROTLSTHASHSZ] = { NULL, }; static struct rot_list *rot_hash_table[ROTLSTHASHSZ] = { NULL, };
static int rot_lookup_backend(rot_model_t rot_model); static int rot_lookup_backend(rot_model_t rot_model);
/* /*
* Basically, this is a hash insert function that doesn't check for dup! * Basically, this is a hash insert function that doesn't check for dup!
*/ */
int HAMLIB_API rot_register(const struct rot_caps *caps) int HAMLIB_API rot_register(const struct rot_caps *caps)
{ {
int hval; int hval;
struct rot_list *p; struct rot_list *p;
if (!caps) if (!caps) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
rot_debug(RIG_DEBUG_VERBOSE, "rot_register (%d)\n",caps->rot_model); rot_debug(RIG_DEBUG_VERBOSE, "rot_register (%d)\n", caps->rot_model);
#ifndef DONT_WANT_DUP_CHECK #ifndef DONT_WANT_DUP_CHECK
if (rot_get_caps(caps->rot_model)!=NULL)
return -RIG_EINVAL; if (rot_get_caps(caps->rot_model) != NULL) {
return -RIG_EINVAL;
}
#endif #endif
p = (struct rot_list*)malloc(sizeof(struct rot_list)); p = (struct rot_list *)malloc(sizeof(struct rot_list));
if (!p)
return -RIG_ENOMEM;
hval = HASH_FUNC(caps->rot_model); if (!p) {
p->caps = caps; return -RIG_ENOMEM;
// p->handle = NULL; }
p->next = rot_hash_table[hval];
rot_hash_table[hval] = p;
return RIG_OK; hval = HASH_FUNC(caps->rot_model);
p->caps = caps;
// p->handle = NULL;
p->next = rot_hash_table[hval];
rot_hash_table[hval] = p;
return RIG_OK;
} }
/* /*
* Get rot capabilities. * Get rot capabilities.
* ie. rot_hash_table lookup * i.e. rot_hash_table lookup
*/ */
const struct rot_caps * HAMLIB_API rot_get_caps(rot_model_t rot_model) const struct rot_caps * HAMLIB_API rot_get_caps(rot_model_t rot_model)
{ {
struct rot_list *p; struct rot_list *p;
for (p = rot_hash_table[HASH_FUNC(rot_model)]; p; p=p->next) { for (p = rot_hash_table[HASH_FUNC(rot_model)]; p; p = p->next) {
if (p->caps->rot_model == rot_model) if (p->caps->rot_model == rot_model) {
return p->caps; return p->caps;
} }
return NULL; /* sorry, caps not registered! */ }
return NULL; /* sorry, caps not registered! */
} }
/* /*
* lookup for backend index in rot_backend_list table, * lookup for backend index in rot_backend_list table,
* according to BACKEND_NUM * according to BACKEND_NUM
@ -199,16 +214,19 @@ const struct rot_caps * HAMLIB_API rot_get_caps(rot_model_t rot_model)
*/ */
static int rot_lookup_backend(rot_model_t rot_model) static int rot_lookup_backend(rot_model_t rot_model)
{ {
int i; int i;
for (i=0; i<ROT_BACKEND_MAX && rot_backend_list[i].be_name; i++) { for (i = 0; i < ROT_BACKEND_MAX && rot_backend_list[i].be_name; i++) {
if (ROT_BACKEND_NUM(rot_model) == if (ROT_BACKEND_NUM(rot_model) ==
rot_backend_list[i].be_num) rot_backend_list[i].be_num) {
return i; return i;
} }
return -1; }
return -1;
} }
/* /*
* rot_check_backend * rot_check_backend
* check the backend declaring this model has been loaded * check the backend declaring this model has been loaded
@ -217,128 +235,148 @@ static int rot_lookup_backend(rot_model_t rot_model)
*/ */
int HAMLIB_API rot_check_backend(rot_model_t rot_model) int HAMLIB_API rot_check_backend(rot_model_t rot_model)
{ {
const struct rot_caps *caps; const struct rot_caps *caps;
int be_idx; int be_idx;
int retval; int retval;
/* already loaded ? */ /* already loaded ? */
caps = rot_get_caps(rot_model); caps = rot_get_caps(rot_model);
if (caps)
return RIG_OK;
be_idx = rot_lookup_backend(rot_model); if (caps) {
return RIG_OK;
}
/* be_idx = rot_lookup_backend(rot_model);
* Never heard about this backend family!
*/
if (be_idx == -1) {
rot_debug(RIG_DEBUG_VERBOSE, "rot_check_backend: unsupported "
"backend %d for model %d\n",
ROT_BACKEND_NUM(rot_model), rot_model);
return -RIG_ENAVAIL;
}
retval = rot_load_backend(rot_backend_list[be_idx].be_name); /*
* Never heard about this backend family!
*/
if (be_idx == -1) {
rot_debug(RIG_DEBUG_VERBOSE,
"%s: unsupported backend %d for model %d\n",
__func__,
ROT_BACKEND_NUM(rot_model), rot_model);
return retval; return -RIG_ENAVAIL;
}
retval = rot_load_backend(rot_backend_list[be_idx].be_name);
return retval;
} }
int HAMLIB_API rot_unregister(rot_model_t rot_model) int HAMLIB_API rot_unregister(rot_model_t rot_model)
{ {
int hval; int hval;
struct rot_list *p,*q; struct rot_list *p, *q;
hval = HASH_FUNC(rot_model); hval = HASH_FUNC(rot_model);
q = NULL; q = NULL;
for (p = rot_hash_table[hval]; p; p=p->next) {
if (p->caps->rot_model == rot_model) { for (p = rot_hash_table[hval]; p; p = p->next) {
if (q == NULL) if (p->caps->rot_model == rot_model) {
rot_hash_table[hval] = p->next; if (q == NULL) {
else rot_hash_table[hval] = p->next;
q->next = p->next; } else {
free(p); q->next = p->next;
return RIG_OK; }
}
q = p; free(p);
} return RIG_OK;
return -RIG_EINVAL; /* sorry, caps not registered! */ }
q = p;
}
return -RIG_EINVAL; /* sorry, caps not registered! */
} }
/* /*
* rot_list_foreach * rot_list_foreach
* executes cfunc on all the elements stored in the rot hash list * executes cfunc on all the elements stored in the rot hash list
*/ */
int HAMLIB_API rot_list_foreach(int (*cfunc)(const struct rot_caps*, rig_ptr_t),rig_ptr_t data) int HAMLIB_API rot_list_foreach(int (*cfunc)(const struct rot_caps *, rig_ptr_t),
rig_ptr_t data)
{ {
struct rot_list *p; struct rot_list *p;
int i; int i;
if (!cfunc) if (!cfunc) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
for (i=0; i<ROTLSTHASHSZ; i++) { for (i = 0; i < ROTLSTHASHSZ; i++) {
for (p=rot_hash_table[i]; p; p=p->next) for (p = rot_hash_table[i]; p; p = p->next)
if ((*cfunc)(p->caps,data) == 0) if ((*cfunc)(p->caps, data) == 0) {
return RIG_OK; return RIG_OK;
} }
return RIG_OK; }
return RIG_OK;
} }
/* /*
* rot_probe_all * rot_probe_all
* called straight by rot_probe * called straight by rot_probe
*/ */
rot_model_t HAMLIB_API rot_probe_all(hamlib_port_t *p) rot_model_t HAMLIB_API rot_probe_all(hamlib_port_t *p)
{ {
int i; int i;
rot_model_t rot_model; rot_model_t rot_model;
for (i=0; i<ROT_BACKEND_MAX && rot_backend_list[i].be_name; i++) { for (i = 0; i < ROT_BACKEND_MAX && rot_backend_list[i].be_name; i++) {
if (rot_backend_list[i].be_probe) { if (rot_backend_list[i].be_probe) {
rot_model = (*rot_backend_list[i].be_probe)(p); rot_model = (*rot_backend_list[i].be_probe)(p);
if (rot_model != ROT_MODEL_NONE)
return rot_model; if (rot_model != ROT_MODEL_NONE) {
} return rot_model;
} }
return ROT_MODEL_NONE; }
}
return ROT_MODEL_NONE;
} }
int rot_load_all_backends() int rot_load_all_backends()
{ {
int i; int i;
for (i=0; i<ROT_BACKEND_MAX && rot_backend_list[i].be_name; i++) { for (i = 0; i < ROT_BACKEND_MAX && rot_backend_list[i].be_name; i++) {
rot_load_backend(rot_backend_list[i].be_name); rot_load_backend(rot_backend_list[i].be_name);
} }
return RIG_OK;
return RIG_OK;
} }
/* /*
* rot_load_backend * rot_load_backend
* Dynamically load a rot backend through dlopen mechanism * Dynamically load a rot backend through dlopen mechanism
*/ */
int HAMLIB_API rot_load_backend(const char *be_name) int HAMLIB_API rot_load_backend(const char *be_name)
{ {
int status; int status;
int (*be_init)(rig_ptr_t); int (*be_init)(rig_ptr_t);
int i; int i;
for (i=0; i<ROT_BACKEND_MAX && rot_backend_list[i].be_name; i++) { for (i = 0; i < ROT_BACKEND_MAX && rot_backend_list[i].be_name; i++) {
if (!strcmp(be_name, rot_backend_list[i].be_name)) { if (!strcmp(be_name, rot_backend_list[i].be_name)) {
be_init = rot_backend_list[i].be_init; be_init = rot_backend_list[i].be_init;
if( be_init == NULL )
{
printf("Null\n");
return -EINVAL;
}
status = (*be_init)(NULL);
return status;
}
}
return -EINVAL; if (be_init == NULL) {
printf("Null\n");
return -EINVAL;
}
status = (*be_init)(NULL);
return status;
}
}
return -EINVAL;
} }

Wyświetl plik

@ -54,7 +54,7 @@
#include <fcntl.h> #include <fcntl.h>
#include "hamlib/rotator.h" #include <hamlib/rotator.h>
#include "serial.h" #include "serial.h"
#include "parallel.h" #include "parallel.h"
#include "usb_port.h" #include "usb_port.h"
@ -85,56 +85,66 @@
#define CHECK_ROT_ARG(r) (!(r) || !(r)->caps || !(r)->state.comm_state) #define CHECK_ROT_ARG(r) (!(r) || !(r)->caps || !(r)->state.comm_state)
/* /*
* Data structure to track the opened rot (by rot_open) * Data structure to track the opened rot (by rot_open)
*/ */
struct opened_rot_l { struct opened_rot_l {
ROT *rot; ROT *rot;
struct opened_rot_l *next; struct opened_rot_l *next;
}; };
static struct opened_rot_l *opened_rot_list = { NULL }; static struct opened_rot_l *opened_rot_list = { NULL };
/* /*
* track which rot is opened (with rot_open) * track which rot is opened (with rot_open)
* needed at least for transceive mode * needed at least for transceive mode
*/ */
static int add_opened_rot(ROT *rot) static int add_opened_rot(ROT *rot)
{ {
struct opened_rot_l *p; struct opened_rot_l *p;
p = (struct opened_rot_l *)malloc(sizeof(struct opened_rot_l)); p = (struct opened_rot_l *)malloc(sizeof(struct opened_rot_l));
if (!p)
return -RIG_ENOMEM; if (!p) {
p->rot = rot; return -RIG_ENOMEM;
p->next = opened_rot_list; }
opened_rot_list = p;
return RIG_OK; p->rot = rot;
p->next = opened_rot_list;
opened_rot_list = p;
return RIG_OK;
} }
static int remove_opened_rot(ROT *rot) static int remove_opened_rot(ROT *rot)
{ {
struct opened_rot_l *p,*q; struct opened_rot_l *p, *q;
q = NULL; q = NULL;
for (p=opened_rot_list; p; p=p->next) { for (p = opened_rot_list; p; p = p->next) {
if (p->rot == rot) { if (p->rot == rot) {
if (q == NULL) { if (q == NULL) {
opened_rot_list = opened_rot_list->next; opened_rot_list = opened_rot_list->next;
} else { } else {
q->next = p->next; q->next = p->next;
} }
free(p);
return RIG_OK; free(p);
} return RIG_OK;
q = p; }
}
return -RIG_EINVAL; /* Not found in list ! */ q = p;
}
return -RIG_EINVAL; /* Not found in list ! */
} }
#endif /* !DOC_HIDDEN */ #endif /* !DOC_HIDDEN */
/** /**
* \brief execs cfunc() on each opened rot * \brief execs cfunc() on each opened rot
* \param cfunc The function to be executed on each rot * \param cfunc The function to be executed on each rot
* \param data Data pointer to be passed to cfunc() * \param data Data pointer to be passed to cfunc()
* *
* Calls cfunc() function for each opened rot. * Calls cfunc() function for each opened rot.
* The contents of the opened rot table * The contents of the opened rot table
@ -149,21 +159,25 @@ static int remove_opened_rot(ROT *rot)
* *
* \return always RIG_OK. * \return always RIG_OK.
*/ */
int foreach_opened_rot(int (*cfunc)(ROT *, rig_ptr_t), rig_ptr_t data) int foreach_opened_rot(int (*cfunc)(ROT *, rig_ptr_t), rig_ptr_t data)
{ {
struct opened_rot_l *p; struct opened_rot_l *p;
for (p=opened_rot_list; p; p=p->next) { rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if ((*cfunc)(p->rot,data) == 0)
return RIG_OK; for (p = opened_rot_list; p; p = p->next) {
} if ((*cfunc)(p->rot, data) == 0) {
return RIG_OK; return RIG_OK;
}
}
return RIG_OK;
} }
/** /**
* \brief allocate a new #ROT handle * \brief allocate a new #ROT handle
* \param rot_model The rot model for this new handle * \param rot_model The rot model for this new handle
* *
* Allocates a new #ROT handle and initializes the associated data * Allocates a new #ROT handle and initializes the associated data
* for \a rot_model. * for \a rot_model.
@ -173,105 +187,110 @@ int foreach_opened_rot(int (*cfunc)(ROT *, rig_ptr_t), rig_ptr_t data)
* *
* \sa rot_cleanup(), rot_open() * \sa rot_cleanup(), rot_open()
*/ */
ROT *HAMLIB_API rot_init(rot_model_t rot_model)
ROT * HAMLIB_API rot_init(rot_model_t rot_model)
{ {
ROT *rot; ROT *rot;
const struct rot_caps *caps; const struct rot_caps *caps;
struct rot_state *rs; struct rot_state *rs;
int retcode; int retcode;
rot_debug(RIG_DEBUG_VERBOSE,"rot:rot_init called \n"); rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
rot_check_backend(rot_model); rot_check_backend(rot_model);
caps = rot_get_caps(rot_model); caps = rot_get_caps(rot_model);
if (!caps)
return NULL;
/* if (!caps) {
* okay, we've found it. Allocate some memory and set it to zeros, return NULL;
* and especially the initialize the callbacks }
*/
rot = calloc(1, sizeof(ROT));
if (rot == NULL) {
/*
* FIXME: how can the caller know it's a memory shortage,
* and not "rot not found" ?
*/
return NULL;
}
/* caps is const, so we need to tell compiler /*
that we now what we are doing */ * okay, we've found it. Allocate some memory and set it to zeros,
rot->caps = (struct rot_caps *) caps; * and especially the initialize the callbacks
*/
rot = calloc(1, sizeof(ROT));
/* if (rot == NULL) {
* populate the rot->state /*
* TODO: read the Preferences here! * FIXME: how can the caller know it's a memory shortage,
*/ * and not "rot not found" ?
*/
return NULL;
}
rs = &rot->state; /* caps is const, so we need to tell compiler
that we know what we are doing */
rot->caps = (struct rot_caps *) caps;
rs->comm_state = 0; /*
rs->rotport.type.rig = caps->port_type; /* default from caps */ * populate the rot->state
* TODO: read the Preferences here!
*/
rs = &rot->state;
rs->rotport.write_delay = caps->write_delay; rs->comm_state = 0;
rs->rotport.post_write_delay = caps->post_write_delay; rs->rotport.type.rig = caps->port_type; /* default from caps */
rs->rotport.timeout = caps->timeout;
rs->rotport.retry = caps->retry;
switch (caps->port_type) { rs->rotport.write_delay = caps->write_delay;
case RIG_PORT_SERIAL: rs->rotport.post_write_delay = caps->post_write_delay;
strncpy(rs->rotport.pathname, DEFAULT_SERIAL_PORT, FILPATHLEN - 1); rs->rotport.timeout = caps->timeout;
rs->rotport.parm.serial.rate = caps->serial_rate_max; /* fastest ! */ rs->rotport.retry = caps->retry;
rs->rotport.parm.serial.data_bits = caps->serial_data_bits;
rs->rotport.parm.serial.stop_bits = caps->serial_stop_bits;
rs->rotport.parm.serial.parity = caps->serial_parity;
rs->rotport.parm.serial.handshake = caps->serial_handshake;
break;
case RIG_PORT_PARALLEL: switch (caps->port_type) {
strncpy(rs->rotport.pathname, DEFAULT_PARALLEL_PORT, FILPATHLEN - 1); case RIG_PORT_SERIAL:
break; strncpy(rs->rotport.pathname, DEFAULT_SERIAL_PORT, FILPATHLEN - 1);
rs->rotport.parm.serial.rate = caps->serial_rate_max; /* fastest ! */
rs->rotport.parm.serial.data_bits = caps->serial_data_bits;
rs->rotport.parm.serial.stop_bits = caps->serial_stop_bits;
rs->rotport.parm.serial.parity = caps->serial_parity;
rs->rotport.parm.serial.handshake = caps->serial_handshake;
break;
case RIG_PORT_NETWORK: case RIG_PORT_PARALLEL:
case RIG_PORT_UDP_NETWORK: strncpy(rs->rotport.pathname, DEFAULT_PARALLEL_PORT, FILPATHLEN - 1);
strncpy(rs->rotport.pathname, "127.0.0.1:4533", FILPATHLEN - 1); break;
break;
default: case RIG_PORT_NETWORK:
strncpy(rs->rotport.pathname, "", FILPATHLEN - 1); case RIG_PORT_UDP_NETWORK:
} strncpy(rs->rotport.pathname, "127.0.0.1:4533", FILPATHLEN - 1);
break;
rs->min_el = caps->min_el; default:
rs->max_el = caps->max_el; strncpy(rs->rotport.pathname, "", FILPATHLEN - 1);
rs->min_az = caps->min_az; }
rs->max_az = caps->max_az;
rs->rotport.fd = -1; rs->min_el = caps->min_el;
rs->max_el = caps->max_el;
rs->min_az = caps->min_az;
rs->max_az = caps->max_az;
/* rs->rotport.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 rot_state.
*/
if (caps->rot_init != NULL) {
retcode = caps->rot_init(rot);
if (retcode != RIG_OK) {
rot_debug(RIG_DEBUG_VERBOSE,"rot:backend_init failed!\n");
/* cleanup and exit */
free(rot);
return NULL;
}
}
return rot; /*
* 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 rot_state.
*/
if (caps->rot_init != NULL) {
retcode = caps->rot_init(rot);
if (retcode != RIG_OK) {
rot_debug(RIG_DEBUG_VERBOSE,
"%s: backend_init failed!\n",
__func__);
/* cleanup and exit */
free(rot);
return NULL;
}
}
return rot;
} }
/** /**
* \brief open the communication to the rot * \brief open the communication to the rot
* \param rot The #ROT handle of the rotator to be opened * \param rot The #ROT handle of the rotator to be opened
* *
* Opens communication to a rotator which \a ROT handle has been passed * Opens communication to a rotator which \a ROT handle has been passed
* by argument. * by argument.
@ -280,95 +299,113 @@ ROT * HAMLIB_API rot_init(rot_model_t rot_model)
* a negative value if an error occured (in which case, cause is * a negative value if an error occured (in which case, cause is
* set appropriately). * set appropriately).
* *
* \retval RIG_EINVAL \a rot is NULL or unconsistent. * \retval RIG_EINVAL \a rot is NULL or unconsistent.
* \retval RIG_ENIMPL port type communication is not implemented yet. * \retval RIG_ENIMPL port type communication is not implemented yet.
* *
* \sa rot_init(), rot_close() * \sa rot_init(), rot_close()
*/ */
int HAMLIB_API rot_open(ROT *rot) int HAMLIB_API rot_open(ROT *rot)
{ {
const struct rot_caps *caps; const struct rot_caps *caps;
struct rot_state *rs; struct rot_state *rs;
int status; int status;
rot_debug(RIG_DEBUG_VERBOSE,"rot:rot_open called \n"); rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!rot || !rot->caps) if (!rot || !rot->caps) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
caps = rot->caps; caps = rot->caps;
rs = &rot->state; rs = &rot->state;
if (rs->comm_state) if (rs->comm_state) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
rs->rotport.fd = -1; rs->rotport.fd = -1;
switch(rs->rotport.type.rig) { switch (rs->rotport.type.rig) {
case RIG_PORT_SERIAL: case RIG_PORT_SERIAL:
status = serial_open(&rs->rotport); status = serial_open(&rs->rotport);
if (status != 0)
return status;
break;
case RIG_PORT_PARALLEL: if (status != 0) {
status = par_open(&rs->rotport); return status;
if (status < 0) }
return status;
break;
case RIG_PORT_DEVICE: break;
status = open(rs->rotport.pathname, O_RDWR, 0);
if (status < 0)
return -RIG_EIO;
rs->rotport.fd = status;
break;
case RIG_PORT_USB: case RIG_PORT_PARALLEL:
status = usb_port_open(&rs->rotport); status = par_open(&rs->rotport);
if (status < 0)
return status;
break;
case RIG_PORT_NONE: if (status < 0) {
case RIG_PORT_RPC: return status;
break; /* ez :) */ }
case RIG_PORT_NETWORK: break;
case RIG_PORT_UDP_NETWORK:
case RIG_PORT_DEVICE:
status = open(rs->rotport.pathname, O_RDWR, 0);
if (status < 0) {
return -RIG_EIO;
}
rs->rotport.fd = status;
break;
case RIG_PORT_USB:
status = usb_port_open(&rs->rotport);
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 */ /* FIXME: default port */
status = network_open(&rs->rotport, 4533); status = network_open(&rs->rotport, 4533);
if (status < 0)
return status;
break;
default: if (status < 0) {
return -RIG_EINVAL; return status;
} }
break;
default:
return -RIG_EINVAL;
}
add_opened_rot(rot); add_opened_rot(rot);
rs->comm_state = 1; rs->comm_state = 1;
/* /*
* Maybe the backend has something to initialize * Maybe the backend has something to initialize
* In case of failure, just close down and report error code. * In case of failure, just close down and report error code.
*/ */
if (caps->rot_open != NULL) { if (caps->rot_open != NULL) {
status = caps->rot_open(rot); status = caps->rot_open(rot);
if (status != RIG_OK) {
return status;
}
}
return RIG_OK; if (status != RIG_OK) {
return status;
}
}
return RIG_OK;
} }
/** /**
* \brief close the communication to the rot * \brief close the communication to the rot
* \param rot The #ROT handle of the rotator to be closed * \param rot The #ROT handle of the rotator to be closed
* *
* Closes communication to a rotator which \a ROT handle has been passed * Closes communication to a rotator which \a ROT handle has been passed
* by argument that was previously open with rot_open(). * by argument that was previously open with rot_open().
@ -379,62 +416,70 @@ int HAMLIB_API rot_open(ROT *rot)
* *
* \sa rot_cleanup(), rot_open() * \sa rot_cleanup(), rot_open()
*/ */
int HAMLIB_API rot_close(ROT *rot) int HAMLIB_API rot_close(ROT *rot)
{ {
const struct rot_caps *caps; const struct rot_caps *caps;
struct rot_state *rs; struct rot_state *rs;
rot_debug(RIG_DEBUG_VERBOSE,"rot:rot_close called \n"); rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!rot || !rot->caps) if (!rot || !rot->caps) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
caps = rot->caps; caps = rot->caps;
rs = &rot->state; rs = &rot->state;
if (!rs->comm_state) if (!rs->comm_state) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
/* /*
* Let the backend say 73s to the rot. * Let the backend say 73s to the rot.
* and ignore the return code. * and ignore the return code.
*/ */
if (caps->rot_close) if (caps->rot_close) {
caps->rot_close(rot); caps->rot_close(rot);
}
if (rs->rotport.fd != -1) { if (rs->rotport.fd != -1) {
switch(rs->rotport.type.rig) { switch (rs->rotport.type.rig) {
case RIG_PORT_SERIAL: case RIG_PORT_SERIAL:
ser_close(&rs->rotport); ser_close(&rs->rotport);
break; break;
case RIG_PORT_PARALLEL:
par_close(&rs->rotport);
break;
case RIG_PORT_USB:
usb_port_close(&rs->rotport);
break;
case RIG_PORT_NETWORK:
case RIG_PORT_UDP_NETWORK:
network_close(&rs->rotport);
break;
default:
close(rs->rotport.fd);
}
rs->rotport.fd = -1;
}
remove_opened_rot(rot); case RIG_PORT_PARALLEL:
par_close(&rs->rotport);
break;
rs->comm_state = 0; case RIG_PORT_USB:
usb_port_close(&rs->rotport);
break;
return RIG_OK; case RIG_PORT_NETWORK:
case RIG_PORT_UDP_NETWORK:
network_close(&rs->rotport);
break;
default:
close(rs->rotport.fd);
}
rs->rotport.fd = -1;
}
remove_opened_rot(rot);
rs->comm_state = 0;
return RIG_OK;
} }
/** /**
* \brief release a rot handle and free associated memory * \brief release a rot handle and free associated memory
* \param rot The #ROT handle of the radio to be closed * \param rot The #ROT handle of the radio to be closed
* *
* Releases a rot struct which port has eventualy been closed already * Releases a rot struct which port has eventualy been closed already
* with rot_close(). * with rot_close().
@ -445,36 +490,39 @@ int HAMLIB_API rot_close(ROT *rot)
* *
* \sa rot_init(), rot_close() * \sa rot_init(), rot_close()
*/ */
int HAMLIB_API rot_cleanup(ROT *rot) int HAMLIB_API rot_cleanup(ROT *rot)
{ {
rot_debug(RIG_DEBUG_VERBOSE,"rot:rot_cleanup called \n"); rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!rot || !rot->caps) if (!rot || !rot->caps) {
return -RIG_EINVAL; return -RIG_EINVAL;
}
/* /*
* check if they forgot to close the rot * check if they forgot to close the rot
*/ */
if (rot->state.comm_state) if (rot->state.comm_state) {
rot_close(rot); rot_close(rot);
}
/* /*
* basically free up the priv struct * basically free up the priv struct
*/ */
if (rot->caps->rot_cleanup) if (rot->caps->rot_cleanup) {
rot->caps->rot_cleanup(rot); rot->caps->rot_cleanup(rot);
}
free(rot); free(rot);
return RIG_OK; return RIG_OK;
} }
/** /**
* \brief set the azimuth and elevation of the rotator * \brief set the azimuth and elevation of the rotator
* \param rot The rot handle * \param rot The rot handle
* \param azimuth The azimuth to set to * \param azimuth The azimuth to set to
* \param elevation The elevation to set to * \param elevation The elevation to set to
* *
* Sets the azimuth and elevation of the rotator. * Sets the azimuth and elevation of the rotator.
* *
@ -484,33 +532,41 @@ int HAMLIB_API rot_cleanup(ROT *rot)
* *
* \sa rot_get_position() * \sa rot_get_position()
*/ */
int HAMLIB_API rot_set_position(ROT *rot, azimuth_t azimuth,
int HAMLIB_API rot_set_position (ROT *rot, azimuth_t azimuth, elevation_t elevation) elevation_t elevation)
{ {
const struct rot_caps *caps; const struct rot_caps *caps;
const struct rot_state *rs; const struct rot_state *rs;
if (CHECK_ROT_ARG(rot)) rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rot->caps; if (CHECK_ROT_ARG(rot)) {
rs = &rot->state; return -RIG_EINVAL;
}
if (azimuth < rs->min_az || azimuth > rs->max_az || caps = rot->caps;
elevation < rs->min_el || elevation > rs->max_el) rs = &rot->state;
return -RIG_EINVAL;
if (caps->set_position == NULL) if (azimuth < rs->min_az
return -RIG_ENAVAIL; || azimuth > rs->max_az
|| elevation < rs->min_el
|| elevation > rs->max_el) {
return -RIG_EINVAL;
}
return caps->set_position(rot, azimuth, elevation); if (caps->set_position == NULL) {
return -RIG_ENAVAIL;
}
return caps->set_position(rot, azimuth, elevation);
} }
/** /**
* \brief get the azimuth and elevation of the rotator * \brief get the azimuth and elevation of the rotator
* \param rot The rot handle * \param rot The rot handle
* \param azimuth The location where to store the current azimuth * \param azimuth The location where to store the current azimuth
* \param elevation The location where to store the current elevation * \param elevation The location where to store the current elevation
* *
* Retrieves the current azimuth and elevation of the rotator. * Retrieves the current azimuth and elevation of the rotator.
* *
@ -520,25 +576,30 @@ int HAMLIB_API rot_set_position (ROT *rot, azimuth_t azimuth, elevation_t elevat
* *
* \sa rot_set_position() * \sa rot_set_position()
*/ */
int HAMLIB_API rot_get_position(ROT *rot, azimuth_t *azimuth,
int HAMLIB_API rot_get_position (ROT *rot, azimuth_t *azimuth, elevation_t *elevation) elevation_t *elevation)
{ {
const struct rot_caps *caps; const struct rot_caps *caps;
if (CHECK_ROT_ARG(rot) || !azimuth || !elevation) rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rot->caps; if (CHECK_ROT_ARG(rot) || !azimuth || !elevation) {
return -RIG_EINVAL;
}
if (caps->get_position == NULL) caps = rot->caps;
return -RIG_ENAVAIL;
return caps->get_position(rot, azimuth, elevation); if (caps->get_position == NULL) {
return -RIG_ENAVAIL;
}
return caps->get_position(rot, azimuth, elevation);
} }
/** /**
* \brief park the antenna * \brief park the antenna
* \param rot The rot handle * \param rot The rot handle
* *
* Park the antenna. * Park the antenna.
* *
@ -547,25 +608,29 @@ int HAMLIB_API rot_get_position (ROT *rot, azimuth_t *azimuth, elevation_t *elev
* set appropriately). * set appropriately).
* *
*/ */
int HAMLIB_API rot_park(ROT *rot)
int HAMLIB_API rot_park (ROT *rot)
{ {
const struct rot_caps *caps; const struct rot_caps *caps;
if (CHECK_ROT_ARG(rot)) rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rot->caps; if (CHECK_ROT_ARG(rot)) {
return -RIG_EINVAL;
}
if (caps->park == NULL) caps = rot->caps;
return -RIG_ENAVAIL;
return caps->park(rot); if (caps->park == NULL) {
return -RIG_ENAVAIL;
}
return caps->park(rot);
} }
/** /**
* \brief stop the rotator * \brief stop the rotator
* \param rot The rot handle * \param rot The rot handle
* *
* Stop the rotator. * Stop the rotator.
* *
@ -574,25 +639,29 @@ int HAMLIB_API rot_park (ROT *rot)
* set appropriately). * set appropriately).
* *
*/ */
int HAMLIB_API rot_stop(ROT *rot)
int HAMLIB_API rot_stop (ROT *rot)
{ {
const struct rot_caps *caps; const struct rot_caps *caps;
if (CHECK_ROT_ARG(rot)) rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rot->caps; if (CHECK_ROT_ARG(rot)) {
return -RIG_EINVAL;
}
if (caps->stop == NULL) caps = rot->caps;
return -RIG_ENAVAIL;
return caps->stop(rot); if (caps->stop == NULL) {
return -RIG_ENAVAIL;
}
return caps->stop(rot);
} }
/** /**
* \brief reset the rotator * \brief reset the rotator
* \param rot The rot handle * \param rot The rot handle
* \param reset The reset operation to perform * \param reset The reset operation to perform
* *
* Resets the rotator. * Resets the rotator.
@ -602,22 +671,26 @@ int HAMLIB_API rot_stop (ROT *rot)
* set appropriately). * set appropriately).
* *
*/ */
int HAMLIB_API rot_reset(ROT *rot, rot_reset_t reset)
int HAMLIB_API rot_reset (ROT *rot, rot_reset_t reset)
{ {
const struct rot_caps *caps; const struct rot_caps *caps;
if (CHECK_ROT_ARG(rot)) rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rot->caps; if (CHECK_ROT_ARG(rot)) {
return -RIG_EINVAL;
}
if (caps->reset == NULL) caps = rot->caps;
return -RIG_ENAVAIL;
return caps->reset(rot, reset); if (caps->reset == NULL) {
return -RIG_ENAVAIL;
}
return caps->reset(rot, reset);
} }
/** /**
* \brief move the rotator in the specified direction * \brief move the rotator in the specified direction
* \param rot The rot handle * \param rot The rot handle
@ -627,24 +700,29 @@ int HAMLIB_API rot_reset (ROT *rot, rot_reset_t reset)
* Move the rotator in the specified direction. The speed is a value * Move the rotator in the specified direction. The speed is a value
* between 1 and 100. * between 1 and 100.
*/ */
int HAMLIB_API rot_move (ROT *rot, int direction, int speed) int HAMLIB_API rot_move(ROT *rot, int direction, int speed)
{ {
const struct rot_caps *caps; const struct rot_caps *caps;
if (CHECK_ROT_ARG(rot)) rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rot->caps; if (CHECK_ROT_ARG(rot)) {
return -RIG_EINVAL;
}
if (caps->move == NULL) caps = rot->caps;
return -RIG_ENAVAIL;
return caps->move(rot, direction, speed); if (caps->move == NULL) {
return -RIG_ENAVAIL;
}
return caps->move(rot, direction, speed);
} }
/** /**
* \brief get general information from the rotator * \brief get general information from the rotator
* \param rot The rot handle * \param rot The rot handle
* *
* Retrieves some general information from the rotator. * Retrieves some general information from the rotator.
* This can include firmware revision, exact model name, or just nothing. * This can include firmware revision, exact model name, or just nothing.
@ -653,15 +731,19 @@ int HAMLIB_API rot_move (ROT *rot, int direction, int speed)
* if the operation has been sucessful, otherwise NULL if an error occured * if the operation has been sucessful, otherwise NULL if an error occured
* or get_info not part of capabilities. * or get_info not part of capabilities.
*/ */
const char* HAMLIB_API rot_get_info(ROT *rot) const char *HAMLIB_API rot_get_info(ROT *rot)
{ {
if (CHECK_ROT_ARG(rot)) rot_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return NULL;
if (rot->caps->get_info == NULL) if (CHECK_ROT_ARG(rot)) {
return NULL; return NULL;
}
return rot->caps->get_info(rot); if (rot->caps->get_info == NULL) {
return NULL;
}
return rot->caps->get_info(rot);
} }
/*! @} */ /*! @} */

Wyświetl plik

@ -58,7 +58,7 @@
#else #else
#ifdef HAVE_TERMIO_H #ifdef HAVE_TERMIO_H
#include <termio.h> #include <termio.h>
#else /* sgtty */ #else /* sgtty */
#ifdef HAVE_SGTTY_H #ifdef HAVE_SGTTY_H
#include <sgtty.h> #include <sgtty.h>
#endif #endif
@ -67,7 +67,7 @@
#if defined(WIN32) && !defined(HAVE_TERMIOS_H) #if defined(WIN32) && !defined(HAVE_TERMIOS_H)
#include "win32termios.h" #include "win32termios.h"
#define HAVE_TERMIOS_H 1 /* we have replacement */ #define HAVE_TERMIOS_H 1 /* we have replacement */
#else #else
#define OPEN open #define OPEN open
#define CLOSE close #define CLOSE close
@ -82,44 +82,52 @@
#include <sys/ioccom.h> #include <sys/ioccom.h>
#endif #endif
/** /**
* \brief Open serial port using rig.state data * \brief Open serial port using rig.state data
* \param rp port data structure (must spec port id eg /dev/ttyS1) * \param rp port data structure (must spec port id eg /dev/ttyS1)
* \return RIG_OK or < 0 if error * \return RIG_OK or < 0 if error
*/ */
int HAMLIB_API serial_open(hamlib_port_t *rp) { int HAMLIB_API serial_open(hamlib_port_t *rp)
{
int fd; /* File descriptor for the port */ int fd; /* File descriptor for the port */
int err; int err;
if (!rp) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
/* if (!rp) {
* Open in Non-blocking mode. Watch for EAGAIN errors! return -RIG_EINVAL;
*/ }
fd = OPEN(rp->pathname, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) { /*
* Open in Non-blocking mode. Watch for EAGAIN errors!
*/
fd = OPEN(rp->pathname, O_RDWR | O_NOCTTY | O_NDELAY);
/* Could not open the port. */ if (fd == -1) {
/* Could not open the port. */
rig_debug(RIG_DEBUG_ERR,
"%s: Unable to open %s - %s\n",
__func__,
rp->pathname,
strerror(errno));
return -RIG_EIO;
}
rig_debug(RIG_DEBUG_ERR, "%s: Unable to open %s - %s\n", rp->fd = fd;
__func__, rp->pathname, strerror(errno));
return -RIG_EIO;
}
rp->fd = fd; err = serial_setup(rp);
err = serial_setup(rp); if (err != RIG_OK) {
if (err != RIG_OK) { CLOSE(fd);
CLOSE(fd); return err;
return err; }
}
return RIG_OK; return RIG_OK;
} }
/** /**
* \brief Set up Serial port according to requests in port * \brief Set up Serial port according to requests in port
* \param rp * \param rp
@ -127,265 +135,308 @@ int HAMLIB_API serial_open(hamlib_port_t *rp) {
*/ */
int HAMLIB_API serial_setup(hamlib_port_t *rp) int HAMLIB_API serial_setup(hamlib_port_t *rp)
{ {
int fd; int fd;
/* There's a lib replacement for termios under Mingw */ /* There's a lib replacement for termios under Mingw */
#if defined(HAVE_TERMIOS_H) #if defined(HAVE_TERMIOS_H)
speed_t speed; /* serial comm speed */ speed_t speed; /* serial comm speed */
struct termios options; struct termios options;
#elif defined(HAVE_TERMIO_H) #elif defined(HAVE_TERMIO_H)
struct termio options; struct termio options;
#elif defined(HAVE_SGTTY_H) #elif defined(HAVE_SGTTY_H)
struct sgttyb sg; struct sgttyb sg;
#else #else
#error "No term control supported!" #error "No term control supported!"
#endif #endif
if (!rp) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
fd = rp->fd; if (!rp) {
return -RIG_EINVAL;
}
/* fd = rp->fd;
* Get the current options for the port...
*/
/*
* Get the current options for the port...
*/
#if defined(HAVE_TERMIOS_H) #if defined(HAVE_TERMIOS_H)
tcgetattr(fd, &options); tcgetattr(fd, &options);
#elif defined(HAVE_TERMIO_H) #elif defined(HAVE_TERMIO_H)
IOCTL (fd, TCGETA, &options); IOCTL(fd, TCGETA, &options);
#else /* sgtty */ #else /* sgtty */
IOCTL (fd, TIOCGETP, &sg); IOCTL(fd, TIOCGETP, &sg);
#endif #endif
#ifdef HAVE_CFMAKERAW #ifdef HAVE_CFMAKERAW
cfmakeraw(&options); /* Set serial port to RAW mode by default. */ /* Set serial port to RAW mode by default. */
cfmakeraw(&options);
#endif #endif
/* /*
* Set the baud rates to requested values * Set the baud rates to requested values
*/ */
switch (rp->parm.serial.rate) {
case 150:
speed = B150; /* yikes... */
break;
switch(rp->parm.serial.rate) { case 300:
case 150: speed = B300; /* yikes... */
speed = B150; /* yikes... */ break;
break;
case 300: case 600:
speed = B300; /* yikes... */
break;
case 600:
speed = B600; speed = B600;
break; break;
case 1200:
speed = B1200;
break;
case 2400:
speed = B2400;
break;
case 4800:
speed = B4800;
break;
case 9600:
speed = B9600;
break;
case 19200:
speed = B19200;
break;
case 38400:
speed = B38400;
break;
case 57600:
speed = B57600; /* cool.. */
break;
case 115200:
speed = B115200; /* awsome! */
break;
default:
rig_debug(RIG_DEBUG_ERR, "%s: unsupported rate specified: %d\n",
__func__, rp->parm.serial.rate);
CLOSE(fd);
return -RIG_ECONF;
}
/* TODO */
cfsetispeed(&options, speed);
cfsetospeed(&options, speed);
/* case 1200:
* Enable the receiver and set local mode... speed = B1200;
*/ break;
options.c_cflag |= (CLOCAL | CREAD); case 2400:
speed = B2400;
break;
/* case 4800:
* close doesn't change modem signals speed = B4800;
*/ break;
options.c_cflag &= ~HUPCL;
/* case 9600:
* Set data to requested values. speed = B9600;
* break;
*/
switch(rp->parm.serial.data_bits) { case 19200:
case 7: speed = B19200;
options.c_cflag &= ~CSIZE; break;
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
break;
default:
rig_debug(RIG_DEBUG_ERR, "%s: unsupported serial_data_bits "
"specified: %d\n", __func__, rp->parm.serial.data_bits);
CLOSE(fd);
return -RIG_ECONF;
break;
}
/* case 38400:
* Set stop bits to requested values. speed = B38400;
* break;
*/
switch(rp->parm.serial.stop_bits) { case 57600:
case 1: speed = B57600; /* cool.. */
options.c_cflag &= ~CSTOPB; break;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default: case 115200:
rig_debug(RIG_DEBUG_ERR, "%s: unsupported serial_stop_bits " speed = B115200; /* awesome! */
"specified: %d\n", __func__, break;
rp->parm.serial.stop_bits);
CLOSE(fd);
return -RIG_ECONF;
break;
}
/* default:
* Set parity to requested values. rig_debug(RIG_DEBUG_ERR,
* "%s: unsupported rate specified: %d\n",
*/ __func__,
rp->parm.serial.rate);
CLOSE(fd);
switch(rp->parm.serial.parity) { return -RIG_ECONF;
case RIG_PARITY_NONE: }
options.c_cflag &= ~PARENB;
break; /* TODO */
case RIG_PARITY_EVEN: cfsetispeed(&options, speed);
options.c_cflag |= PARENB; cfsetospeed(&options, speed);
options.c_cflag &= ~PARODD;
break; /*
case RIG_PARITY_ODD: * Enable the receiver and set local mode...
options.c_cflag |= PARENB; */
options.c_cflag |= PARODD; options.c_cflag |= (CLOCAL | CREAD);
break;
/* CMSPAR is not POSIX */ /*
* close doesn't change modem signals
*/
options.c_cflag &= ~HUPCL;
/*
* Set data to requested values.
*
*/
switch (rp->parm.serial.data_bits) {
case 7:
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
break;
default:
rig_debug(RIG_DEBUG_ERR,
"%s: unsupported serial_data_bits specified: %d\n",
__func__,
rp->parm.serial.data_bits);
CLOSE(fd);
return -RIG_ECONF;
break;
}
/*
* Set stop bits to requested values.
*
*/
switch (rp->parm.serial.stop_bits) {
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
rig_debug(RIG_DEBUG_ERR,
"%s: unsupported serial_stop_bits specified: %d\n",
__func__,
rp->parm.serial.stop_bits);
CLOSE(fd);
return -RIG_ECONF;
break;
}
/*
* Set parity to requested values.
*
*/
switch (rp->parm.serial.parity) {
case RIG_PARITY_NONE:
options.c_cflag &= ~PARENB;
break;
case RIG_PARITY_EVEN:
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
break;
case RIG_PARITY_ODD:
options.c_cflag |= PARENB;
options.c_cflag |= PARODD;
break;
/* CMSPAR is not POSIX */
#ifdef CMSPAR #ifdef CMSPAR
case RIG_PARITY_MARK:
options.c_cflag |= PARENB | CMSPAR; case RIG_PARITY_MARK:
options.c_cflag |= PARODD; options.c_cflag |= PARENB | CMSPAR;
break; options.c_cflag |= PARODD;
case RIG_PARITY_SPACE: break;
options.c_cflag |= PARENB | CMSPAR;
options.c_cflag &= ~PARODD; case RIG_PARITY_SPACE:
break; options.c_cflag |= PARENB | CMSPAR;
options.c_cflag &= ~PARODD;
break;
#endif #endif
default:
rig_debug(RIG_DEBUG_ERR, "%s: unsupported serial_parity " default:
"specified: %d\n", __func__, rig_debug(RIG_DEBUG_ERR,
rp->parm.serial.parity); "%s: unsupported serial_parity specified: %d\n",
CLOSE(fd); __func__,
return -RIG_ECONF; rp->parm.serial.parity);
break; CLOSE(fd);
}
return -RIG_ECONF;
break;
}
/* /*
* Set flow control to requested mode * Set flow control to requested mode
* *
*/ */
switch (rp->parm.serial.handshake) {
case RIG_HANDSHAKE_NONE:
options.c_cflag &= ~CRTSCTS;
options.c_iflag &= ~IXON;
break;
switch(rp->parm.serial.handshake) { case RIG_HANDSHAKE_XONXOFF:
case RIG_HANDSHAKE_NONE: options.c_cflag &= ~CRTSCTS;
options.c_cflag &= ~CRTSCTS; options.c_iflag |= IXON; /* Enable Xon/Xoff software handshaking */
options.c_iflag &= ~IXON; break;
break;
case RIG_HANDSHAKE_XONXOFF:
options.c_cflag &= ~CRTSCTS;
options.c_iflag |= IXON; /* Enable Xon/Xoff software handshaking */
break;
case RIG_HANDSHAKE_HARDWARE:
options.c_cflag |= CRTSCTS; /* Enable Hardware handshaking */
options.c_iflag &= ~IXON;
break;
default:
rig_debug(RIG_DEBUG_ERR, "%s: unsupported flow_control "
"specified: %d\n", __func__,
rp->parm.serial.handshake);
CLOSE(fd);
return -RIG_ECONF;
break;
}
/* case RIG_HANDSHAKE_HARDWARE:
* Choose raw input, no preprocessing please .. options.c_cflag |= CRTSCTS; /* Enable Hardware handshaking */
*/ options.c_iflag &= ~IXON;
break;
default:
rig_debug(RIG_DEBUG_ERR,
"%s: unsupported flow_control specified: %d\n",
__func__,
rp->parm.serial.handshake);
CLOSE(fd);
return -RIG_ECONF;
break;
}
/*
* Choose raw input, no preprocessing please ..
*/
#if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H) #if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H)
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
/* /*
* Choose raw output, no preprocessing please .. * Choose raw output, no preprocessing please ..
*/ */
options.c_oflag &= ~OPOST;
options.c_oflag &= ~OPOST; #else /* sgtty */
sg.sg_flags = RAW;
#else /* sgtty */
sg.sg_flags = RAW;
#endif #endif
/* /*
* VTIME in deciseconds, rp->timeout in miliseconds * VTIME in deciseconds, rp->timeout in miliseconds
*/ */
options.c_cc[VTIME] = (rp->timeout + 99) / 100; options.c_cc[VTIME] = (rp->timeout + 99) / 100;
options.c_cc[VMIN] = 1; options.c_cc[VMIN] = 1;
/* /*
* Flush serial port * Flush serial port
*/ */
tcflush(fd, TCIFLUSH);
tcflush(fd, TCIFLUSH);
/*
* Finally, set the new options for the port...
*/
/*
* Finally, set the new options for the port...
*/
#if defined(HAVE_TERMIOS_H) #if defined(HAVE_TERMIOS_H)
if (tcsetattr(fd, TCSANOW, &options) == -1) {
rig_debug(RIG_DEBUG_ERR, "%s: tcsetattr failed: %s\n", if (tcsetattr(fd, TCSANOW, &options) == -1) {
__func__, strerror(errno)); rig_debug(RIG_DEBUG_ERR,
CLOSE(fd); "%s: tcsetattr failed: %s\n",
return -RIG_ECONF; /* arg, so close! */ __func__,
} strerror(errno));
CLOSE(fd);
return -RIG_ECONF; /* arg, so close! */
}
#elif defined(HAVE_TERMIO_H) #elif defined(HAVE_TERMIO_H)
if (IOCTL(fd, TCSETA, &options) == -1) {
rig_debug(RIG_DEBUG_ERR, "%s: ioctl(TCSETA) failed: %s\n", if (IOCTL(fd, TCSETA, &options) == -1) {
__func__, strerror(errno)); rig_debug(RIG_DEBUG_ERR,
CLOSE(fd); "%s: ioctl(TCSETA) failed: %s\n",
return -RIG_ECONF; /* arg, so close! */ __func__,
} strerror(errno));
#else /* sgtty */ CLOSE(fd);
if (IOCTL(fd, TIOCSETP, &sg) == -1) {
rig_debug(RIG_DEBUG_ERR, "%s: ioctl(TIOCSETP) failed: %s\n", return -RIG_ECONF; /* arg, so close! */
__func__, strerror(errno)); }
CLOSE(fd);
return -RIG_ECONF; /* arg, so close! */ #else
} /* sgtty */
if (IOCTL(fd, TIOCSETP, &sg) == -1) {
rig_debug(RIG_DEBUG_ERR,
"%s: ioctl(TIOCSETP) failed: %s\n",
__func__,
strerror(errno));
CLOSE(fd);
return -RIG_ECONF; /* arg, so close! */
}
#endif #endif
return RIG_OK; return RIG_OK;
} }
@ -394,13 +445,16 @@ int HAMLIB_API serial_setup(hamlib_port_t *rp)
* \param p * \param p
* \return RIG_OK * \return RIG_OK
*/ */
int HAMLIB_API serial_flush(hamlib_port_t *p ) int HAMLIB_API serial_flush(hamlib_port_t *p)
{ {
tcflush(p->fd, TCIFLUSH); rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return RIG_OK; tcflush(p->fd, TCIFLUSH);
return RIG_OK;
} }
/** /**
* \brief Open serial port * \brief Open serial port
* \param p * \param p
@ -408,9 +462,12 @@ int HAMLIB_API serial_flush(hamlib_port_t *p )
*/ */
int ser_open(hamlib_port_t *p) int ser_open(hamlib_port_t *p)
{ {
return (p->fd = OPEN(p->pathname, O_RDWR | O_NOCTTY | O_NDELAY)); rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return (p->fd = OPEN(p->pathname, O_RDWR | O_NOCTTY | O_NDELAY));
} }
/** /**
* \brief Close serial port * \brief Close serial port
* \param p fd * \param p fd
@ -418,11 +475,14 @@ int ser_open(hamlib_port_t *p)
*/ */
int ser_close(hamlib_port_t *p) int ser_close(hamlib_port_t *p)
{ {
int rc = CLOSE(p->fd); rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
p->fd = -1;
return rc; int rc = CLOSE(p->fd);
p->fd = -1;
return rc;
} }
/** /**
* \brief Set Request to Send (RTS) bit * \brief Set Request to Send (RTS) bit
* \param p * \param p
@ -431,32 +491,42 @@ int ser_close(hamlib_port_t *p)
*/ */
int HAMLIB_API ser_set_rts(hamlib_port_t *p, int state) int HAMLIB_API ser_set_rts(hamlib_port_t *p, int state)
{ {
unsigned int y = TIOCM_RTS; unsigned int y = TIOCM_RTS;
int rc; int rc;
rig_debug(RIG_DEBUG_VERBOSE, "%s: RTS=%d\n", __func__, state); rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
rig_debug(RIG_DEBUG_VERBOSE, "%s: RTS=%d\n", __func__, state);
#if defined(TIOCMBIS) && defined(TIOCMBIC) #if defined(TIOCMBIS) && defined(TIOCMBIC)
rc = IOCTL(p->fd, state ? TIOCMBIS : TIOCMBIC, &y); rc = IOCTL(p->fd, state ? TIOCMBIS : TIOCMBIC, &y);
#else #else
rc = IOCTL(p->fd, TIOCMGET, &y); rc = IOCTL(p->fd, TIOCMGET, &y);
if (rc >= 0)
{ if (rc >= 0) {
if (state) if (state) {
y |= TIOCM_RTS; y |= TIOCM_RTS;
else } else {
y &= ~TIOCM_RTS; y &= ~TIOCM_RTS;
rc = IOCTL(p->fd, TIOCMSET, &y); }
rc = IOCTL(p->fd, TIOCMSET, &y);
} }
#endif #endif
if (rc < 0)
{ if (rc < 0) {
rig_debug(RIG_DEBUG_ERR, "%s: Cannot change RTS - %s\n", __func__, strerror(errno)); rig_debug(RIG_DEBUG_ERR,
return -RIG_EIO; "%s: Cannot change RTS - %s\n",
__func__,
strerror(errno));
return -RIG_EIO;
} }
return RIG_OK;
return RIG_OK;
} }
/** /**
* \brief Get RTS bit * \brief Get RTS bit
* \param p supposed to be &rig->state.rigport * \param p supposed to be &rig->state.rigport
@ -464,15 +534,18 @@ int HAMLIB_API ser_set_rts(hamlib_port_t *p, int state)
*/ */
int HAMLIB_API ser_get_rts(hamlib_port_t *p, int *state) int HAMLIB_API ser_get_rts(hamlib_port_t *p, int *state)
{ {
int retcode; int retcode;
unsigned int y; unsigned int y;
retcode = IOCTL(p->fd, TIOCMGET, &y); rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
*state = (y & TIOCM_RTS) == TIOCM_RTS;
return retcode < 0 ? -RIG_EIO : RIG_OK; retcode = IOCTL(p->fd, TIOCMGET, &y);
*state = (y & TIOCM_RTS) == TIOCM_RTS;
return retcode < 0 ? -RIG_EIO : RIG_OK;
} }
/** /**
* \brief Set Data Terminal Ready (DTR) bit * \brief Set Data Terminal Ready (DTR) bit
* \param p * \param p
@ -481,32 +554,42 @@ int HAMLIB_API ser_get_rts(hamlib_port_t *p, int *state)
*/ */
int HAMLIB_API ser_set_dtr(hamlib_port_t *p, int state) int HAMLIB_API ser_set_dtr(hamlib_port_t *p, int state)
{ {
unsigned int y = TIOCM_DTR; unsigned int y = TIOCM_DTR;
int rc; int rc;
rig_debug(RIG_DEBUG_VERBOSE, "%s: DTR=%d\n", __func__, state); rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
rig_debug(RIG_DEBUG_VERBOSE, "%s: DTR=%d\n", __func__, state);
#if defined(TIOCMBIS) && defined(TIOCMBIC) #if defined(TIOCMBIS) && defined(TIOCMBIC)
rc = IOCTL(p->fd, state ? TIOCMBIS : TIOCMBIC, &y); rc = IOCTL(p->fd, state ? TIOCMBIS : TIOCMBIC, &y);
#else #else
rc = IOCTL(p->fd, TIOCMGET, &y); rc = IOCTL(p->fd, TIOCMGET, &y);
if (rc >= 0)
{ if (rc >= 0) {
if (state) if (state) {
y |= TIOCM_DTR; y |= TIOCM_DTR;
else } else {
y &= ~TIOCM_DTR; y &= ~TIOCM_DTR;
rc = IOCTL(p->fd, TIOCMSET, &y); }
rc = IOCTL(p->fd, TIOCMSET, &y);
} }
#endif #endif
if (rc < 0)
{ if (rc < 0) {
rig_debug(RIG_DEBUG_ERR, "%s: Cannot change DTR - %s\n", __func__, strerror(errno)); rig_debug(RIG_DEBUG_ERR,
return -RIG_EIO; "%s: Cannot change DTR - %s\n",
__func__,
strerror(errno));
return -RIG_EIO;
} }
return RIG_OK;
return RIG_OK;
} }
/** /**
* \brief Get DTR bit * \brief Get DTR bit
* \param p supposed to be &rig->state.rigport * \param p supposed to be &rig->state.rigport
@ -514,15 +597,18 @@ int HAMLIB_API ser_set_dtr(hamlib_port_t *p, int state)
*/ */
int HAMLIB_API ser_get_dtr(hamlib_port_t *p, int *state) int HAMLIB_API ser_get_dtr(hamlib_port_t *p, int *state)
{ {
int retcode; int retcode;
unsigned int y; unsigned int y;
retcode = IOCTL(p->fd, TIOCMGET, &y); rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
*state = (y & TIOCM_DTR) == TIOCM_DTR;
return retcode < 0 ? -RIG_EIO : RIG_OK; retcode = IOCTL(p->fd, TIOCMGET, &y);
*state = (y & TIOCM_DTR) == TIOCM_DTR;
return retcode < 0 ? -RIG_EIO : RIG_OK;
} }
/** /**
* \brief Set Break * \brief Set Break
* \param p * \param p
@ -531,14 +617,17 @@ int HAMLIB_API ser_get_dtr(hamlib_port_t *p, int *state)
*/ */
int HAMLIB_API ser_set_brk(hamlib_port_t *p, int state) int HAMLIB_API ser_set_brk(hamlib_port_t *p, int state)
{ {
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
#if defined(TIOCSBRK) && defined(TIOCCBRK) #if defined(TIOCSBRK) && defined(TIOCCBRK)
return IOCTL(p->fd, state ? TIOCSBRK : TIOCCBRK, 0 ) < 0 ? return IOCTL(p->fd, state ? TIOCSBRK : TIOCCBRK, 0) < 0 ?
-RIG_EIO : RIG_OK; -RIG_EIO : RIG_OK;
#else #else
return -RIG_ENIMPL; return -RIG_ENIMPL;
#endif #endif
} }
/** /**
* \brief Get Carrier (CI?) bit * \brief Get Carrier (CI?) bit
* \param p supposed to be &rig->state.rigport * \param p supposed to be &rig->state.rigport
@ -546,15 +635,18 @@ int HAMLIB_API ser_set_brk(hamlib_port_t *p, int state)
*/ */
int HAMLIB_API ser_get_car(hamlib_port_t *p, int *state) int HAMLIB_API ser_get_car(hamlib_port_t *p, int *state)
{ {
int retcode; int retcode;
unsigned int y; unsigned int y;
retcode = IOCTL(p->fd, TIOCMGET, &y); rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
*state = (y & TIOCM_CAR) == TIOCM_CAR;
return retcode < 0 ? -RIG_EIO : RIG_OK; retcode = IOCTL(p->fd, TIOCMGET, &y);
*state = (y & TIOCM_CAR) == TIOCM_CAR;
return retcode < 0 ? -RIG_EIO : RIG_OK;
} }
/** /**
* \brief Get Clear to Send (CTS) bit * \brief Get Clear to Send (CTS) bit
* \param p supposed to be &rig->state.rigport * \param p supposed to be &rig->state.rigport
@ -562,15 +654,18 @@ int HAMLIB_API ser_get_car(hamlib_port_t *p, int *state)
*/ */
int HAMLIB_API ser_get_cts(hamlib_port_t *p, int *state) int HAMLIB_API ser_get_cts(hamlib_port_t *p, int *state)
{ {
int retcode; int retcode;
unsigned int y; unsigned int y;
retcode = IOCTL(p->fd, TIOCMGET, &y); rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
*state = (y & TIOCM_CTS) == TIOCM_CTS;
return retcode < 0 ? -RIG_EIO : RIG_OK; retcode = IOCTL(p->fd, TIOCMGET, &y);
*state = (y & TIOCM_CTS) == TIOCM_CTS;
return retcode < 0 ? -RIG_EIO : RIG_OK;
} }
/** /**
* \brief Get Data Set Ready (DSR) bit * \brief Get Data Set Ready (DSR) bit
* \param p supposed to be &rig->state.rigport * \param p supposed to be &rig->state.rigport
@ -578,13 +673,15 @@ int HAMLIB_API ser_get_cts(hamlib_port_t *p, int *state)
*/ */
int HAMLIB_API ser_get_dsr(hamlib_port_t *p, int *state) int HAMLIB_API ser_get_dsr(hamlib_port_t *p, int *state)
{ {
int retcode; int retcode;
unsigned int y; unsigned int y;
retcode = IOCTL(p->fd, TIOCMGET, &y); rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
*state = (y & TIOCM_DSR) == TIOCM_DSR;
return retcode < 0 ? -RIG_EIO : RIG_OK; retcode = IOCTL(p->fd, TIOCMGET, &y);
*state = (y & TIOCM_DSR) == TIOCM_DSR;
return retcode < 0 ? -RIG_EIO : RIG_OK;
} }
/** @} */ /** @} */

Wyświetl plik

@ -45,7 +45,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include "hamlib/rig.h" #include <hamlib/rig.h>
#include "cal.h" #include "cal.h"
@ -58,10 +58,10 @@
/** /**
* \brief set a radio level setting * \brief set a radio level setting
* \param rig The rig handle * \param rig The rig handle
* \param vfo The target VFO * \param vfo The target VFO
* \param level The level setting * \param level The level setting
* \param val The value to set the level setting to * \param val The value to set the level setting to
* *
* Sets the level of a setting. * Sets the level of a setting.
* The level value \a val can be a float or an integer. See #value_t * The level value \a val can be a float or an integer. See #value_t
@ -75,51 +75,62 @@
*/ */
int HAMLIB_API rig_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) int HAMLIB_API rig_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
{ {
const struct rig_caps *caps; const struct rig_caps *caps;
int retcode; int retcode;
vfo_t curr_vfo; vfo_t curr_vfo;
if (CHECK_RIG_ARG(rig)) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rig->caps; if (CHECK_RIG_ARG(rig)) {
return -RIG_EINVAL;
}
if (caps->set_level == NULL || !rig_has_set_level(rig,level)) caps = rig->caps;
return -RIG_ENAVAIL;
if ((caps->targetable_vfo&RIG_TARGETABLE_PURE) || if (caps->set_level == NULL || !rig_has_set_level(rig, level)) {
vfo == RIG_VFO_CURR || vfo == rig->state.current_vfo) return -RIG_ENAVAIL;
return caps->set_level(rig, vfo, level, val); }
if (!caps->set_vfo) if ((caps->targetable_vfo & RIG_TARGETABLE_PURE)
return -RIG_ENTARGET; || vfo == RIG_VFO_CURR
curr_vfo = rig->state.current_vfo; || vfo == rig->state.current_vfo) {
retcode = caps->set_vfo(rig, vfo); return caps->set_level(rig, vfo, level, val);
if (retcode != RIG_OK) }
return retcode;
retcode = caps->set_level(rig, vfo, level, val); if (!caps->set_vfo) {
caps->set_vfo(rig, curr_vfo); return -RIG_ENTARGET;
return retcode; }
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK) {
return retcode;
}
retcode = caps->set_level(rig, vfo, level, val);
caps->set_vfo(rig, curr_vfo);
return retcode;
} }
/** /**
* \brief get the value of a level * \brief get the value of a level
* \param rig The rig handle * \param rig The rig handle
* \param vfo The target VFO * \param vfo The target VFO
* \param level The level setting * \param level The level setting
* \param val The location where to store the value of \a level * \param val The location where to store the value of \a level
* *
* Retrieves the value of a \a level. * Retrieves the value of a \a level.
* The level value \a val can be a float or an integer. See #value_t * The level value \a val can be a float or an integer. See #value_t
* for more information. * for more information.
* *
* RIG_LEVEL_STRENGTH: \a val is an integer, representing the S Meter * RIG_LEVEL_STRENGTH: \a val is an integer, representing the S Meter
* level in dB relative to S9, according to the ideal S Meter scale. * level in dB relative to S9, according to the ideal S Meter scale.
* The ideal S Meter scale is as follow: S0=-54, S1=-48, S2=-42, S3=-36, * The ideal S Meter scale is as follow: S0=-54, S1=-48, S2=-42, S3=-36,
* S4=-30, S5=-24, S6=-18, S7=-12, S8=-6, S9=0, +10=10, +20=20, * S4=-30, S5=-24, S6=-18, S7=-12, S8=-6, S9=0, +10=10, +20=20,
* +30=30, +40=40, +50=50 and +60=60. This is the responsability * +30=30, +40=40, +50=50 and +60=60. This is the responsability
* of the backend to return values calibrated for this scale. * of the backend to return values calibrated for this scale.
* *
* \return RIG_OK if the operation has been sucessful, otherwise * \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is * a negative value if an error occured (in which case, cause is
@ -129,57 +140,72 @@ int HAMLIB_API rig_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
*/ */
int HAMLIB_API rig_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) int HAMLIB_API rig_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
{ {
const struct rig_caps *caps; const struct rig_caps *caps;
int retcode; int retcode;
vfo_t curr_vfo; vfo_t curr_vfo;
if (CHECK_RIG_ARG(rig) || !val) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rig->caps; if (CHECK_RIG_ARG(rig) || !val) {
return -RIG_EINVAL;
}
if (caps->get_level == NULL || !rig_has_get_level(rig,level)) caps = rig->caps;
return -RIG_ENAVAIL;
/* if (caps->get_level == NULL || !rig_has_get_level(rig, level)) {
* Special case(frontend emulation): calibrated S-meter reading return -RIG_ENAVAIL;
*/ }
if (level == RIG_LEVEL_STRENGTH &&
(caps->has_get_level & RIG_LEVEL_STRENGTH) == 0 &&
rig_has_get_level(rig,RIG_LEVEL_RAWSTR) &&
rig->state.str_cal.size) {
value_t rawstr; /*
* Special case(frontend emulation): calibrated S-meter reading
*/
if (level == RIG_LEVEL_STRENGTH
&& (caps->has_get_level & RIG_LEVEL_STRENGTH) == 0
&& rig_has_get_level(rig, RIG_LEVEL_RAWSTR)
&& rig->state.str_cal.size) {
retcode = rig_get_level(rig, vfo, RIG_LEVEL_RAWSTR, &rawstr); value_t rawstr;
if (retcode != RIG_OK)
return retcode; retcode = rig_get_level(rig, vfo, RIG_LEVEL_RAWSTR, &rawstr);
val->i = (int)rig_raw2val(rawstr.i, &rig->state.str_cal);
return RIG_OK; if (retcode != RIG_OK) {
} return retcode;
}
val->i = (int)rig_raw2val(rawstr.i, &rig->state.str_cal);
return RIG_OK;
}
if ((caps->targetable_vfo&RIG_TARGETABLE_PURE) || if ((caps->targetable_vfo & RIG_TARGETABLE_PURE)
vfo == RIG_VFO_CURR || vfo == rig->state.current_vfo) || vfo == RIG_VFO_CURR
return caps->get_level(rig, vfo, level, val); || vfo == rig->state.current_vfo) {
if (!caps->set_vfo) return caps->get_level(rig, vfo, level, val);
return -RIG_ENTARGET; }
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_level(rig, vfo, level, val); if (!caps->set_vfo) {
caps->set_vfo(rig, curr_vfo); return -RIG_ENTARGET;
return retcode; }
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK) {
return retcode;
}
retcode = caps->get_level(rig, vfo, level, val);
caps->set_vfo(rig, curr_vfo);
return retcode;
} }
/** /**
* \brief set a radio parameter * \brief set a radio parameter
* \param rig The rig handle * \param rig The rig handle
* \param parm The parameter * \param parm The parameter
* \param val The value to set the parameter * \param val The value to set the parameter
* *
* Sets a parameter. * Sets a parameter.
* The parameter value \a val can be a float or an integer. See #value_t * The parameter value \a val can be a float or an integer. See #value_t
@ -193,20 +219,25 @@ int HAMLIB_API rig_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
*/ */
int HAMLIB_API rig_set_parm(RIG *rig, setting_t parm, value_t val) int HAMLIB_API rig_set_parm(RIG *rig, setting_t parm, value_t val)
{ {
if (CHECK_RIG_ARG(rig)) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
if (rig->caps->set_parm == NULL || !rig_has_set_parm(rig,parm)) if (CHECK_RIG_ARG(rig)) {
return -RIG_ENAVAIL; return -RIG_EINVAL;
}
return rig->caps->set_parm(rig, parm, val); if (rig->caps->set_parm == NULL || !rig_has_set_parm(rig, parm)) {
return -RIG_ENAVAIL;
}
return rig->caps->set_parm(rig, parm, val);
} }
/** /**
* \brief get the value of a parameter * \brief get the value of a parameter
* \param rig The rig handle * \param rig The rig handle
* \param parm The parameter * \param parm The parameter
* \param val The location where to store the value of \a parm * \param val The location where to store the value of \a parm
* *
* Retrieves the value of a \a parm. * Retrieves the value of a \a parm.
* The parameter value \a val can be a float or an integer. See #value_t * The parameter value \a val can be a float or an integer. See #value_t
@ -220,25 +251,30 @@ int HAMLIB_API rig_set_parm(RIG *rig, setting_t parm, value_t val)
*/ */
int HAMLIB_API rig_get_parm(RIG *rig, setting_t parm, value_t *val) int HAMLIB_API rig_get_parm(RIG *rig, setting_t parm, value_t *val)
{ {
if (CHECK_RIG_ARG(rig) || !val) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
if (rig->caps->get_parm == NULL || !rig_has_get_parm(rig,parm)) if (CHECK_RIG_ARG(rig) || !val) {
return -RIG_ENAVAIL; return -RIG_EINVAL;
}
return rig->caps->get_parm(rig, parm, val); if (rig->caps->get_parm == NULL || !rig_has_get_parm(rig, parm)) {
return -RIG_ENAVAIL;
}
return rig->caps->get_parm(rig, parm, val);
} }
/** /**
* \brief check retrieval ability of level settings * \brief check retrieval ability of level settings
* \param rig The rig handle * \param rig The rig handle
* \param level The level settings * \param level The level settings
* *
* Checks if a rig is capable of *getting* a level setting. * Checks if a rig is capable of *getting* a level setting.
* Since the \a level is an OR'ed bitwise argument, more than * Since the \a level is an OR'ed bitwise argument, more than
* one level can be checked at the same time. * one level can be checked at the same time.
* *
* EXAMPLE: if (rig_has_get_level(my_rig, RIG_LVL_STRENGTH)) disp_Smeter(); * EXAMPLE: if (rig_has_get_level(my_rig, RIG_LVL_STRENGTH)) disp_Smeter();
* *
* \return a bit map of supported level settings that can be retrieved, * \return a bit map of supported level settings that can be retrieved,
* otherwise 0 if none supported. * otherwise 0 if none supported.
@ -247,23 +283,26 @@ int HAMLIB_API rig_get_parm(RIG *rig, setting_t parm, value_t *val)
*/ */
setting_t HAMLIB_API rig_has_get_level(RIG *rig, setting_t level) setting_t HAMLIB_API rig_has_get_level(RIG *rig, setting_t level)
{ {
if (!rig || !rig->caps) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return 0;
return (rig->state.has_get_level & level); if (!rig || !rig->caps) {
return 0;
}
return (rig->state.has_get_level & level);
} }
/** /**
* \brief check settable ability of level settings * \brief check settable ability of level settings
* \param rig The rig handle * \param rig The rig handle
* \param level The level settings * \param level The level settings
* *
* Checks if a rig can *set* a level setting. * Checks if a rig can *set* a level setting.
* Since the \a level is an OR'ed bitwise argument, more than * Since the \a level is an OR'ed bitwise argument, more than
* one level can be check at the same time. * one level can be check at the same time.
* *
* EXAMPLE: if (rig_has_set_level(my_rig, RIG_LVL_RFPOWER)) crank_tx(); * EXAMPLE: if (rig_has_set_level(my_rig, RIG_LVL_RFPOWER)) crank_tx();
* *
* \return a bit map of supported level settings that can be set, * \return a bit map of supported level settings that can be set,
* otherwise 0 if none supported. * otherwise 0 if none supported.
@ -272,22 +311,26 @@ setting_t HAMLIB_API rig_has_get_level(RIG *rig, setting_t level)
*/ */
setting_t HAMLIB_API rig_has_set_level(RIG *rig, setting_t level) setting_t HAMLIB_API rig_has_set_level(RIG *rig, setting_t level)
{ {
if (!rig || !rig->caps) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return 0;
return (rig->state.has_set_level & level); if (!rig || !rig->caps) {
return 0;
}
return (rig->state.has_set_level & level);
} }
/** /**
* \brief check retrieval ability of parameter settings * \brief check retrieval ability of parameter settings
* \param rig The rig handle * \param rig The rig handle
* \param parm The parameter settings * \param parm The parameter settings
* *
* Checks if a rig is capable of *getting* a parm setting. * Checks if a rig is capable of *getting* a parm setting.
* Since the \a parm is an OR'ed bitwise argument, more than * Since the \a parm is an OR'ed bitwise argument, more than
* one parameter can be checked at the same time. * one parameter can be checked at the same time.
* *
* EXAMPLE: if (rig_has_get_parm(my_rig, RIG_PARM_ANN)) good4you(); * EXAMPLE: if (rig_has_get_parm(my_rig, RIG_PARM_ANN)) good4you();
* *
* \return a bit map of supported parameter settings that can be retrieved, * \return a bit map of supported parameter settings that can be retrieved,
* otherwise 0 if none supported. * otherwise 0 if none supported.
@ -296,23 +339,26 @@ setting_t HAMLIB_API rig_has_set_level(RIG *rig, setting_t level)
*/ */
setting_t HAMLIB_API rig_has_get_parm(RIG *rig, setting_t parm) setting_t HAMLIB_API rig_has_get_parm(RIG *rig, setting_t parm)
{ {
if (!rig || !rig->caps) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return 0;
return (rig->state.has_get_parm & parm); if (!rig || !rig->caps) {
return 0;
}
return (rig->state.has_get_parm & parm);
} }
/** /**
* \brief check settable ability of parameter settings * \brief check settable ability of parameter settings
* \param rig The rig handle * \param rig The rig handle
* \param parm The parameter settings * \param parm The parameter settings
* *
* Checks if a rig can *set* a parameter setting. * Checks if a rig can *set* a parameter setting.
* Since the \a parm is an OR'ed bitwise argument, more than * Since the \a parm is an OR'ed bitwise argument, more than
* one parameter can be check at the same time. * one parameter can be check at the same time.
* *
* EXAMPLE: if (rig_has_set_parm(my_rig, RIG_PARM_ANN)) announce_all(); * EXAMPLE: if (rig_has_set_parm(my_rig, RIG_PARM_ANN)) announce_all();
* *
* \return a bit map of supported parameter settings that can be set, * \return a bit map of supported parameter settings that can be set,
* otherwise 0 if none supported. * otherwise 0 if none supported.
@ -321,22 +367,26 @@ setting_t HAMLIB_API rig_has_get_parm(RIG *rig, setting_t parm)
*/ */
setting_t HAMLIB_API rig_has_set_parm(RIG *rig, setting_t parm) setting_t HAMLIB_API rig_has_set_parm(RIG *rig, setting_t parm)
{ {
if (!rig || !rig->caps) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return 0;
return (rig->state.has_set_parm & parm); if (!rig || !rig->caps) {
return 0;
}
return (rig->state.has_set_parm & parm);
} }
/** /**
* \brief check ability of radio functions * \brief check ability of radio functions
* \param rig The rig handle * \param rig The rig handle
* \param func The functions * \param func The functions
* *
* Checks if a rig supports a set of functions. * Checks if a rig supports a set of functions.
* Since the \a func is an OR'ed bitwise argument, more than * Since the \a func is an OR'ed bitwise argument, more than
* one function can be checked at the same time. * one function can be checked at the same time.
* *
* EXAMPLE: if (rig_has_get_func(my_rig,RIG_FUNC_FAGC)) disp_fagc_button(); * EXAMPLE: if (rig_has_get_func(my_rig,RIG_FUNC_FAGC)) disp_fagc_button();
* *
* \return a bit map of supported functions, * \return a bit map of supported functions,
* otherwise 0 if none supported. * otherwise 0 if none supported.
@ -345,22 +395,26 @@ setting_t HAMLIB_API rig_has_set_parm(RIG *rig, setting_t parm)
*/ */
setting_t HAMLIB_API rig_has_get_func(RIG *rig, setting_t func) setting_t HAMLIB_API rig_has_get_func(RIG *rig, setting_t func)
{ {
if (!rig || !rig->caps) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return 0;
return (rig->state.has_get_func & func); if (!rig || !rig->caps) {
return 0;
}
return (rig->state.has_get_func & func);
} }
/** /**
* \brief check ability of radio functions * \brief check ability of radio functions
* \param rig The rig handle * \param rig The rig handle
* \param func The functions * \param func The functions
* *
* Checks if a rig supports a set of functions. * Checks if a rig supports a set of functions.
* Since the \a func is an OR'ed bitwise argument, more than * Since the \a func is an OR'ed bitwise argument, more than
* one function can be checked at the same time. * one function can be checked at the same time.
* *
* EXAMPLE: if (rig_has_set_func(my_rig,RIG_FUNC_FAGC)) disp_fagc_button(); * EXAMPLE: if (rig_has_set_func(my_rig,RIG_FUNC_FAGC)) disp_fagc_button();
* *
* \return a bit map of supported functions, * \return a bit map of supported functions,
* otherwise 0 if none supported. * otherwise 0 if none supported.
@ -369,18 +423,22 @@ setting_t HAMLIB_API rig_has_get_func(RIG *rig, setting_t func)
*/ */
setting_t HAMLIB_API rig_has_set_func(RIG *rig, setting_t func) setting_t HAMLIB_API rig_has_set_func(RIG *rig, setting_t func)
{ {
if (!rig || !rig->caps) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return 0;
return (rig->state.has_set_func & func); if (!rig || !rig->caps) {
return 0;
}
return (rig->state.has_set_func & func);
} }
/** /**
* \brief activate/de-activate functions of radio * \brief activate/de-activate functions of radio
* \param rig The rig handle * \param rig The rig handle
* \param vfo The target VFO * \param vfo The target VFO
* \param func The functions to activate * \param func The functions to activate
* \param status The status (on or off) to set to * \param status The status (on or off) to set to
* *
* Activate/de-activate a function of the radio. * Activate/de-activate a function of the radio.
* *
@ -393,43 +451,54 @@ setting_t HAMLIB_API rig_has_set_func(RIG *rig, setting_t func)
* *
* \sa rig_get_func() * \sa rig_get_func()
*/ */
int HAMLIB_API rig_set_func(RIG *rig, vfo_t vfo, setting_t func, int status) int HAMLIB_API rig_set_func(RIG *rig, vfo_t vfo, setting_t func, int status)
{ {
const struct rig_caps *caps; const struct rig_caps *caps;
int retcode; int retcode;
vfo_t curr_vfo; vfo_t curr_vfo;
if (CHECK_RIG_ARG(rig)) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rig->caps; if (CHECK_RIG_ARG(rig)) {
return -RIG_EINVAL;
}
if (caps->set_func == NULL || !rig_has_set_func(rig,func)) caps = rig->caps;
return -RIG_ENAVAIL;
if ((caps->targetable_vfo&RIG_TARGETABLE_FUNC) || if (caps->set_func == NULL || !rig_has_set_func(rig, func)) {
vfo == RIG_VFO_CURR || vfo == rig->state.current_vfo) return -RIG_ENAVAIL;
return caps->set_func(rig, vfo, func, status); }
if (!caps->set_vfo) if ((caps->targetable_vfo & RIG_TARGETABLE_FUNC)
return -RIG_ENTARGET; || vfo == RIG_VFO_CURR
curr_vfo = rig->state.current_vfo; || vfo == rig->state.current_vfo) {
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_func(rig, vfo, func, status); return caps->set_func(rig, vfo, func, status);
caps->set_vfo(rig, curr_vfo); }
return retcode;
if (!caps->set_vfo) {
return -RIG_ENTARGET;
}
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK) {
return retcode;
}
retcode = caps->set_func(rig, vfo, func, status);
caps->set_vfo(rig, curr_vfo);
return retcode;
} }
/** /**
* \brief get the status of functions of the radio * \brief get the status of functions of the radio
* \param rig The rig handle * \param rig The rig handle
* \param vfo The target VFO * \param vfo The target VFO
* \param func The functions to get the status * \param func The functions to get the status
* \param status The location where to store the function status * \param status The location where to store the function status
* *
* Retrieves the status (on/off) of a function of the radio. * Retrieves the status (on/off) of a function of the radio.
* Upon return, \a status will hold the status of the function, * Upon return, \a status will hold the status of the function,
@ -445,40 +514,53 @@ int HAMLIB_API rig_set_func(RIG *rig, vfo_t vfo, setting_t func, int status)
*/ */
int HAMLIB_API rig_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status) int HAMLIB_API rig_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status)
{ {
const struct rig_caps *caps; const struct rig_caps *caps;
int retcode; int retcode;
vfo_t curr_vfo; vfo_t curr_vfo;
if (CHECK_RIG_ARG(rig) || !func) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rig->caps; if (CHECK_RIG_ARG(rig) || !func) {
return -RIG_EINVAL;
}
if (caps->get_func == NULL || !rig_has_get_func(rig,func)) caps = rig->caps;
return -RIG_ENAVAIL;
if ((caps->targetable_vfo&RIG_TARGETABLE_FUNC) || if (caps->get_func == NULL || !rig_has_get_func(rig, func)) {
vfo == RIG_VFO_CURR || vfo == rig->state.current_vfo) return -RIG_ENAVAIL;
return caps->get_func(rig, vfo, func, status); }
if (!caps->set_vfo) if ((caps->targetable_vfo & RIG_TARGETABLE_FUNC)
return -RIG_ENTARGET; || vfo == RIG_VFO_CURR
curr_vfo = rig->state.current_vfo; || vfo == rig->state.current_vfo) {
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_func(rig, vfo, func, status); return caps->get_func(rig, vfo, func, status);
caps->set_vfo(rig, curr_vfo); }
return retcode;
if (!caps->set_vfo) {
return -RIG_ENTARGET;
}
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK) {
return retcode;
}
retcode = caps->get_func(rig, vfo, func, status);
caps->set_vfo(rig, curr_vfo);
return retcode;
} }
/** /**
* \brief set a radio level extra parameter * \brief set a radio level extra parameter
* \param rig The rig handle * \param rig The rig handle
* \param vfo The target VFO * \param vfo The target VFO
* \param token The parameter * \param token The parameter
* \param val The value to set the parameter to * \param val The value to set the parameter to
* *
* Sets an level extra parameter. * Sets an level extra parameter.
* *
@ -488,42 +570,56 @@ int HAMLIB_API rig_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status)
* *
* \sa rig_get_ext_level() * \sa rig_get_ext_level()
*/ */
int HAMLIB_API rig_set_ext_level(RIG *rig, vfo_t vfo, token_t token, value_t val) int HAMLIB_API rig_set_ext_level(RIG *rig, vfo_t vfo, token_t token,
value_t val)
{ {
const struct rig_caps *caps; const struct rig_caps *caps;
int retcode; int retcode;
vfo_t curr_vfo; vfo_t curr_vfo;
if (CHECK_RIG_ARG(rig)) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rig->caps; if (CHECK_RIG_ARG(rig)) {
return -RIG_EINVAL;
}
if (caps->set_ext_level == NULL) caps = rig->caps;
return -RIG_ENAVAIL;
if ((caps->targetable_vfo&RIG_TARGETABLE_PURE) || if (caps->set_ext_level == NULL) {
vfo == RIG_VFO_CURR || vfo == rig->state.current_vfo) return -RIG_ENAVAIL;
return caps->set_ext_level(rig, vfo, token, val); }
if (!caps->set_vfo) if ((caps->targetable_vfo & RIG_TARGETABLE_PURE)
return -RIG_ENTARGET; || vfo == RIG_VFO_CURR
curr_vfo = rig->state.current_vfo; || vfo == rig->state.current_vfo) {
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_ext_level(rig, vfo, token, val); return caps->set_ext_level(rig, vfo, token, val);
caps->set_vfo(rig, curr_vfo); }
return retcode;
if (!caps->set_vfo) {
return -RIG_ENTARGET;
}
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK) {
return retcode;
}
retcode = caps->set_ext_level(rig, vfo, token, val);
caps->set_vfo(rig, curr_vfo);
return retcode;
} }
/** /**
* \brief get the value of a level extra parameter * \brief get the value of a level extra parameter
* \param rig The rig handle * \param rig The rig handle
* \param vfo The target VFO * \param vfo The target VFO
* \param token The parameter * \param token The parameter
* \param val The location where to store the value of \a token * \param val The location where to store the value of \a token
* *
* Retrieves the value of a level extra parameter associated with \a token. * Retrieves the value of a level extra parameter associated with \a token.
* *
@ -533,41 +629,55 @@ int HAMLIB_API rig_set_ext_level(RIG *rig, vfo_t vfo, token_t token, value_t val
* *
* \sa rig_set_ext_level() * \sa rig_set_ext_level()
*/ */
int HAMLIB_API rig_get_ext_level(RIG *rig, vfo_t vfo, token_t token, value_t *val) int HAMLIB_API rig_get_ext_level(RIG *rig, vfo_t vfo, token_t token,
value_t *val)
{ {
const struct rig_caps *caps; const struct rig_caps *caps;
int retcode; int retcode;
vfo_t curr_vfo; vfo_t curr_vfo;
if (CHECK_RIG_ARG(rig) || !val) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rig->caps; if (CHECK_RIG_ARG(rig) || !val) {
return -RIG_EINVAL;
}
if (caps->get_ext_level == NULL) caps = rig->caps;
return -RIG_ENAVAIL;
if ((caps->targetable_vfo&RIG_TARGETABLE_PURE) || if (caps->get_ext_level == NULL) {
vfo == RIG_VFO_CURR || vfo == rig->state.current_vfo) return -RIG_ENAVAIL;
return caps->get_ext_level(rig, vfo, token, val); }
if (!caps->set_vfo) if ((caps->targetable_vfo & RIG_TARGETABLE_PURE)
return -RIG_ENTARGET; || vfo == RIG_VFO_CURR
curr_vfo = rig->state.current_vfo; || vfo == rig->state.current_vfo) {
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_ext_level(rig, vfo, token, val); return caps->get_ext_level(rig, vfo, token, val);
caps->set_vfo(rig, curr_vfo); }
return retcode;
if (!caps->set_vfo) {
return -RIG_ENTARGET;
}
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK) {
return retcode;
}
retcode = caps->get_ext_level(rig, vfo, token, val);
caps->set_vfo(rig, curr_vfo);
return retcode;
} }
/** /**
* \brief set a radio parm extra parameter * \brief set a radio parm extra parameter
* \param rig The rig handle * \param rig The rig handle
* \param token The parameter * \param token The parameter
* \param val The value to set the parameter to * \param val The value to set the parameter to
* *
* Sets an parm extra parameter. * Sets an parm extra parameter.
* *
@ -579,20 +689,25 @@ int HAMLIB_API rig_get_ext_level(RIG *rig, vfo_t vfo, token_t token, value_t *va
*/ */
int HAMLIB_API rig_set_ext_parm(RIG *rig, token_t token, value_t val) int HAMLIB_API rig_set_ext_parm(RIG *rig, token_t token, value_t val)
{ {
if (CHECK_RIG_ARG(rig)) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
if (rig->caps->set_ext_parm == NULL) if (CHECK_RIG_ARG(rig)) {
return -RIG_ENAVAIL; return -RIG_EINVAL;
}
return rig->caps->set_ext_parm(rig, token, val); if (rig->caps->set_ext_parm == NULL) {
return -RIG_ENAVAIL;
}
return rig->caps->set_ext_parm(rig, token, val);
} }
/** /**
* \brief get the value of a parm extra parameter * \brief get the value of a parm extra parameter
* \param rig The rig handle * \param rig The rig handle
* \param token The parameter * \param token The parameter
* \param val The location where to store the value of \a token * \param val The location where to store the value of \a token
* *
* Retrieves the value of a parm extra parameter associated with \a token. * Retrieves the value of a parm extra parameter associated with \a token.
* *
@ -604,19 +719,23 @@ int HAMLIB_API rig_set_ext_parm(RIG *rig, token_t token, value_t val)
*/ */
int HAMLIB_API rig_get_ext_parm(RIG *rig, token_t token, value_t *val) int HAMLIB_API rig_get_ext_parm(RIG *rig, token_t token, value_t *val)
{ {
if (CHECK_RIG_ARG(rig) || !val) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
if (rig->caps->get_ext_parm == NULL) if (CHECK_RIG_ARG(rig) || !val) {
return -RIG_ENAVAIL; return -RIG_EINVAL;
}
return rig->caps->get_ext_parm(rig, token, val); if (rig->caps->get_ext_parm == NULL) {
return -RIG_ENAVAIL;
}
return rig->caps->get_ext_parm(rig, token, val);
} }
/** /**
* \brief basically convert setting_t expressed 2^n to n * \brief basically convert setting_t expressed 2^n to n
* \param s The setting to convert to * \param s The setting to convert to
* *
* Converts a setting_t value expressed by 2^n to the value of n. * Converts a setting_t value expressed by 2^n to the value of n.
* *
@ -625,14 +744,17 @@ int HAMLIB_API rig_get_ext_parm(RIG *rig, token_t token, value_t *val)
*/ */
int HAMLIB_API rig_setting2idx(setting_t s) int HAMLIB_API rig_setting2idx(setting_t s)
{ {
int i; int i;
for (i = 0; i<RIG_SETTING_MAX; i++) { rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (s & rig_idx2setting(i))
return i;
}
return 0; for (i = 0; i < RIG_SETTING_MAX; i++) {
if (s & rig_idx2setting(i)) {
return i;
}
}
return 0;
} }
/*! @} */ /*! @} */

Wyświetl plik

@ -44,9 +44,9 @@
#define IS_TOKEN_FRONTEND(t) ((t)&(1<<30)) #define IS_TOKEN_FRONTEND(t) ((t)&(1<<30))
/** \brief Null frontend token */ /** \brief Null frontend token */
#define TOK_FRONTEND_NONE TOKEN_FRONTEND(0) #define TOK_FRONTEND_NONE TOKEN_FRONTEND(0)
/** \brief Null backend token */ /** \brief Null backend token */
#define TOK_BACKEND_NONE TOKEN_BACKEND(0) #define TOK_BACKEND_NONE TOKEN_BACKEND(0)
/* /*
* tokens shared among rig and rotator, * tokens shared among rig and rotator,
@ -54,37 +54,37 @@
*/ */
/** \brief Pathname is device for rig control, e.g. /dev/ttyS0 */ /** \brief Pathname is device for rig control, e.g. /dev/ttyS0 */
#define TOK_PATHNAME TOKEN_FRONTEND(10) #define TOK_PATHNAME TOKEN_FRONTEND(10)
/** \brief Delay before serial output (units?) */ /** \brief Delay before serial output (units?) */
#define TOK_WRITE_DELAY TOKEN_FRONTEND(12) #define TOK_WRITE_DELAY TOKEN_FRONTEND(12)
/** \brief Delay after serial output (units?) */ /** \brief Delay after serial output (units?) */
#define TOK_POST_WRITE_DELAY TOKEN_FRONTEND(13) #define TOK_POST_WRITE_DELAY TOKEN_FRONTEND(13)
/** \brief Timeout delay (units?) */ /** \brief Timeout delay (units?) */
#define TOK_TIMEOUT TOKEN_FRONTEND(14) #define TOK_TIMEOUT TOKEN_FRONTEND(14)
/** \brief Number of retries permitted */ /** \brief Number of retries permitted */
#define TOK_RETRY TOKEN_FRONTEND(15) #define TOK_RETRY TOKEN_FRONTEND(15)
/** \brief Serial speed - "baud rate" */ /** \brief Serial speed - "baud rate" */
#define TOK_SERIAL_SPEED TOKEN_FRONTEND(20) #define TOK_SERIAL_SPEED TOKEN_FRONTEND(20)
/** \brief No. data bits per serial character */ /** \brief No. data bits per serial character */
#define TOK_DATA_BITS TOKEN_FRONTEND(21) #define TOK_DATA_BITS TOKEN_FRONTEND(21)
/** \brief No. stop bits per serial character */ /** \brief No. stop bits per serial character */
#define TOK_STOP_BITS TOKEN_FRONTEND(22) #define TOK_STOP_BITS TOKEN_FRONTEND(22)
/** \brief Serial parity (format?) */ /** \brief Serial parity (format?) */
#define TOK_PARITY TOKEN_FRONTEND(23) #define TOK_PARITY TOKEN_FRONTEND(23)
/** \brief Serial Handshake (format?) */ /** \brief Serial Handshake (format?) */
#define TOK_HANDSHAKE TOKEN_FRONTEND(24) #define TOK_HANDSHAKE TOKEN_FRONTEND(24)
/** \brief Serial Req. To Send status */ /** \brief Serial Req. To Send status */
#define TOK_RTS_STATE TOKEN_FRONTEND(25) #define TOK_RTS_STATE TOKEN_FRONTEND(25)
/** \brief Serial Data Terminal Ready status */ /** \brief Serial Data Terminal Ready status */
#define TOK_DTR_STATE TOKEN_FRONTEND(26) #define TOK_DTR_STATE TOKEN_FRONTEND(26)
/** \brief PTT type override */ /** \brief PTT type override */
#define TOK_PTT_TYPE TOKEN_FRONTEND(30) #define TOK_PTT_TYPE TOKEN_FRONTEND(30)
/** \brief PTT pathname override */ /** \brief PTT pathname override */
#define TOK_PTT_PATHNAME TOKEN_FRONTEND(31) #define TOK_PTT_PATHNAME TOKEN_FRONTEND(31)
/** \brief DCD type override */ /** \brief DCD type override */
#define TOK_DCD_TYPE TOKEN_FRONTEND(32) #define TOK_DCD_TYPE TOKEN_FRONTEND(32)
/** \brief DCD pathname override */ /** \brief DCD pathname override */
#define TOK_DCD_PATHNAME TOKEN_FRONTEND(33) #define TOK_DCD_PATHNAME TOKEN_FRONTEND(33)
/** \brief CM108 GPIO bit number for PTT */ /** \brief CM108 GPIO bit number for PTT */
#define TOK_PTT_BITNUM TOKEN_FRONTEND(34) #define TOK_PTT_BITNUM TOKEN_FRONTEND(34)
/* /*
@ -93,23 +93,23 @@
/* rx_range_list/tx_range_list, filters, announces, has(func,lvl,..) */ /* rx_range_list/tx_range_list, filters, announces, has(func,lvl,..) */
/** \brief rig: ?? */ /** \brief rig: ?? */
#define TOK_VFO_COMP TOKEN_FRONTEND(110) #define TOK_VFO_COMP TOKEN_FRONTEND(110)
/** \brief rig: polling interval (units?) */ /** \brief rig: polling interval (units?) */
#define TOK_POLL_INTERVAL TOKEN_FRONTEND(111) #define TOK_POLL_INTERVAL TOKEN_FRONTEND(111)
/** \brief rig: International Telecommunications Union region no. */ /** \brief rig: International Telecommunications Union region no. */
#define TOK_ITU_REGION TOKEN_FRONTEND(120) #define TOK_ITU_REGION TOKEN_FRONTEND(120)
/* /*
* rotator specific tokens * rotator specific tokens
* (strictly, should be documented as rotator_internal) * (strictly, should be documented as rotator_internal)
*/ */
/** \brief rot: Minimum Azimuth */ /** \brief rot: Minimum Azimuth */
#define TOK_MIN_AZ TOKEN_FRONTEND(110) #define TOK_MIN_AZ TOKEN_FRONTEND(110)
/** \brief rot: Maximum Azimuth */ /** \brief rot: Maximum Azimuth */
#define TOK_MAX_AZ TOKEN_FRONTEND(111) #define TOK_MAX_AZ TOKEN_FRONTEND(111)
/** \brief rot: Minimum Elevation */ /** \brief rot: Minimum Elevation */
#define TOK_MIN_EL TOKEN_FRONTEND(112) #define TOK_MIN_EL TOKEN_FRONTEND(112)
/** \brief rot: Maximum Elevation */ /** \brief rot: Maximum Elevation */
#define TOK_MAX_EL TOKEN_FRONTEND(113) #define TOK_MAX_EL TOKEN_FRONTEND(113)
#endif /* _TOKEN_H */ #endif /* _TOKEN_H */

Wyświetl plik

@ -36,7 +36,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "hamlib/rig.h" #include <hamlib/rig.h>
#include "tones.h" #include "tones.h"
#if !defined(_WIN32) && !defined(__CYGWIN__) #if !defined(_WIN32) && !defined(__CYGWIN__)
@ -77,9 +77,9 @@ const tone_t full_dcs_list[] = { FULL_DCS_LIST };
/** /**
* \brief set CTCSS sub-tone frequency * \brief set CTCSS sub-tone frequency
* \param rig The rig handle * \param rig The rig handle
* \param vfo The target VFO * \param vfo The target VFO
* \param tone The tone to set to * \param tone The tone to set to
* *
* Sets the current Continuous Tone Controlled Squelch System (CTCSS) * Sets the current Continuous Tone Controlled Squelch System (CTCSS)
* sub-audible tone frequency. * sub-audible tone frequency.
@ -97,42 +97,54 @@ const tone_t full_dcs_list[] = { FULL_DCS_LIST };
* *
* \sa rig_get_ctcss_tone(), rig_set_ctcss_sql() * \sa rig_get_ctcss_tone(), rig_set_ctcss_sql()
*/ */
int HAMLIB_API rig_set_ctcss_tone(RIG *rig, vfo_t vfo, tone_t tone) int HAMLIB_API rig_set_ctcss_tone(RIG *rig, vfo_t vfo, tone_t tone)
{ {
const struct rig_caps *caps; const struct rig_caps *caps;
int retcode; int retcode;
vfo_t curr_vfo; vfo_t curr_vfo;
if (CHECK_RIG_ARG(rig)) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rig->caps; if (CHECK_RIG_ARG(rig)) {
return -RIG_EINVAL;
}
if (caps->set_ctcss_tone == NULL) caps = rig->caps;
return -RIG_ENAVAIL;
if ((caps->targetable_vfo&RIG_TARGETABLE_TONE) || if (caps->set_ctcss_tone == NULL) {
vfo == RIG_VFO_CURR || vfo == rig->state.current_vfo) return -RIG_ENAVAIL;
return caps->set_ctcss_tone(rig, vfo, tone); }
if (!caps->set_vfo) if ((caps->targetable_vfo & RIG_TARGETABLE_TONE)
return -RIG_ENTARGET; || vfo == RIG_VFO_CURR
curr_vfo = rig->state.current_vfo; || vfo == rig->state.current_vfo) {
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_ctcss_tone(rig, vfo, tone); return caps->set_ctcss_tone(rig, vfo, tone);
caps->set_vfo(rig, curr_vfo); }
return retcode;
if (!caps->set_vfo) {
return -RIG_ENTARGET;
}
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK) {
return retcode;
}
retcode = caps->set_ctcss_tone(rig, vfo, tone);
caps->set_vfo(rig, curr_vfo);
return retcode;
} }
/** /**
* \brief get the current CTCSS sub-tone frequency * \brief get the current CTCSS sub-tone frequency
* \param rig The rig handle * \param rig The rig handle
* \param vfo The target VFO * \param vfo The target VFO
* \param tone The location where to store the current tone * \param tone The location where to store the current tone
* *
* Retrieves the current Continuous Tone Controlled Squelch System (CTCSS) * Retrieves the current Continuous Tone Controlled Squelch System (CTCSS)
* sub-audible tone frequency. * sub-audible tone frequency.
@ -149,39 +161,52 @@ int HAMLIB_API rig_set_ctcss_tone(RIG *rig, vfo_t vfo, tone_t tone)
*/ */
int HAMLIB_API rig_get_ctcss_tone(RIG *rig, vfo_t vfo, tone_t *tone) int HAMLIB_API rig_get_ctcss_tone(RIG *rig, vfo_t vfo, tone_t *tone)
{ {
const struct rig_caps *caps; const struct rig_caps *caps;
int retcode; int retcode;
vfo_t curr_vfo; vfo_t curr_vfo;
if (CHECK_RIG_ARG(rig) || !tone) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rig->caps; if (CHECK_RIG_ARG(rig) || !tone) {
return -RIG_EINVAL;
}
if (caps->get_ctcss_tone == NULL) caps = rig->caps;
return -RIG_ENAVAIL;
if ((caps->targetable_vfo&RIG_TARGETABLE_TONE) || if (caps->get_ctcss_tone == NULL) {
vfo == RIG_VFO_CURR || vfo == rig->state.current_vfo) return -RIG_ENAVAIL;
return caps->get_ctcss_tone(rig, vfo, tone); }
if (!caps->set_vfo) if ((caps->targetable_vfo & RIG_TARGETABLE_TONE)
return -RIG_ENTARGET; || vfo == RIG_VFO_CURR
curr_vfo = rig->state.current_vfo; || vfo == rig->state.current_vfo) {
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_ctcss_tone(rig, vfo, tone); return caps->get_ctcss_tone(rig, vfo, tone);
caps->set_vfo(rig, curr_vfo); }
return retcode;
if (!caps->set_vfo) {
return -RIG_ENTARGET;
}
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK) {
return retcode;
}
retcode = caps->get_ctcss_tone(rig, vfo, tone);
caps->set_vfo(rig, curr_vfo);
return retcode;
} }
/** /**
* \brief set the current encoding DCS code * \brief set the current encoding DCS code
* \param rig The rig handle * \param rig The rig handle
* \param vfo The target VFO * \param vfo The target VFO
* \param code The tone to set to * \param code The tone to set to
* *
* Sets the current encoding Digitally-Coded Squelch code. * Sets the current encoding Digitally-Coded Squelch code.
* *
@ -194,39 +219,52 @@ int HAMLIB_API rig_get_ctcss_tone(RIG *rig, vfo_t vfo, tone_t *tone)
int HAMLIB_API rig_set_dcs_code(RIG *rig, vfo_t vfo, tone_t code) int HAMLIB_API rig_set_dcs_code(RIG *rig, vfo_t vfo, tone_t code)
{ {
const struct rig_caps *caps; const struct rig_caps *caps;
int retcode; int retcode;
vfo_t curr_vfo; vfo_t curr_vfo;
if (CHECK_RIG_ARG(rig)) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rig->caps; if (CHECK_RIG_ARG(rig)) {
return -RIG_EINVAL;
}
if (caps->set_dcs_code == NULL) caps = rig->caps;
return -RIG_ENAVAIL;
if ((caps->targetable_vfo&RIG_TARGETABLE_TONE) || if (caps->set_dcs_code == NULL) {
vfo == RIG_VFO_CURR || vfo == rig->state.current_vfo) return -RIG_ENAVAIL;
return caps->set_dcs_code(rig, vfo, code); }
if (!caps->set_vfo) if ((caps->targetable_vfo & RIG_TARGETABLE_TONE)
return -RIG_ENTARGET; || vfo == RIG_VFO_CURR
curr_vfo = rig->state.current_vfo; || vfo == rig->state.current_vfo) {
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_dcs_code(rig, vfo, code); return caps->set_dcs_code(rig, vfo, code);
caps->set_vfo(rig, curr_vfo); }
return retcode;
if (!caps->set_vfo) {
return -RIG_ENTARGET;
}
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK) {
return retcode;
}
retcode = caps->set_dcs_code(rig, vfo, code);
caps->set_vfo(rig, curr_vfo);
return retcode;
} }
/** /**
* \brief get the current encoding DCS code * \brief get the current encoding DCS code
* \param rig The rig handle * \param rig The rig handle
* \param vfo The target VFO * \param vfo The target VFO
* \param code The location where to store the current tone * \param code The location where to store the current tone
* *
* Retrieves the current encoding Digitally-Coded Squelch code. * Retrieves the current encoding Digitally-Coded Squelch code.
* *
@ -238,39 +276,52 @@ int HAMLIB_API rig_set_dcs_code(RIG *rig, vfo_t vfo, tone_t code)
*/ */
int HAMLIB_API rig_get_dcs_code(RIG *rig, vfo_t vfo, tone_t *code) int HAMLIB_API rig_get_dcs_code(RIG *rig, vfo_t vfo, tone_t *code)
{ {
const struct rig_caps *caps; const struct rig_caps *caps;
int retcode; int retcode;
vfo_t curr_vfo; vfo_t curr_vfo;
if (CHECK_RIG_ARG(rig) || !code) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rig->caps; if (CHECK_RIG_ARG(rig) || !code) {
return -RIG_EINVAL;
}
if (caps->get_dcs_code == NULL) caps = rig->caps;
return -RIG_ENAVAIL;
if ((caps->targetable_vfo&RIG_TARGETABLE_TONE) || if (caps->get_dcs_code == NULL) {
vfo == RIG_VFO_CURR || vfo == rig->state.current_vfo) return -RIG_ENAVAIL;
return caps->get_dcs_code(rig, vfo, code); }
if (!caps->set_vfo) if ((caps->targetable_vfo & RIG_TARGETABLE_TONE)
return -RIG_ENTARGET; || vfo == RIG_VFO_CURR
curr_vfo = rig->state.current_vfo; || vfo == rig->state.current_vfo) {
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_dcs_code(rig, vfo, code); return caps->get_dcs_code(rig, vfo, code);
caps->set_vfo(rig, curr_vfo); }
return retcode;
if (!caps->set_vfo) {
return -RIG_ENTARGET;
}
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK) {
return retcode;
}
retcode = caps->get_dcs_code(rig, vfo, code);
caps->set_vfo(rig, curr_vfo);
return retcode;
} }
/** /**
* \brief set CTCSS squelch * \brief set CTCSS squelch
* \param rig The rig handle * \param rig The rig handle
* \param vfo The target VFO * \param vfo The target VFO
* \param tone The PL tone to set the squelch to * \param tone The PL tone to set the squelch to
* *
* Sets the current Continuous Tone Controlled Squelch System (CTCSS) * Sets the current Continuous Tone Controlled Squelch System (CTCSS)
* sub-audible *squelch* tone. * sub-audible *squelch* tone.
@ -288,42 +339,54 @@ int HAMLIB_API rig_get_dcs_code(RIG *rig, vfo_t vfo, tone_t *code)
* *
* \sa rig_get_ctcss_sql(), rig_set_ctcss_tone() * \sa rig_get_ctcss_sql(), rig_set_ctcss_tone()
*/ */
int HAMLIB_API rig_set_ctcss_sql(RIG *rig, vfo_t vfo, tone_t tone) int HAMLIB_API rig_set_ctcss_sql(RIG *rig, vfo_t vfo, tone_t tone)
{ {
const struct rig_caps *caps; const struct rig_caps *caps;
int retcode; int retcode;
vfo_t curr_vfo; vfo_t curr_vfo;
if (CHECK_RIG_ARG(rig)) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rig->caps; if (CHECK_RIG_ARG(rig)) {
return -RIG_EINVAL;
}
if (caps->set_ctcss_sql == NULL) caps = rig->caps;
return -RIG_ENAVAIL;
if ((caps->targetable_vfo&RIG_TARGETABLE_TONE) || if (caps->set_ctcss_sql == NULL) {
vfo == RIG_VFO_CURR || vfo == rig->state.current_vfo) return -RIG_ENAVAIL;
return caps->set_ctcss_sql(rig, vfo, tone); }
if (!caps->set_vfo) if ((caps->targetable_vfo & RIG_TARGETABLE_TONE)
return -RIG_ENTARGET; || vfo == RIG_VFO_CURR
curr_vfo = rig->state.current_vfo; || vfo == rig->state.current_vfo) {
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_ctcss_sql(rig, vfo, tone); return caps->set_ctcss_sql(rig, vfo, tone);
caps->set_vfo(rig, curr_vfo); }
return retcode;
if (!caps->set_vfo) {
return -RIG_ENTARGET;
}
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK) {
return retcode;
}
retcode = caps->set_ctcss_sql(rig, vfo, tone);
caps->set_vfo(rig, curr_vfo);
return retcode;
} }
/** /**
* \brief get the current CTCSS squelch * \brief get the current CTCSS squelch
* \param rig The rig handle * \param rig The rig handle
* \param vfo The target VFO * \param vfo The target VFO
* \param tone The location where to store the current tone * \param tone The location where to store the current tone
* *
* Retrieves the current Continuous Tone Controlled Squelch System (CTCSS) * Retrieves the current Continuous Tone Controlled Squelch System (CTCSS)
* sub-audible *squelch* tone. * sub-audible *squelch* tone.
@ -340,39 +403,52 @@ int HAMLIB_API rig_set_ctcss_sql(RIG *rig, vfo_t vfo, tone_t tone)
*/ */
int HAMLIB_API rig_get_ctcss_sql(RIG *rig, vfo_t vfo, tone_t *tone) int HAMLIB_API rig_get_ctcss_sql(RIG *rig, vfo_t vfo, tone_t *tone)
{ {
const struct rig_caps *caps; const struct rig_caps *caps;
int retcode; int retcode;
vfo_t curr_vfo; vfo_t curr_vfo;
if (CHECK_RIG_ARG(rig) || !tone) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rig->caps; if (CHECK_RIG_ARG(rig) || !tone) {
return -RIG_EINVAL;
}
if (caps->get_ctcss_sql == NULL) caps = rig->caps;
return -RIG_ENAVAIL;
if ((caps->targetable_vfo&RIG_TARGETABLE_TONE) || if (caps->get_ctcss_sql == NULL) {
vfo == RIG_VFO_CURR || vfo == rig->state.current_vfo) return -RIG_ENAVAIL;
return caps->get_ctcss_sql(rig, vfo, tone); }
if (!caps->set_vfo) if ((caps->targetable_vfo & RIG_TARGETABLE_TONE)
return -RIG_ENTARGET; || vfo == RIG_VFO_CURR
curr_vfo = rig->state.current_vfo; || vfo == rig->state.current_vfo) {
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_ctcss_sql(rig, vfo, tone); return caps->get_ctcss_sql(rig, vfo, tone);
caps->set_vfo(rig, curr_vfo); }
return retcode;
if (!caps->set_vfo) {
return -RIG_ENTARGET;
}
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK) {
return retcode;
}
retcode = caps->get_ctcss_sql(rig, vfo, tone);
caps->set_vfo(rig, curr_vfo);
return retcode;
} }
/** /**
* \brief set the current DCS code * \brief set the current DCS code
* \param rig The rig handle * \param rig The rig handle
* \param vfo The target VFO * \param vfo The target VFO
* \param code The tone to set to * \param code The tone to set to
* *
* Sets the current Digitally-Coded *Squelch* code. * Sets the current Digitally-Coded *Squelch* code.
* *
@ -382,42 +458,54 @@ int HAMLIB_API rig_get_ctcss_sql(RIG *rig, vfo_t vfo, tone_t *tone)
* *
* \sa rig_get_dcs_sql(), rig_set_dcs_code() * \sa rig_get_dcs_sql(), rig_set_dcs_code()
*/ */
int HAMLIB_API rig_set_dcs_sql(RIG *rig, vfo_t vfo, tone_t code) int HAMLIB_API rig_set_dcs_sql(RIG *rig, vfo_t vfo, tone_t code)
{ {
const struct rig_caps *caps; const struct rig_caps *caps;
int retcode; int retcode;
vfo_t curr_vfo; vfo_t curr_vfo;
if (CHECK_RIG_ARG(rig)) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rig->caps; if (CHECK_RIG_ARG(rig)) {
return -RIG_EINVAL;
}
if (caps->set_dcs_sql == NULL) caps = rig->caps;
return -RIG_ENAVAIL;
if ((caps->targetable_vfo&RIG_TARGETABLE_TONE) || if (caps->set_dcs_sql == NULL) {
vfo == RIG_VFO_CURR || vfo == rig->state.current_vfo) return -RIG_ENAVAIL;
return caps->set_dcs_sql(rig, vfo, code); }
if (!caps->set_vfo) if ((caps->targetable_vfo & RIG_TARGETABLE_TONE)
return -RIG_ENTARGET; || vfo == RIG_VFO_CURR
curr_vfo = rig->state.current_vfo; || vfo == rig->state.current_vfo) {
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_dcs_sql(rig, vfo, code); return caps->set_dcs_sql(rig, vfo, code);
caps->set_vfo(rig, curr_vfo); }
return retcode;
if (!caps->set_vfo) {
return -RIG_ENTARGET;
}
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK) {
return retcode;
}
retcode = caps->set_dcs_sql(rig, vfo, code);
caps->set_vfo(rig, curr_vfo);
return retcode;
} }
/** /**
* \brief get the current DCS code * \brief get the current DCS code
* \param rig The rig handle * \param rig The rig handle
* \param vfo The target VFO * \param vfo The target VFO
* \param code The location where to store the current tone * \param code The location where to store the current tone
* *
* Retrieves the current Digitally-Coded *Squelch* code. * Retrieves the current Digitally-Coded *Squelch* code.
* *
@ -429,32 +517,44 @@ int HAMLIB_API rig_set_dcs_sql(RIG *rig, vfo_t vfo, tone_t code)
*/ */
int HAMLIB_API rig_get_dcs_sql(RIG *rig, vfo_t vfo, tone_t *code) int HAMLIB_API rig_get_dcs_sql(RIG *rig, vfo_t vfo, tone_t *code)
{ {
const struct rig_caps *caps; const struct rig_caps *caps;
int retcode; int retcode;
vfo_t curr_vfo; vfo_t curr_vfo;
if (CHECK_RIG_ARG(rig) || !code) rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_EINVAL;
caps = rig->caps; if (CHECK_RIG_ARG(rig) || !code) {
return -RIG_EINVAL;
}
if (caps->get_dcs_sql == NULL) caps = rig->caps;
return -RIG_ENAVAIL;
if ((caps->targetable_vfo&RIG_TARGETABLE_TONE) || if (caps->get_dcs_sql == NULL) {
vfo == RIG_VFO_CURR || vfo == rig->state.current_vfo) return -RIG_ENAVAIL;
return caps->get_dcs_sql(rig, vfo, code); }
if (!caps->set_vfo) if ((caps->targetable_vfo & RIG_TARGETABLE_TONE)
return -RIG_ENTARGET; || vfo == RIG_VFO_CURR
curr_vfo = rig->state.current_vfo; || vfo == rig->state.current_vfo) {
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_dcs_sql(rig, vfo, code); return caps->get_dcs_sql(rig, vfo, code);
caps->set_vfo(rig, curr_vfo); }
return retcode;
if (!caps->set_vfo) {
return -RIG_ENTARGET;
}
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK) {
return retcode;
}
retcode = caps->get_dcs_sql(rig, vfo, code);
caps->set_vfo(rig, curr_vfo);
return retcode;
} }
/*! @} */ /*! @} */

Wyświetl plik

@ -23,24 +23,25 @@
#define _TONES_H 1 #define _TONES_H 1
#include "hamlib/rig.h" /* and implicitly rig_dll.h */ #include <hamlib/rig.h> /* and implicitly rig_dll.h */
/* /*
* 52 CTCSS sub-audible tones * 52 CTCSS sub-audible tones
*/ */
#define FULL_CTCSS_LIST \ #define FULL_CTCSS_LIST \
600, 670, 693, 719, 744, 770, 797, 825, 854, 885, 915, \ 600, 670, 693, 719, 744, 770, 797, 825, 854, 885, 915, \
948, 974, 1000, 1035, 1072, 1109, 1148, 1188, 1200, 1230, 1273, \ 948, 974, 1000, 1035, 1072, 1109, 1148, 1188, 1200, 1230, 1273, \
1318, 1365, 1413, 1462, 1514, 1567, 1598, 1622, 1655, 1679, \ 1318, 1365, 1413, 1462, 1514, 1567, 1598, 1622, 1655, 1679, \
1713, 1738, 1773, 1799, 1835, 1862, 1899, 1928, 1966, 1995, \ 1713, 1738, 1773, 1799, 1835, 1862, 1899, 1928, 1966, 1995, \
2035, 2065, 2107, 2181, 2257, 2291, 2336, 2418, 2503, 2541, \ 2035, 2065, 2107, 2181, 2257, 2291, 2336, 2418, 2503, 2541, \
0, 0,
static const tone_t static_full_ctcss_list[] = { static const tone_t static_full_ctcss_list[] = {
FULL_CTCSS_LIST FULL_CTCSS_LIST
}; };
/* /*
* 50 CTCSS sub-audible tones, from 67.0Hz to 254.1Hz * 50 CTCSS sub-audible tones, from 67.0Hz to 254.1Hz
* *
@ -49,55 +50,58 @@ static const tone_t static_full_ctcss_list[] = {
* own caps. --SF * own caps. --SF
*/ */
#define COMMON_CTCSS_LIST \ #define COMMON_CTCSS_LIST \
670, 693, 719, 744, 770, 797, 825, 854, 885, 915, \ 670, 693, 719, 744, 770, 797, 825, 854, 885, 915, \
948, 974, 1000, 1035, 1072, 1109, 1148, 1188, 1230, 1273, \ 948, 974, 1000, 1035, 1072, 1109, 1148, 1188, 1230, 1273, \
1318, 1365, 1413, 1462, 1514, 1567, 1598, 1622, 1655, 1679, \ 1318, 1365, 1413, 1462, 1514, 1567, 1598, 1622, 1655, 1679, \
1713, 1738, 1773, 1799, 1835, 1862, 1899, 1928, 1966, 1995, \ 1713, 1738, 1773, 1799, 1835, 1862, 1899, 1928, 1966, 1995, \
2035, 2065, 2107, 2181, 2257, 2291, 2336, 2418, 2503, 2541, \ 2035, 2065, 2107, 2181, 2257, 2291, 2336, 2418, 2503, 2541, \
0, 0,
static const tone_t static_common_ctcss_list[] = { static const tone_t static_common_ctcss_list[] = {
COMMON_CTCSS_LIST COMMON_CTCSS_LIST
}; };
/* /*
* 104 DCS codes * 104 DCS codes
*/ */
#define COMMON_DCS_LIST \ #define COMMON_DCS_LIST \
23, 25, 26, 31, 32, 36, 43, 47, 51, 53, \ 23, 25, 26, 31, 32, 36, 43, 47, 51, 53, \
54, 65, 71, 72, 73, 74, 114, 115, 116, 122, 125, 131, \ 54, 65, 71, 72, 73, 74, 114, 115, 116, 122, 125, 131, \
132, 134, 143, 145, 152, 155, 156, 162, 165, 172, 174, 205, \ 132, 134, 143, 145, 152, 155, 156, 162, 165, 172, 174, 205, \
212, 223, 225, 226, 243, 244, 245, 246, 251, 252, 255, 261, \ 212, 223, 225, 226, 243, 244, 245, 246, 251, 252, 255, 261, \
263, 265, 266, 271, 274, 306, 311, 315, 325, 331, 332, 343, \ 263, 265, 266, 271, 274, 306, 311, 315, 325, 331, 332, 343, \
346, 351, 356, 364, 365, 371, 411, 412, 413, 423, 431, 432, \ 346, 351, 356, 364, 365, 371, 411, 412, 413, 423, 431, 432, \
445, 446, 452, 454, 455, 462, 464, 465, 466, 503, 506, 516, \ 445, 446, 452, 454, 455, 462, 464, 465, 466, 503, 506, 516, \
523, 526, 532, 546, 565, 606, 612, 624, 627, 631, 632, 654, \ 523, 526, 532, 546, 565, 606, 612, 624, 627, 631, 632, 654, \
662, 664, 703, 712, 723, 731, 732, 734, 743, 754, \ 662, 664, 703, 712, 723, 731, 732, 734, 743, 754, \
0, 0,
static const tone_t static_common_dcs_list[] = { static const tone_t static_common_dcs_list[] = {
COMMON_DCS_LIST COMMON_DCS_LIST
}; };
/* /*
* 106 DCS codes * 106 DCS codes
*/ */
#define FULL_DCS_LIST \ #define FULL_DCS_LIST \
17, 23, 25, 26, 31, 32, 36, 43, 47, 50, 51, 53, \ 17, 23, 25, 26, 31, 32, 36, 43, 47, 50, 51, 53, \
54, 65, 71, 72, 73, 74, 114, 115, 116, 122, 125, 131, \ 54, 65, 71, 72, 73, 74, 114, 115, 116, 122, 125, 131, \
132, 134, 143, 145, 152, 155, 156, 162, 165, 172, 174, 205, \ 132, 134, 143, 145, 152, 155, 156, 162, 165, 172, 174, 205, \
212, 223, 225, 226, 243, 244, 245, 246, 251, 252, 255, 261, \ 212, 223, 225, 226, 243, 244, 245, 246, 251, 252, 255, 261, \
263, 265, 266, 271, 274, 306, 311, 315, 325, 331, 332, 343, \ 263, 265, 266, 271, 274, 306, 311, 315, 325, 331, 332, 343, \
346, 351, 356, 364, 365, 371, 411, 412, 413, 423, 431, 432, \ 346, 351, 356, 364, 365, 371, 411, 412, 413, 423, 431, 432, \
445, 446, 452, 454, 455, 462, 464, 465, 466, 503, 506, 516, \ 445, 446, 452, 454, 455, 462, 464, 465, 466, 503, 506, 516, \
523, 526, 532, 546, 565, 606, 612, 624, 627, 631, 632, 654, \ 523, 526, 532, 546, 565, 606, 612, 624, 627, 631, 632, 654, \
662, 664, 703, 712, 723, 731, 732, 734, 743, 754, \ 662, 664, 703, 712, 723, 731, 732, 734, 743, 754, \
0, 0,
static const tone_t static_full_dcs_list[] = { static const tone_t static_full_dcs_list[] = {
FULL_DCS_LIST FULL_DCS_LIST
}; };
/* /*
* These arrays cannot be shared on Win32 systems, * These arrays cannot be shared on Win32 systems,
* because DLL's vars don't have constant address. * because DLL's vars don't have constant address.

Wyświetl plik

@ -35,7 +35,7 @@
#include "config.h" #include "config.h"
#endif #endif
#include "hamlib/rig.h" #include <hamlib/rig.h>
/* /*
* Compile only if libusb is available * Compile only if libusb is available
@ -60,110 +60,146 @@
#include "usb_port.h" #include "usb_port.h"
/** /**
* \brief Find and open USB device * \brief Find and open USB device
* \param port * \param port
* \return usb_handle * \return usb_handle
*/ */
static libusb_device_handle *find_and_open_device(const hamlib_port_t *port) static libusb_device_handle * find_and_open_device(const hamlib_port_t *port)
{ {
libusb_device_handle *udh = NULL; libusb_device_handle *udh = NULL;
libusb_device *dev, **devs; libusb_device *dev, **devs;
struct libusb_device_descriptor desc; struct libusb_device_descriptor desc;
char string[256]; char string[256];
int i, r; int i, r;
rig_debug(RIG_DEBUG_VERBOSE, "%s: looking for device %04x:%04x...", rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
__func__, port->parm.usb.vid, port->parm.usb.pid);
r = libusb_get_device_list(NULL, &devs); rig_debug(RIG_DEBUG_VERBOSE,
"%s: looking for device %04x:%04x...",
__func__,
port->parm.usb.vid,
port->parm.usb.pid);
if (r < 0) { r = libusb_get_device_list(NULL, &devs);
rig_debug(RIG_DEBUG_ERR, "%s: failed getting usb device list: %s",
__func__, libusb_error_name(r));
return NULL;
}
for (i = 0; (dev = devs[i]) != NULL; i++) { if (r < 0) {
rig_debug(RIG_DEBUG_ERR,
"%s: failed getting usb device list: %s",
__func__,
libusb_error_name(r));
libusb_get_device_descriptor(dev, &desc); return NULL;
}
rig_debug(RIG_DEBUG_VERBOSE, " %04x:%04x,", for (i = 0; (dev = devs[i]) != NULL; i++) {
desc.idVendor, desc.idProduct);
if (desc.idVendor == port->parm.usb.vid && libusb_get_device_descriptor(dev, &desc);
desc.idProduct == port->parm.usb.pid) {
/* we need to open the device in order to query strings */ rig_debug(RIG_DEBUG_VERBOSE,
r = libusb_open(dev, &udh); " %04x:%04x,",
desc.idVendor,
desc.idProduct);
if (r < 0) { if (desc.idVendor == port->parm.usb.vid
rig_debug(RIG_DEBUG_WARN, "%s: Warning: Cannot open USB device: %s\n", && desc.idProduct == port->parm.usb.pid) {
__func__, libusb_error_name(r));
continue;
}
/* now check whether the names match: */ /* we need to open the device in order to query strings */
if (port->parm.usb.vendor_name) { r = libusb_open(dev, &udh);
string[0] = '\0'; if (r < 0) {
r = libusb_get_string_descriptor_ascii(udh, desc.iManufacturer, (unsigned char *)string, sizeof(string)); rig_debug(RIG_DEBUG_WARN,
"%s: Warning: Cannot open USB device: %s\n",
__func__,
libusb_error_name(r));
if (r < 0) { continue;
rig_debug(RIG_DEBUG_WARN, "Warning: cannot query manufacturer for USB device: %s\n", libusb_error_name(r)); }
libusb_close(udh);
continue;
}
rig_debug(RIG_DEBUG_VERBOSE, " vendor >%s<", string); /* now check whether the names match: */
if (port->parm.usb.vendor_name) {
if (strcmp(string, port->parm.usb.vendor_name) != 0) { string[0] = '\0';
rig_debug(RIG_DEBUG_WARN, "%s: Warning: Vendor name string mismatch!\n", __func__); r = libusb_get_string_descriptor_ascii(udh,
libusb_close(udh); desc.iManufacturer,
continue; (unsigned char *)string,
} sizeof(string));
}
if (port->parm.usb.product) { if (r < 0) {
rig_debug(RIG_DEBUG_WARN,
"Warning: cannot query manufacturer for USB device: %s\n",
libusb_error_name(r));
string[0] = '\0'; libusb_close(udh);
r = libusb_get_string_descriptor_ascii(udh, desc.iProduct, (unsigned char *)string, sizeof(string)); continue;
}
if (r < 0) { rig_debug(RIG_DEBUG_VERBOSE, " vendor >%s<", string);
rig_debug(RIG_DEBUG_WARN, "Warning: cannot query product for USB device: %s\n", libusb_error_name(r));
libusb_close(udh);
continue;
}
rig_debug(RIG_DEBUG_VERBOSE, " product >%s<", string); if (strcmp(string, port->parm.usb.vendor_name) != 0) {
rig_debug(RIG_DEBUG_WARN,
"%s: Warning: Vendor name string mismatch!\n",
__func__);
if (strcmp(string, port->parm.usb.product) != 0) { libusb_close(udh);
/* Now testing with strncasecmp() for case insensitive continue;
* match. Updating firmware on FUNcube Dongle to v18f resulted }
* in product string changing from "FunCube Dongle" to }
* "FUNcube Dongle". As new dongles are shipped with
* older firmware, both product strings are valid. Sigh...
*/
if (strncasecmp(string, port->parm.usb.product, sizeof(port->parm.usb.product - 1)) != 0) {
rig_debug(RIG_DEBUG_WARN, "%s: Warning: Product string mismatch!\n", __func__);
libusb_close(udh);
continue;
}
}
}
libusb_free_device_list(devs, 1); if (port->parm.usb.product) {
rig_debug(RIG_DEBUG_VERBOSE, " -> found\n"); string[0] = '\0';
return udh; r = libusb_get_string_descriptor_ascii(udh,
} desc.iProduct,
} (unsigned char *)string,
sizeof(string));
libusb_free_device_list(devs, 1); if (r < 0) {
rig_debug(RIG_DEBUG_WARN,
"Warning: cannot query product for USB device: %s\n",
libusb_error_name(r));
rig_debug(RIG_DEBUG_VERBOSE, " -> not found\n"); libusb_close(udh);
return NULL; /* not found */ continue;
}
rig_debug(RIG_DEBUG_VERBOSE, " product >%s<", string);
if (strcmp(string, port->parm.usb.product) != 0) {
/* Now testing with strncasecmp() for case insensitive
* match. Updating firmware on FUNcube Dongle to v18f resulted
* in product string changing from "FunCube Dongle" to
* "FUNcube Dongle". As new dongles are shipped with
* older firmware, both product strings are valid. Sigh...
*/
if (strncasecmp(string,
port->parm.usb.product,
sizeof(port->parm.usb.product - 1)) != 0) {
rig_debug(RIG_DEBUG_WARN,
"%s: Warning: Product string mismatch!\n",
__func__);
libusb_close(udh);
continue;
}
}
}
libusb_free_device_list(devs, 1);
rig_debug(RIG_DEBUG_VERBOSE, " -> found\n");
return udh;
}
}
libusb_free_device_list(devs, 1);
rig_debug(RIG_DEBUG_VERBOSE, " -> not found\n");
return NULL; /* not found */
} }
@ -174,119 +210,144 @@ static libusb_device_handle *find_and_open_device(const hamlib_port_t *port)
*/ */
int usb_port_open(hamlib_port_t *port) int usb_port_open(hamlib_port_t *port)
{ {
static char pathname[FILPATHLEN]; static char pathname[FILPATHLEN];
libusb_device_handle *udh; libusb_device_handle *udh;
char *p, *q; char *p, *q;
int r; int r;
/* init defaut libusb-1.0 library contexte, if needed */ rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
r = libusb_init(NULL);
if (r < 0) { /* init defaut libusb-1.0 library contexte, if needed */
rig_debug(RIG_DEBUG_ERR, "%s: libusb_init failed: %s\n", r = libusb_init(NULL);
__func__, libusb_error_name(r));
return -RIG_EIO;
}
//libusb_set_debug(NULL, 1); if (r < 0) {
rig_debug(RIG_DEBUG_ERR,
"%s: libusb_init failed: %s\n",
__func__,
libusb_error_name(r));
/* Extract VID/PID/Vendor/Product name from pathname. */ return -RIG_EIO;
/* Duplicate the string since we may modify it. */ }
strncpy(pathname, port->pathname, sizeof pathname);
pathname[FILPATHLEN - 1] = '\0';
p = pathname; //libusb_set_debug(NULL, 1);
q = strchr(p, ':');
if (q) { /* Extract VID/PID/Vendor/Product name from pathname. */
++q; /* Duplicate the string since we may modify it. */
port->parm.usb.vid = strtol(q, NULL, 16); strncpy(pathname, port->pathname, sizeof pathname);
p = q; pathname[FILPATHLEN - 1] = '\0';
q = strchr(p, ':');
if (q) { p = pathname;
++q; q = strchr(p, ':');
port->parm.usb.pid = strtol(q, NULL, 16);
p = q;
q = strchr(p, ':');
if (q) { if (q) {
++q; ++q;
port->parm.usb.vendor_name = q; port->parm.usb.vid = strtol(q, NULL, 16);
p = q; p = q;
q = strchr(p, ':'); q = strchr(p, ':');
if (q) { if (q) {
*q++ = '\0'; ++q;
port->parm.usb.product = q; port->parm.usb.pid = strtol(q, NULL, 16);
} p = q;
} q = strchr(p, ':');
}
}
udh = find_and_open_device(port); if (q) {
++q;
port->parm.usb.vendor_name = q;
p = q;
q = strchr(p, ':');
if (udh == 0) { if (q) {
libusb_exit(NULL); *q++ = '\0';
return -RIG_EIO; port->parm.usb.product = q;
} }
}
}
}
/* Try to detach ftdi_sio kernel module. udh = find_and_open_device(port);
* This should be performed only for devices using
* USB-serial converters (like FTDI chips), for other
* devices this may cause problems, so do not do it.
*/
(void)libusb_set_auto_detach_kernel_driver(udh, port->parm.usb.iface);
if (port->parm.usb.iface >= 0) { if (udh == 0) {
libusb_exit(NULL);
return -RIG_EIO;
}
/* Try to detach ftdi_sio kernel module.
* This should be performed only for devices using
* USB-serial converters (like FTDI chips), for other
* devices this may cause problems, so do not do it.
*/
(void)libusb_set_auto_detach_kernel_driver(udh, port->parm.usb.iface);
if (port->parm.usb.iface >= 0) {
#ifdef _WIN32 #ifdef _WIN32
/* Is it still needed with libusb-1.0 ? */ /* Is it still needed with libusb-1.0 ? */
if (port->parm.usb.conf >= 0 && if (port->parm.usb.conf >= 0
(r = libusb_set_configuration(udh, port->parm.usb.conf)) < 0) { && (r = libusb_set_configuration(udh, port->parm.usb.conf)) < 0) {
rig_debug(RIG_DEBUG_ERR, "%s: libusb_set_configuration: failed conf %d: %s\n",
__func__, port->parm.usb.conf, libusb_error_name(r)); rig_debug(RIG_DEBUG_ERR,
libusb_close(udh); "%s: libusb_set_configuration: failed conf %d: %s\n",
libusb_exit(NULL); __func__,
return -RIG_EIO; port->parm.usb.conf,
} libusb_error_name(r));
libusb_close(udh);
libusb_exit(NULL);
return -RIG_EIO;
}
#endif #endif
rig_debug(RIG_DEBUG_VERBOSE, "%s: claiming %d\n", __func__, port->parm.usb.iface); rig_debug(RIG_DEBUG_VERBOSE,
"%s: claiming %d\n",
__func__,
port->parm.usb.iface);
r = libusb_claim_interface(udh, port->parm.usb.iface); r = libusb_claim_interface(udh, port->parm.usb.iface);
if (r < 0) { if (r < 0) {
rig_debug(RIG_DEBUG_ERR, "%s:libusb_claim_interface: failed interface %d: %s\n", rig_debug(RIG_DEBUG_ERR,
__func__, port->parm.usb.iface, libusb_error_name(r)); "%s:libusb_claim_interface: failed interface %d: %s\n",
libusb_close(udh); __func__,
libusb_exit(NULL); port->parm.usb.iface,
return -RIG_EIO; libusb_error_name(r));
}
libusb_close(udh);
libusb_exit(NULL);
return -RIG_EIO;
}
#if 0 #if 0
r = libusb_set_interface_alt_setting(udh, port->parm.usb.iface, port->parm.usb.alt); r = libusb_set_interface_alt_setting(udh, port->parm.usb.iface,
port->parm.usb.alt);
if (r < 0) { if (r < 0) {
fprintf(stderr, "%s:usb_set_alt_interface: failed: %s\n", __func__, fprintf(stderr,
libusb_error_name(r)); "%s:usb_set_alt_interface: failed: %s\n",
libusb_release_interface(udh, port->parm.usb.iface); __func__,
libusb_close(udh); libusb_error_name(r));
libusb_exit(NULL);
return -RIG_EIO; libusb_release_interface(udh, port->parm.usb.iface);
} libusb_close(udh);
libusb_exit(NULL);
return -RIG_EIO;
}
#endif #endif
} }
port->handle = (void *) udh; port->handle = (void *) udh;
return RIG_OK; return RIG_OK;
} }
/** /**
* \brief Close hamlib_port of USB device * \brief Close hamlib_port of USB device
* \param port * \param port
@ -294,29 +355,36 @@ int usb_port_open(hamlib_port_t *port)
*/ */
int usb_port_close(hamlib_port_t *port) int usb_port_close(hamlib_port_t *port)
{ {
libusb_device_handle *udh = port->handle; rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
libusb_release_interface(udh, port->parm.usb.iface); libusb_device_handle *udh = port->handle;
libusb_close(udh); libusb_release_interface(udh, port->parm.usb.iface);
libusb_exit(NULL); libusb_close(udh);
return RIG_OK; libusb_exit(NULL);
return RIG_OK;
} }
#else #else
int usb_port_open(hamlib_port_t *port) int usb_port_open(hamlib_port_t *port)
{ {
return -RIG_ENAVAIL; rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_ENAVAIL;
} }
int usb_port_close(hamlib_port_t *port) int usb_port_close(hamlib_port_t *port)
{ {
return -RIG_ENAVAIL; rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return -RIG_ENAVAIL;
} }
#endif /* defined(HAVE_LIBUSB) && defined(HAVE_LIBUSB_H) */ #endif /* defined(HAVE_LIBUSB) && defined(HAVE_LIBUSB_H) */
/** @} */ /** @} */