mirror of
https://github.com/Hamlib/Hamlib.git
synced 2024-09-25 04:17:28 +00:00
Initial release
git-svn-id: https://hamlib.svn.sourceforge.net/svnroot/hamlib/trunk@812 7ae35d74-ebe9-4afe-98af-79ac388436b8
This commit is contained in:
parent
532602372b
commit
e66509d2c5
268
src/locator.c
Normal file
268
src/locator.c
Normal file
@ -0,0 +1,268 @@
|
||||
/**
|
||||
* \file src/locator.c
|
||||
* \brief Ham Radio Control Libraries interface
|
||||
* \author Stephane Fillod
|
||||
* \date 2000-2001
|
||||
*
|
||||
* Hamlib interface is a frontend implementing wrapper functions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Hamlib Interface - locator and bearing conversion calls
|
||||
* Copyright (c) 2001 by Stephane Fillod
|
||||
*
|
||||
* $Id: locator.c,v 1.1 2001-12-27 21:46:25 fillods Exp $
|
||||
*
|
||||
* Code to determine bearing and range was taken from the Great Circle,
|
||||
* by S. R. Sampson, N5OWK.
|
||||
* Ref: "Air Navigation", Air Force Manual 51-40, 1 February 1987
|
||||
* Ref: "ARRL Satellite Experimenters Handbook", August 1990
|
||||
*
|
||||
* Code to calculate distance and azimuth between two Maidenhead locators,
|
||||
* taken from wwl, by IK0ZSN Mirko Caserta.
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
#include <hamlib/rotator.h>
|
||||
|
||||
|
||||
#define RADIAN (180.0 / M_PI)
|
||||
|
||||
/* arc length for 1 degree, 60 Nautical Miles */
|
||||
#define ARC_IN_KM 111.2
|
||||
|
||||
/*
|
||||
* degrees >360, minutes > 60, and seconds > 60 are allowed
|
||||
*/
|
||||
double dms2dec(int degrees, int minutes, int seconds)
|
||||
{
|
||||
return (double)degrees + minutes/60.0 + seconds/3600.0;
|
||||
}
|
||||
/*
|
||||
* guarantee: dec2dms will make sure 0<=degress<360,
|
||||
* 0<=minutes<60, 0<=seconds<0
|
||||
*/
|
||||
void dec2dms(double dec, int *degrees, int *minutes, int *seconds)
|
||||
{
|
||||
if (!degrees || !minutes || !seconds)
|
||||
return;
|
||||
|
||||
dec = fmod(dec, 360);
|
||||
*degrees = (int)floor(dec);
|
||||
dec -= *degrees;
|
||||
dec *= 60;
|
||||
*minutes = (int)floor(dec);
|
||||
dec -= *minutes;
|
||||
dec *= 60;
|
||||
*seconds = (int)floor(dec);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 4 characters and 6 characters are accepted
|
||||
*/
|
||||
int locator2longlat(double *longitude, double *latitude, const char *locator)
|
||||
{
|
||||
char loc[6];
|
||||
|
||||
if (locator[4] != '\0' && locator[6] != '\0')
|
||||
return -1;
|
||||
|
||||
loc[0] = toupper(locator[0]);
|
||||
loc[1] = toupper(locator[1]);
|
||||
loc[2] = locator[2];
|
||||
loc[3] = locator[3];
|
||||
if (locator[4] != '\0') {
|
||||
loc[4] = toupper(locator[4]);
|
||||
loc[5] = toupper(locator[5]);
|
||||
} else {
|
||||
loc[4] = 'A';
|
||||
loc[5] = 'A';
|
||||
}
|
||||
if (loc[0] < 'A' || loc[0] > 'Z' ||
|
||||
loc[1] < 'A' || loc[1] > 'Z' ||
|
||||
loc[2] < '0' || loc[2] > '9' ||
|
||||
loc[3] < '0' || loc[3] > '9' ||
|
||||
loc[4] < 'A' || loc[4] > 'Z' ||
|
||||
loc[5] < 'A' || loc[5] > 'Z' ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*longitude = 20.0 * (loc[0]-'A') - 180.0 + 2.0 * (loc[2]-'0') +
|
||||
(loc[4]-'A')/12.0 + 1.0;
|
||||
|
||||
*latitude = 10.0 * (loc[1]-'A') - 90.0 + (loc[3]-'0') +
|
||||
(loc[5]-'A')/24.0 + 1.0/48.0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* locator must be at least 6 chars long
|
||||
*/
|
||||
int longlat2locator(double longitude, double latitude, char *locator)
|
||||
{
|
||||
#if 0
|
||||
double t,s;
|
||||
|
||||
t = 20.0 * (loc[0]-'A') - 180.0 + 2.0 * (loc[2]-'0') +
|
||||
(loc[4]-'A')/12.0 + 1.0;
|
||||
*longitude = t;
|
||||
|
||||
s = 10.0 * (loc[1]-'A') - 90.0 + (loc[3]-'0') +
|
||||
(loc[5]-'A')/24.0 + 1.0/48.0;
|
||||
*latitude = s;
|
||||
#endif
|
||||
strcpy (locator, "MM00mm");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 1 towards 2
|
||||
* returns qrb in km
|
||||
* and azimuth in decimal degrees
|
||||
*/
|
||||
|
||||
/*
|
||||
* This version also takes into consideration the two points
|
||||
* being close enough to be in the near-field, and the antipodal points,
|
||||
* which are easily calculated. These last points were made
|
||||
* in discussions with John Allison who makes the nice MAPIT program.
|
||||
*/
|
||||
int qrb(double lon1, double lat1, double lon2, double lat2,
|
||||
double *bearing, double *azimuth)
|
||||
{
|
||||
double delta_long, tmp, arc, cosaz, az;
|
||||
|
||||
if (!bearing || !azimuth)
|
||||
return -1;
|
||||
|
||||
if ((lat1 > 90.0 || lat1 < -90.0) || (lat2 > 90.0 || lat2 < -90.0))
|
||||
return -1;
|
||||
|
||||
if ((lon1 > 180.0 || lon1 < -180.0) || (lon2 > 180.0 || lon2 < -180.0))
|
||||
return -1;
|
||||
|
||||
/* Prevent ACOS() Domain Error */
|
||||
|
||||
if (lat1 == 90.0)
|
||||
lat1 = 89.99;
|
||||
else if (lat1 == -90.0)
|
||||
lat1 = -89.99;
|
||||
|
||||
if (lat2 == 90.0)
|
||||
lat2 = 89.99;
|
||||
else if (lat2 == -90.0)
|
||||
lat2 = -89.99;
|
||||
|
||||
/*
|
||||
* Convert variables to Radians
|
||||
*/
|
||||
lat1 /= RADIAN;
|
||||
lon1 /= RADIAN;
|
||||
lat2 /= RADIAN;
|
||||
lon2 /= RADIAN;
|
||||
|
||||
delta_long = lon2 - lon1;
|
||||
|
||||
tmp = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(delta_long);
|
||||
|
||||
if (tmp > .999999) {
|
||||
/* Station points coincide, use an Omni! */
|
||||
*bearing = 0.0;
|
||||
*azimuth = 0.0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tmp < -.999999) {
|
||||
/*
|
||||
* points are antipodal, it's straight down.
|
||||
* Station is equal distance in all Azimuths.
|
||||
* So take 180 Degrees of arc times 60 nm,
|
||||
* and you get 10800 nm, or whatever units...
|
||||
*/
|
||||
|
||||
*bearing = 180.0*ARC_IN_KM;
|
||||
*azimuth = 0.0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
arc = acos(tmp);
|
||||
|
||||
/*
|
||||
* One degree of arc is 60 Nautical miles
|
||||
* at the surface of the earth, 111.2 km, or 69.1 sm
|
||||
* This method is easier than the one in the handbook
|
||||
*/
|
||||
|
||||
/* Short Path */
|
||||
|
||||
*bearing = ARC_IN_KM * RADIAN * arc;
|
||||
|
||||
/*
|
||||
* Long Path
|
||||
*
|
||||
* distlp = (ARC_IN_KM * 360.0) - distsp;
|
||||
*/
|
||||
|
||||
cosaz = (sin(lat2) - (sin(lat1) * cos(arc))) /
|
||||
(sin(arc) * cos(lat1));
|
||||
|
||||
if (cosaz > .999999)
|
||||
az = 0.0;
|
||||
else if (cosaz < -.999999)
|
||||
az = 180.0;
|
||||
else
|
||||
az = acos(cosaz) * RADIAN;
|
||||
|
||||
/*
|
||||
* Handbook had the test ">= 0.0" which looks backwards??
|
||||
*/
|
||||
|
||||
if (sin(delta_long) < 0.0) {
|
||||
*azimuth = az;
|
||||
} else {
|
||||
*azimuth = 360.0 - az;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
double bearing_long_path(double bearing)
|
||||
{
|
||||
return (ARC_IN_KM * 360.0) - bearing;
|
||||
}
|
||||
|
||||
double azimuth_long_path(double azimuth)
|
||||
{
|
||||
return 360.0-azimuth;
|
||||
}
|
||||
|
273
src/rot_conf.c
Normal file
273
src/rot_conf.c
Normal file
@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Hamlib Interface - configuration interface
|
||||
* Copyright (c) 2000,2001 by Stephane Fillod and Frank Singleton
|
||||
*
|
||||
* $Id: rot_conf.c,v 1.1 2001-12-27 21:46:25 fillods Exp $
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h> /* Standard input/output definitions */
|
||||
#include <string.h> /* String function definitions */
|
||||
#include <unistd.h> /* UNIX standard function definitions */
|
||||
|
||||
#include <hamlib/rotator.h>
|
||||
|
||||
#include "rot_conf.h"
|
||||
|
||||
|
||||
/*
|
||||
* Place holder for now. Here will be defined all the configuration
|
||||
* options available in the rot->state struct.
|
||||
*/
|
||||
static const struct confparams rotfrontend_cfg_params[] = {
|
||||
{ TOK_ROT_PATHNAME, "rot_pathname", "Rig path name",
|
||||
"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_POST_WRITE_DELAY, "post_write_delay", "Post write delay",
|
||||
"Delay in ms between each command sent out",
|
||||
"0", RIG_CONF_NUMERIC, { n: { 0, 1000, 1 } }
|
||||
},
|
||||
{ TOK_TIMEOUT, "timeout", "Timeout", "Timeout in ms",
|
||||
"0", RIG_CONF_NUMERIC, { n: { 0, 10000, 1 } }
|
||||
},
|
||||
{ TOK_RETRY, "retry", "Retry", "Max number of retry",
|
||||
"0", RIG_CONF_NUMERIC, { n: { 0, 10, 1 } }
|
||||
},
|
||||
|
||||
{ TOK_SERIAL_SPEED, "serial_speed", "Serial speed",
|
||||
"Serial port baud rate",
|
||||
"0", RIG_CONF_NUMERIC, { n: { 300, 115200, 1 } }
|
||||
},
|
||||
{ TOK_DATA_BITS, "data_bits", "Serial data bits",
|
||||
"Serial port data bits",
|
||||
"8", RIG_CONF_NUMERIC, { n: { 5, 8, 1 } }
|
||||
},
|
||||
{ TOK_STOP_BITS, "stop_bits", "Serial stop bits",
|
||||
"Serial port stop bits",
|
||||
"1", RIG_CONF_NUMERIC, { n: { 0, 3, 1 } }
|
||||
},
|
||||
{ TOK_PARITY, "serial_parity", "Serial parity",
|
||||
"Serial port parity",
|
||||
"None", RIG_CONF_COMBO, { c: {{ "None", "Odd", "Even", NULL }} }
|
||||
},
|
||||
{ TOK_HANDSHAKE, "serial_handshake", "Serial handshake",
|
||||
"Serial port handshake",
|
||||
"None", RIG_CONF_COMBO, { c: {{ "None", "XONXOFF", "Hardware", NULL }} }
|
||||
},
|
||||
|
||||
{ RIG_CONF_END, NULL, }
|
||||
};
|
||||
|
||||
/*
|
||||
* frontrot_set_conf
|
||||
* assumes rot!=NULL, val!=NULL
|
||||
* TODO: check format of val before doing atoi().
|
||||
*/
|
||||
int frontrot_set_conf(ROT *rot, token_t token, const char *val)
|
||||
{
|
||||
const struct rot_caps *caps;
|
||||
struct rot_state *rs;
|
||||
|
||||
caps = rot->caps;
|
||||
rs = &rot->state;
|
||||
|
||||
switch(token) {
|
||||
case TOK_ROT_PATHNAME:
|
||||
strcpy(rs->rotport.pathname, val);
|
||||
break;
|
||||
case TOK_WRITE_DELAY:
|
||||
rs->rotport.write_delay = atoi(val);
|
||||
break;
|
||||
case TOK_POST_WRITE_DELAY:
|
||||
rs->rotport.post_write_delay = atoi(val);
|
||||
break;
|
||||
case TOK_TIMEOUT:
|
||||
rs->rotport.timeout = atoi(val);
|
||||
break;
|
||||
case TOK_RETRY:
|
||||
rs->rotport.retry = atoi(val);
|
||||
break;
|
||||
|
||||
case TOK_SERIAL_SPEED:
|
||||
rs->rotport.parm.serial.rate = atoi(val);
|
||||
break;
|
||||
case TOK_DATA_BITS:
|
||||
rs->rotport.parm.serial.data_bits = atoi(val);
|
||||
break;
|
||||
case TOK_STOP_BITS:
|
||||
rs->rotport.parm.serial.stop_bits = atoi(val);
|
||||
break;
|
||||
case TOK_PARITY:
|
||||
if (!strncmp(val, "None", 8))
|
||||
rs->rotport.parm.serial.parity = RIG_PARITY_NONE;
|
||||
else if (!strncmp(val, "Odd", 8))
|
||||
rs->rotport.parm.serial.parity = RIG_PARITY_ODD;
|
||||
else if (!strncmp(val, "Even", 8))
|
||||
rs->rotport.parm.serial.parity = RIG_PARITY_EVEN;
|
||||
else
|
||||
return -RIG_EINVAL;
|
||||
break;
|
||||
case TOK_HANDSHAKE:
|
||||
if (!strncmp(val, "None", 8))
|
||||
rs->rotport.parm.serial.handshake = RIG_HANDSHAKE_NONE;
|
||||
else if (!strncmp(val, "XONXOFF", 8))
|
||||
rs->rotport.parm.serial.handshake = RIG_HANDSHAKE_XONXOFF;
|
||||
else if (!strncmp(val, "Hardware", 8))
|
||||
rs->rotport.parm.serial.handshake = RIG_HANDSHAKE_HARDWARE;
|
||||
else
|
||||
return -RIG_EINVAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -RIG_EINVAL;
|
||||
}
|
||||
return RIG_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* frontrot_get_conf
|
||||
* assumes rot!=NULL, val!=NULL
|
||||
*/
|
||||
int frontrot_get_conf(ROT *rot, token_t token, char *val)
|
||||
{
|
||||
const struct rot_caps *caps;
|
||||
struct rot_state *rs;
|
||||
const char *s;
|
||||
|
||||
caps = rot->caps;
|
||||
rs = &rot->state;
|
||||
|
||||
switch(token) {
|
||||
case TOK_ROT_PATHNAME:
|
||||
strcpy(val, rs->rotport.pathname);
|
||||
break;
|
||||
case TOK_WRITE_DELAY:
|
||||
sprintf(val, "%d", rs->rotport.write_delay);
|
||||
break;
|
||||
case TOK_POST_WRITE_DELAY:
|
||||
sprintf(val, "%d", rs->rotport.post_write_delay);
|
||||
break;
|
||||
case TOK_TIMEOUT:
|
||||
sprintf(val, "%d", rs->rotport.timeout);
|
||||
break;
|
||||
case TOK_RETRY:
|
||||
sprintf(val, "%d", rs->rotport.retry);
|
||||
break;
|
||||
case TOK_SERIAL_SPEED:
|
||||
sprintf(val, "%d", rs->rotport.parm.serial.rate);
|
||||
break;
|
||||
case TOK_DATA_BITS:
|
||||
sprintf(val, "%d", rs->rotport.parm.serial.data_bits);
|
||||
break;
|
||||
case TOK_STOP_BITS:
|
||||
sprintf(val, "%d", rs->rotport.parm.serial.stop_bits);
|
||||
break;
|
||||
case TOK_PARITY:
|
||||
switch (rs->rotport.parm.serial.parity) {
|
||||
case RIG_PARITY_NONE: s = "None"; break;
|
||||
case RIG_PARITY_ODD: s = "Odd"; break;
|
||||
case RIG_PARITY_EVEN: s = "Even"; break;
|
||||
default: return -RIG_EINVAL;
|
||||
}
|
||||
strcpy(val, s);
|
||||
break;
|
||||
case TOK_HANDSHAKE:
|
||||
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;
|
||||
|
||||
default:
|
||||
return -RIG_EINVAL;
|
||||
}
|
||||
|
||||
return RIG_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* rot_token_foreach
|
||||
* executes cfunc on all the elements stored in the conf table
|
||||
* start first with backend conf table, then finish with frontend table
|
||||
*/
|
||||
int rot_token_foreach(ROT *rot, int (*cfunc)(const struct confparams *, rig_ptr_t), rig_ptr_t data)
|
||||
{
|
||||
const struct confparams *cfp;
|
||||
|
||||
if (!rot || !rot->caps || !cfunc)
|
||||
return -RIG_EINVAL;
|
||||
|
||||
for (cfp = rot->caps->cfgparams; cfp && cfp->name; cfp++)
|
||||
if ((*cfunc)(cfp, data) == 0)
|
||||
return RIG_OK;
|
||||
for (cfp = rotfrontend_cfg_params; cfp->name; cfp++)
|
||||
if ((*cfunc)(cfp, data) == 0)
|
||||
return RIG_OK;
|
||||
return RIG_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* lookup conf token by its name, return pointer to confparams struct.
|
||||
*
|
||||
* lookup backend config table first, then fall back to frontend.
|
||||
* TODO: should use Lex to speed it up, strcmp hurts!
|
||||
*/
|
||||
const struct confparams *rot_confparam_lookup(ROT *rot, const char *name)
|
||||
{
|
||||
const struct confparams *cfp;
|
||||
|
||||
if (!rot || !rot->caps)
|
||||
return NULL;
|
||||
for (cfp = rot->caps->cfgparams; cfp && cfp->name; cfp++)
|
||||
if (!strcmp(cfp->name, name))
|
||||
return cfp;
|
||||
for (cfp = rotfrontend_cfg_params; cfp->name; cfp++)
|
||||
if (!strcmp(cfp->name, name))
|
||||
return cfp;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple lookup returning token id assicated with name
|
||||
*/
|
||||
token_t rot_token_lookup(ROT *rot, const char *name)
|
||||
{
|
||||
const struct confparams *cfp;
|
||||
|
||||
cfp = rot_confparam_lookup(rot, name);
|
||||
if (!cfp)
|
||||
return RIG_CONF_END;
|
||||
|
||||
return cfp->token;
|
||||
}
|
||||
|
||||
|
48
src/rot_conf.h
Normal file
48
src/rot_conf.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Hamlib Interface - configuration header
|
||||
* Copyright (c) 2000,2001 by Stephane Fillod and Frank Singleton
|
||||
*
|
||||
* $Id: rot_conf.h,v 1.1 2001-12-27 21:46:25 fillods Exp $
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _ROT_CONF_H
|
||||
#define _ROT_CONF_H 1
|
||||
|
||||
#include <hamlib/rotator.h>
|
||||
|
||||
|
||||
int frontrot_set_conf(ROT *rot, token_t token, const char *val);
|
||||
int frontrot_get_conf(ROT *rot, token_t token, char *val);
|
||||
|
||||
#define ROT_TOKEN_FRONTEND RIG_TOKEN_FRONTEND
|
||||
|
||||
#define TOK_ROT_PATHNAME ROT_TOKEN_FRONTEND(10)
|
||||
#define TOK_WRITE_DELAY ROT_TOKEN_FRONTEND(12)
|
||||
#define TOK_POST_WRITE_DELAY ROT_TOKEN_FRONTEND(13)
|
||||
#define TOK_TIMEOUT ROT_TOKEN_FRONTEND(14)
|
||||
#define TOK_RETRY ROT_TOKEN_FRONTEND(15)
|
||||
|
||||
#define TOK_SERIAL_SPEED ROT_TOKEN_FRONTEND(30)
|
||||
#define TOK_DATA_BITS ROT_TOKEN_FRONTEND(31)
|
||||
#define TOK_STOP_BITS ROT_TOKEN_FRONTEND(32)
|
||||
#define TOK_PARITY ROT_TOKEN_FRONTEND(33)
|
||||
#define TOK_HANDSHAKE ROT_TOKEN_FRONTEND(34)
|
||||
|
||||
|
||||
#endif /* _ROT_CONF_H */
|
||||
|
343
src/rot_reg.c
Normal file
343
src/rot_reg.c
Normal file
@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Hamlib Interface - provides registering for dynamically loadable backends.
|
||||
* Copyright (c) 2000,2001 by Stephane Fillod and Frank Singleton
|
||||
*
|
||||
* $Id: rot_reg.c,v 1.1 2001-12-27 21:46:25 fillods Exp $
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* This is libtool's dl wrapper */
|
||||
#include <ltdl.h>
|
||||
|
||||
#include <hamlib/rotator.h>
|
||||
|
||||
|
||||
#ifndef PATH_MAX
|
||||
# define PATH_MAX 1024
|
||||
#endif
|
||||
|
||||
#define ROT_BACKEND_MAX 32
|
||||
|
||||
/*
|
||||
* ROT_BACKEND_LIST is defined in rotlist.h, please keep it up to data,
|
||||
* ie. each time you give birth to 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
|
||||
*/
|
||||
static struct {
|
||||
int be_num;
|
||||
const char *be_name;
|
||||
rot_model_t (*be_probe)(port_t *);
|
||||
} rot_backend_list[ROT_BACKEND_MAX] = ROT_BACKEND_LIST;
|
||||
|
||||
|
||||
/*
|
||||
* This struct to keep track of known rot models.
|
||||
* It is chained, and used in a hash table, see below.
|
||||
*/
|
||||
struct rot_list {
|
||||
const struct rot_caps *caps;
|
||||
lt_dlhandle handle; /* handle returned by lt_dlopen() */
|
||||
struct rot_list *next;
|
||||
};
|
||||
|
||||
#define ROTLSTHASHSZ 16
|
||||
#define HASH_FUNC(a) ((a)%ROTLSTHASHSZ)
|
||||
|
||||
/*
|
||||
* The rot_hash_table is a hash table pointing to a list of next==NULL
|
||||
* terminated caps.
|
||||
*/
|
||||
static struct rot_list *rot_hash_table[ROTLSTHASHSZ] = { NULL, };
|
||||
|
||||
|
||||
static int rot_lookup_backend(rot_model_t rot_model);
|
||||
|
||||
/*
|
||||
* Basically, this is a hash insert function that doesn't check for dup!
|
||||
*/
|
||||
int rot_register(const struct rot_caps *caps)
|
||||
{
|
||||
int hval;
|
||||
struct rot_list *p;
|
||||
|
||||
if (!caps)
|
||||
return -RIG_EINVAL;
|
||||
|
||||
rot_debug(RIG_DEBUG_VERBOSE, "rot_register (%d)\n",caps->rot_model);
|
||||
|
||||
#ifndef DONT_WANT_DUP_CHECK
|
||||
if (rot_get_caps(caps->rot_model)!=NULL)
|
||||
return -RIG_EINVAL;
|
||||
#endif
|
||||
|
||||
p = (struct rot_list*)malloc(sizeof(struct rot_list));
|
||||
if (!p)
|
||||
return -RIG_ENOMEM;
|
||||
|
||||
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.
|
||||
* ie. rot_hash_table lookup
|
||||
*/
|
||||
|
||||
const struct rot_caps *rot_get_caps(rot_model_t rot_model)
|
||||
{
|
||||
struct rot_list *p;
|
||||
|
||||
for (p = rot_hash_table[HASH_FUNC(rot_model)]; p; p=p->next) {
|
||||
if (p->caps->rot_model == rot_model)
|
||||
return p->caps;
|
||||
}
|
||||
return NULL; /* sorry, caps not registered! */
|
||||
}
|
||||
|
||||
/*
|
||||
* lookup for backend index in rot_backend_list table,
|
||||
* according to BACKEND_NUM
|
||||
* return -1 if not found.
|
||||
*/
|
||||
static int rot_lookup_backend(rot_model_t rot_model)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<ROT_BACKEND_MAX && rot_backend_list[i].be_name; i++) {
|
||||
if (ROT_BACKEND_NUM(rot_model) ==
|
||||
rot_backend_list[i].be_num)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* rot_check_backend
|
||||
* check the backend declaring this model has been loaded
|
||||
* and if not loaded already, load it!
|
||||
* This permits seamless operation in rot_init.
|
||||
*/
|
||||
int rot_check_backend(rot_model_t rot_model)
|
||||
{
|
||||
const struct rot_caps *caps;
|
||||
int be_idx;
|
||||
int retval;
|
||||
|
||||
/* already loaded ? */
|
||||
caps = rot_get_caps(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);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int rot_unregister(rot_model_t rot_model)
|
||||
{
|
||||
int hval;
|
||||
struct rot_list *p,*q;
|
||||
|
||||
hval = HASH_FUNC(rot_model);
|
||||
q = NULL;
|
||||
for (p = rot_hash_table[hval]; p; p=p->next) {
|
||||
if (p->caps->rot_model == rot_model) {
|
||||
if (q == NULL)
|
||||
rot_hash_table[hval] = p->next;
|
||||
else
|
||||
q->next = p->next;
|
||||
free(p);
|
||||
return RIG_OK;
|
||||
}
|
||||
q = p;
|
||||
}
|
||||
return -RIG_EINVAL; /* sorry, caps not registered! */
|
||||
}
|
||||
|
||||
/*
|
||||
* rot_list_foreach
|
||||
* executes cfunc on all the elements stored in the rot hash list
|
||||
*/
|
||||
int rot_list_foreach(int (*cfunc)(const struct rot_caps*, rig_ptr_t),rig_ptr_t data)
|
||||
{
|
||||
struct rot_list *p;
|
||||
int i;
|
||||
|
||||
if (!cfunc)
|
||||
return -RIG_EINVAL;
|
||||
|
||||
for (i=0; i<ROTLSTHASHSZ; i++) {
|
||||
for (p=rot_hash_table[i]; p; p=p->next)
|
||||
if ((*cfunc)(p->caps,data) == 0)
|
||||
return RIG_OK;
|
||||
}
|
||||
return RIG_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* rot_probe_all
|
||||
* called straight by rot_probe
|
||||
*/
|
||||
rot_model_t rot_probe_all(port_t *p)
|
||||
{
|
||||
int i;
|
||||
rot_model_t rot_model;
|
||||
|
||||
for (i=0; i<ROT_BACKEND_MAX && rot_backend_list[i].be_name; i++) {
|
||||
if (rot_backend_list[i].be_probe) {
|
||||
rot_model = (*rot_backend_list[i].be_probe)(p);
|
||||
if (rot_model != ROT_MODEL_NONE)
|
||||
return rot_model;
|
||||
}
|
||||
}
|
||||
return ROT_MODEL_NONE;
|
||||
}
|
||||
|
||||
|
||||
int rot_load_all_backends()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<ROT_BACKEND_MAX && rot_backend_list[i].be_name; i++) {
|
||||
rot_load_backend(rot_backend_list[i].be_name);
|
||||
}
|
||||
return RIG_OK;
|
||||
}
|
||||
|
||||
|
||||
#define MAXFUNCNAMELEN 64
|
||||
/*
|
||||
* rot_load_backend
|
||||
* Dynamically load a rot backend through dlopen mechanism
|
||||
*/
|
||||
int rot_load_backend(const char *be_name)
|
||||
{
|
||||
/*
|
||||
* determine PREFIX and POSTFIX values from configure script
|
||||
*/
|
||||
#ifdef __CYGWIN__
|
||||
# define PREFIX "cyghamlib-"
|
||||
# define POSTFIX ".dll"
|
||||
#else
|
||||
# define PREFIX "libhamlib-"
|
||||
# define POSTFIX ".la"
|
||||
#endif
|
||||
|
||||
lt_dlhandle be_handle;
|
||||
int (*be_init)(rig_ptr_t);
|
||||
int status;
|
||||
char libname[PATH_MAX];
|
||||
char initfname[MAXFUNCNAMELEN] = "init_";
|
||||
char probefname[MAXFUNCNAMELEN] = "probe_";
|
||||
int i;
|
||||
|
||||
/*
|
||||
* lt_dlinit may be called several times
|
||||
*/
|
||||
LTDL_SET_PRELOADED_SYMBOLS();
|
||||
|
||||
status = lt_dlinit();
|
||||
if (status) {
|
||||
rot_debug(RIG_DEBUG_ERR, "rot_backend_load: lt_dlinit for %s "
|
||||
"failed: %s\n", be_name, lt_dlerror());
|
||||
return -RIG_EINTERNAL;
|
||||
}
|
||||
|
||||
rot_debug(RIG_DEBUG_VERBOSE, "rot: loading backend %s\n",be_name);
|
||||
|
||||
/*
|
||||
* add hamlib directory here
|
||||
*/
|
||||
snprintf (libname, sizeof (libname), PREFIX"%s", be_name);
|
||||
|
||||
be_handle = lt_dlopenext (libname);
|
||||
|
||||
/*
|
||||
* external module not found? try dlopenself for backends
|
||||
* compiled in static
|
||||
*/
|
||||
if (!be_handle)
|
||||
be_handle = lt_dlopen (NULL);
|
||||
|
||||
if (!be_handle) {
|
||||
rot_debug(RIG_DEBUG_ERR, "rot: lt_dlopen(\"%s\") failed (%s)\n",
|
||||
libname, lt_dlerror());
|
||||
return -RIG_EINVAL;
|
||||
}
|
||||
|
||||
strncat(initfname, be_name, MAXFUNCNAMELEN);
|
||||
be_init = (int (*)(rig_ptr_t)) lt_dlsym (be_handle, initfname);
|
||||
if (!be_init) {
|
||||
rot_debug(RIG_DEBUG_ERR, "rot: dlsym(%s) failed (%s)\n",
|
||||
initfname, lt_dlerror());
|
||||
lt_dlclose(be_handle);
|
||||
return -RIG_EINVAL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* register probe function if present
|
||||
* NOTE: rot_load_backend might have been called upon a backend
|
||||
* not in rotlist.h! In this case, do nothing.
|
||||
*/
|
||||
for (i=0; i<ROT_BACKEND_MAX && rot_backend_list[i].be_name; i++) {
|
||||
if (!strncmp(be_name, rot_backend_list[i].be_name, 64)) {
|
||||
strncat(probefname, be_name, MAXFUNCNAMELEN);
|
||||
rot_backend_list[i].be_probe = (rot_model_t (*)(port_t *))
|
||||
lt_dlsym (be_handle, probefname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
status = (*be_init)(be_handle);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
533
src/rotator.c
Normal file
533
src/rotator.c
Normal file
@ -0,0 +1,533 @@
|
||||
/**
|
||||
* \file src/rotator.c
|
||||
* \brief Ham Radio Control Libraries interface
|
||||
* \author Stephane Fillod
|
||||
* \date 2000-2001
|
||||
*
|
||||
* Hamlib interface is a frontend implementing rotator wrapper functions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Hamlib Interface - main file
|
||||
* Copyright (c) 2000,2001 by Stephane Fillod and Frank Singleton
|
||||
*
|
||||
* $Id: rotator.c,v 1.1 2001-12-27 21:46:25 fillods Exp $
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
#include <hamlib/rotator.h>
|
||||
#include <serial.h>
|
||||
#include "rot_conf.h"
|
||||
|
||||
|
||||
#define DEFAULT_SERIAL_PORT "/dev/rotator"
|
||||
|
||||
/*
|
||||
* Data structure to track the opened rot (by rot_open)
|
||||
*/
|
||||
struct opened_rot_l {
|
||||
ROT *rot;
|
||||
struct opened_rot_l *next;
|
||||
};
|
||||
static struct opened_rot_l *opened_rot_list = { NULL };
|
||||
|
||||
/*
|
||||
* track which rot is opened (with rot_open)
|
||||
* needed at least for transceive mode
|
||||
*/
|
||||
static int add_opened_rot(ROT *rot)
|
||||
{
|
||||
struct opened_rot_l *p;
|
||||
p = (struct opened_rot_l *)malloc(sizeof(struct opened_rot_l));
|
||||
if (!p)
|
||||
return -RIG_ENOMEM;
|
||||
p->rot = rot;
|
||||
p->next = opened_rot_list;
|
||||
opened_rot_list = p;
|
||||
return RIG_OK;
|
||||
}
|
||||
|
||||
static int remove_opened_rot(ROT *rot)
|
||||
{
|
||||
struct opened_rot_l *p,*q;
|
||||
q = NULL;
|
||||
|
||||
for (p=opened_rot_list; p; p=p->next) {
|
||||
if (p->rot == rot) {
|
||||
if (q == NULL) {
|
||||
opened_rot_list = opened_rot_list->next;
|
||||
} else {
|
||||
q->next = p->next;
|
||||
}
|
||||
free(p);
|
||||
return RIG_OK;
|
||||
}
|
||||
q = p;
|
||||
}
|
||||
return -RIG_EINVAL; /* Not found in list ! */
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief execs cfunc() on each opened rot
|
||||
* \param cfunc The function to be executed on each rot
|
||||
* \param data Data pointer to be passed to cfunc()
|
||||
*
|
||||
* Calls cfunc() function for each opened rot.
|
||||
* The contents of the opened rot table
|
||||
* is processed in random order according to a function
|
||||
* pointed to by \a cfunc, whic is called with two arguments,
|
||||
* the first pointing to the #ROT handle, the second
|
||||
* to a data pointer \a data.
|
||||
* If \a data is not needed, then it can be set to NULL.
|
||||
* The processing of the opened rot table is stopped
|
||||
* when cfunc() returns 0.
|
||||
* \internal
|
||||
*
|
||||
* \return always RIG_OK.
|
||||
*/
|
||||
|
||||
int foreach_opened_rot(int (*cfunc)(ROT *, rig_ptr_t), rig_ptr_t data)
|
||||
{
|
||||
struct opened_rot_l *p;
|
||||
|
||||
for (p=opened_rot_list; p; p=p->next) {
|
||||
if ((*cfunc)(p->rot,data) == 0)
|
||||
return RIG_OK;
|
||||
}
|
||||
return RIG_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief allocate a new #ROT handle
|
||||
* \param rot_model The rot model for this new handle
|
||||
*
|
||||
* Allocates a new #ROT handle and initializes the associated data
|
||||
* for \a rot_model.
|
||||
*
|
||||
* \return a pointer to the #ROT handle otherwise NULL if memory allocation
|
||||
* failed or \a rot_model is unknown (e.g. backend autoload failed).
|
||||
*
|
||||
* \sa rot_cleanup(), rot_open()
|
||||
*/
|
||||
|
||||
ROT *rot_init(rot_model_t rot_model)
|
||||
{
|
||||
ROT *rot;
|
||||
const struct rot_caps *caps;
|
||||
struct rot_state *rs;
|
||||
int retcode;
|
||||
|
||||
rot_debug(RIG_DEBUG_VERBOSE,"rot:rot_init called \n");
|
||||
|
||||
rot_check_backend(rot_model);
|
||||
|
||||
caps = rot_get_caps(rot_model);
|
||||
if (!caps)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* okay, we've found it. Allocate some memory and set it to zeros,
|
||||
* 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;
|
||||
}
|
||||
|
||||
rot->caps = caps;
|
||||
|
||||
/*
|
||||
* populate the rot->state
|
||||
* TODO: read the Preferences here!
|
||||
*/
|
||||
|
||||
rs = &rot->state;
|
||||
|
||||
rs->comm_state = 0;
|
||||
rs->rotport.type.rig = caps->port_type; /* default from caps */
|
||||
strncpy(rs->rotport.pathname, DEFAULT_SERIAL_PORT, FILPATHLEN);
|
||||
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;
|
||||
rs->rotport.write_delay = caps->write_delay;
|
||||
rs->rotport.post_write_delay = caps->post_write_delay;
|
||||
|
||||
rs->rotport.timeout = caps->timeout;
|
||||
rs->rotport.retry = caps->retry;
|
||||
|
||||
rs->min_el = caps->min_el;
|
||||
rs->min_el = caps->min_el;
|
||||
rs->min_az = caps->min_az;
|
||||
rs->min_az = caps->min_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;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief open the communication to the rot
|
||||
* \param rot The #ROT handle of the radio to be opened
|
||||
*
|
||||
* Opens communication to a radio which \a ROT handle has been passed
|
||||
* by argument.
|
||||
*
|
||||
* \return RIG_OK if the operation has been sucessful, otherwise
|
||||
* a negative value if an error occured (in which case, cause is
|
||||
* set appropriately).
|
||||
*
|
||||
* \retval RIG_EINVAL \a rot is NULL or unconsistent.
|
||||
* \retval RIG_ENIMPL port type communication is not implemented yet.
|
||||
*
|
||||
* \sa rot_init(), rot_close()
|
||||
*/
|
||||
|
||||
int rot_open(ROT *rot)
|
||||
{
|
||||
const struct rot_caps *caps;
|
||||
struct rot_state *rs;
|
||||
int status;
|
||||
azimuth_t az;
|
||||
elevation_t el;
|
||||
|
||||
rot_debug(RIG_DEBUG_VERBOSE,"rot:rot_open called \n");
|
||||
|
||||
if (!rot || !rot->caps)
|
||||
return -RIG_EINVAL;
|
||||
|
||||
caps = rot->caps;
|
||||
rs = &rot->state;
|
||||
|
||||
if (rs->comm_state)
|
||||
return -RIG_EINVAL;
|
||||
|
||||
rs->rotport.fd = -1;
|
||||
|
||||
switch(rs->rotport.type.rig) {
|
||||
case RIG_PORT_SERIAL:
|
||||
status = serial_open(&rs->rotport);
|
||||
if (status != 0)
|
||||
return status;
|
||||
break;
|
||||
|
||||
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_NONE:
|
||||
case RIG_PORT_RPC:
|
||||
break; /* ez :) */
|
||||
|
||||
case RIG_PORT_NETWORK: /* not implemented yet! */
|
||||
return -RIG_ENIMPL;
|
||||
default:
|
||||
return -RIG_EINVAL;
|
||||
}
|
||||
|
||||
|
||||
add_opened_rot(rot);
|
||||
|
||||
rs->comm_state = 1;
|
||||
|
||||
/*
|
||||
* Maybe the backend has something to initialize
|
||||
* In case of failure, just close down and report error code.
|
||||
*/
|
||||
if (caps->rot_open != NULL) {
|
||||
status = caps->rot_open(rot);
|
||||
if (status != RIG_OK) {
|
||||
rot_close(rot);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* trigger state->current_az/current_el first retrieval
|
||||
*/
|
||||
rot_get_position(rot, &az, &el);
|
||||
|
||||
return RIG_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief close the communication to the rot
|
||||
* \param rot The #ROT handle of the radio to be closed
|
||||
*
|
||||
* Closes communication to a radio which \a ROT handle has been passed
|
||||
* by argument that was previously open with rot_open().
|
||||
*
|
||||
* \return RIG_OK if the operation has been sucessful, otherwise
|
||||
* a negative value if an error occured (in which case, cause is
|
||||
* set appropriately).
|
||||
*
|
||||
* \sa rot_cleanup(), rot_open()
|
||||
*/
|
||||
|
||||
int rot_close(ROT *rot)
|
||||
{
|
||||
const struct rot_caps *caps;
|
||||
struct rot_state *rs;
|
||||
|
||||
rot_debug(RIG_DEBUG_VERBOSE,"rot:rot_close called \n");
|
||||
|
||||
if (!rot || !rot->caps)
|
||||
return -RIG_EINVAL;
|
||||
|
||||
caps = rot->caps;
|
||||
rs = &rot->state;
|
||||
|
||||
if (!rs->comm_state)
|
||||
return -RIG_EINVAL;
|
||||
|
||||
/*
|
||||
* Let the backend say 73s to the rot.
|
||||
* and ignore the return code.
|
||||
*/
|
||||
if (caps->rot_close)
|
||||
caps->rot_close(rot);
|
||||
|
||||
|
||||
if (rs->rotport.fd != -1) {
|
||||
if (!rs->rotport.stream)
|
||||
fclose(rs->rotport.stream); /* this closes also fd */
|
||||
else
|
||||
close(rs->rotport.fd);
|
||||
rs->rotport.fd = -1;
|
||||
rs->rotport.stream = NULL;
|
||||
}
|
||||
|
||||
remove_opened_rot(rot);
|
||||
|
||||
rs->comm_state = 0;
|
||||
|
||||
return RIG_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief release a rot handle and free associated memory
|
||||
* \param rot The #ROT handle of the radio to be closed
|
||||
*
|
||||
* Releases a rot struct which port has eventualy been closed already
|
||||
* with rot_close().
|
||||
*
|
||||
* \return RIG_OK if the operation has been sucessful, otherwise
|
||||
* a negative value if an error occured (in which case, cause is
|
||||
* set appropriately).
|
||||
*
|
||||
* \sa rot_init(), rot_close()
|
||||
*/
|
||||
|
||||
int rot_cleanup(ROT *rot)
|
||||
{
|
||||
rot_debug(RIG_DEBUG_VERBOSE,"rot:rot_cleanup called \n");
|
||||
|
||||
if (!rot || !rot->caps)
|
||||
return -RIG_EINVAL;
|
||||
|
||||
/*
|
||||
* check if they forgot to close the rot
|
||||
*/
|
||||
if (rot->state.comm_state)
|
||||
rot_close(rot);
|
||||
|
||||
/*
|
||||
* basically free up the priv struct
|
||||
*/
|
||||
if (rot->caps->rot_cleanup)
|
||||
rot->caps->rot_cleanup(rot);
|
||||
|
||||
free(rot);
|
||||
|
||||
return RIG_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief set a rotator configuration parameter
|
||||
* \param rot The rot handle
|
||||
* \param token The parameter
|
||||
* \param val The value to set the parameter to
|
||||
*
|
||||
* Sets a configuration parameter.
|
||||
*
|
||||
* \return RIG_OK if the operation has been sucessful, otherwise
|
||||
* a negative value if an error occured (in which case, cause is
|
||||
* set appropriately).
|
||||
*
|
||||
* \sa rot_get_conf()
|
||||
*/
|
||||
int rot_set_conf(ROT *rot, token_t token, const char *val)
|
||||
{
|
||||
if (!rot || !rot->caps)
|
||||
return -RIG_EINVAL;
|
||||
|
||||
if (RIG_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
|
||||
* \param rot The rot handle
|
||||
* \param token The parameter
|
||||
* \param val The location where to store the value of config \a token
|
||||
*
|
||||
* Retrieves the value of a configuration paramter associated with \a token.
|
||||
*
|
||||
* \return RIG_OK if the operation has been sucessful, otherwise
|
||||
* a negative value if an error occured (in which case, cause is
|
||||
* set appropriately).
|
||||
*
|
||||
* \sa rot_set_conf()
|
||||
*/
|
||||
int rot_get_conf(ROT *rot, token_t token, char *val)
|
||||
{
|
||||
if (!rot || !rot->caps || !val)
|
||||
return -RIG_EINVAL;
|
||||
|
||||
if (RIG_IS_TOKEN_FRONTEND(token))
|
||||
return frontrot_get_conf(rot, token, val);
|
||||
|
||||
if (rot->caps->get_conf == NULL)
|
||||
return -RIG_ENAVAIL;
|
||||
|
||||
return rot->caps->get_conf(rot, token, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief set the azimuth and elevation of the rotator
|
||||
* \param rot The rot handle
|
||||
* \param azimuth The azimuth to set to
|
||||
* \param elevation The elevation to set to
|
||||
*
|
||||
* Sets the azimuth and elevation of the rotator.
|
||||
*
|
||||
* \return RIG_OK if the operation has been sucessful, otherwise
|
||||
* a negative value if an error occured (in which case, cause is
|
||||
* set appropriately).
|
||||
*
|
||||
* \sa rot_get_position()
|
||||
*/
|
||||
|
||||
int rot_set_position (ROT *rot, azimuth_t azimuth, elevation_t elevation)
|
||||
{
|
||||
const struct rot_caps *caps;
|
||||
|
||||
if (!rot || !rot->caps)
|
||||
return -RIG_EINVAL;
|
||||
|
||||
caps = rot->caps;
|
||||
|
||||
if (caps->set_position == NULL)
|
||||
return -RIG_ENAVAIL;
|
||||
|
||||
return caps->set_position(rot, azimuth, elevation);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief get the azimuth and elevation of the rotator
|
||||
* \param rot The rot handle
|
||||
* \param azimuth The location where to store the current azimuth
|
||||
* \param elevation The location where to store the current elevation
|
||||
*
|
||||
* Retrieves the current azimuth and elevation of the rotator.
|
||||
*
|
||||
* \return RIG_OK if the operation has been sucessful, otherwise
|
||||
* a negative value if an error occured (in which case, cause is
|
||||
* set appropriately).
|
||||
*
|
||||
* \sa rot_set_position()
|
||||
*/
|
||||
|
||||
int rot_get_position (ROT *rot, azimuth_t *azimuth, elevation_t *elevation)
|
||||
{
|
||||
const struct rot_caps *caps;
|
||||
|
||||
if (!rot || !rot->caps || !azimuth || !elevation)
|
||||
return -RIG_EINVAL;
|
||||
|
||||
caps = rot->caps;
|
||||
|
||||
if (caps->get_position == NULL)
|
||||
return -RIG_ENAVAIL;
|
||||
|
||||
return caps->get_position(rot, azimuth, elevation);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief get general information from the rotator
|
||||
* \param rot The rot handle
|
||||
*
|
||||
* Retrieves some general information from the rotator.
|
||||
* This can include firmware revision, exact model name, or just nothing.
|
||||
*
|
||||
* \return a pointer to static memory containing the ASCIIZ string
|
||||
* if the operation has been sucessful, otherwise NULL if an error occured
|
||||
* or get_info not part of capabilities.
|
||||
*/
|
||||
const char* rot_get_info(ROT *rot)
|
||||
{
|
||||
if (!rot || !rot->caps)
|
||||
return NULL;
|
||||
|
||||
if (rot->caps->get_info == NULL)
|
||||
return NULL;
|
||||
|
||||
return rot->caps->get_info(rot);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user