Initial support for CM108 GPIO contorl of PTT

Signed-off-by: Nate Bargmann <n0nb@n0nb.us>
Hamlib-1.2.15
Andrew Errington 2012-01-09 08:22:59 +09:00 zatwierdzone przez Nate Bargmann
rodzic 4324d9ea98
commit 1a77ef9eb9
11 zmienionych plików z 406 dodań i 10 usunięć

Wyświetl plik

@ -77,7 +77,7 @@ AC_CHECK_HEADERS([alloca.h argz.h malloc.h memory.h string.h strings.h])
AC_CHECK_HEADERS([stdlib.h values.h rpc/rpc.h rpc/rpcent.h net/errno.h])
AC_CHECK_HEADERS([fcntl.h sys/ioctl.h sys/time.h sys/param.h unistd.h getopt.h errno.h])
AC_CHECK_HEADERS([sys/ioccom.h sgtty.h term.h termio.h termios.h])
AC_CHECK_HEADERS([linux/ppdev.h linux/parport.h linux/ioctl.h])
AC_CHECK_HEADERS([linux/ppdev.h linux/parport.h linux/ioctl.h linux/hidraw.h])
AC_CHECK_HEADERS([dev/ppbus/ppi.h dev/ppbus/ppbconf.h])
AC_CHECK_HEADERS([sys/socket.h netinet/in.h netdb.h arpa/inet.h ws2tcpip.h])

Wyświetl plik

@ -171,7 +171,8 @@ typedef enum rig_port_e {
RIG_PORT_RPC, /*!< RPC wrapper */
RIG_PORT_PARALLEL, /*!< Parallel port */
RIG_PORT_USB, /*!< USB port */
RIG_PORT_UDP_NETWORK /*!< UDP Network socket type */
RIG_PORT_UDP_NETWORK, /*!< UDP Network socket type */
RIG_PORT_CM108 /*!< CM108 GPIO */
} rig_port_t;
/**
@ -391,7 +392,8 @@ typedef enum {
RIG_DCD_SERIAL_DSR, /*!< DCD status from serial DSR signal */
RIG_DCD_SERIAL_CTS, /*!< DCD status from serial CTS signal */
RIG_DCD_SERIAL_CAR, /*!< DCD status from serial CD signal */
RIG_DCD_PARALLEL /*!< DCD status from parallel port pin */
RIG_DCD_PARALLEL, /*!< DCD status from parallel port pin */
RIG_DCD_CM108 /*!< DCD status from CM108 vol dn pin */
} dcd_type_t;
@ -415,7 +417,8 @@ typedef enum {
RIG_PTT_SERIAL_DTR, /*!< PTT control through serial DTR signal */
RIG_PTT_SERIAL_RTS, /*!< PTT control through serial RTS signal */
RIG_PTT_PARALLEL, /*!< PTT control through parallel port */
RIG_PTT_RIG_MICDATA /*!< Legacy PTT, supports RIG_PTT_ON_MIC/RIG_PTT_ON_DATA */
RIG_PTT_RIG_MICDATA, /*!< Legacy PTT, supports RIG_PTT_ON_MIC/RIG_PTT_ON_DATA */
RIG_PTT_CM108 /*!< PTT control through CM108 GPIO pin */
} ptt_type_t;
/**
@ -1338,6 +1341,7 @@ typedef struct {
int retry; /*!< Maximum number of retries, 0 to disable */
char pathname[FILPATHLEN]; /*!< Port pathname */
int ptt_bitnum; /*< Bit number for CM108 GPIO PTT */
union {
struct {
int rate; /*!< Serial baud rate */

Wyświetl plik

@ -1,7 +1,8 @@
INCLUDES = @INCLUDES@ @INCLTDL@
RIGSRC = rig.c serial.c misc.c register.c event.c cal.c conf.c tones.c \
rotator.c locator.c rot_reg.c rot_conf.c iofunc.c ext.c \
mem.c settings.c parallel.c usb_port.c debug.c network.c
mem.c settings.c parallel.c usb_port.c debug.c network.c \
cm108.c
lib_LTLIBRARIES = libhamlib.la
libhamlib_la_SOURCES = $(RIGSRC)
@ -12,5 +13,5 @@ libhamlib_la_LIBADD = @LIBLTDL@ $(top_builddir)/lib/libmisc.la \
noinst_HEADERS = event.h misc.h serial.h iofunc.h cal.h tones.h \
rot_conf.h token.h idx_builtin.h register.h par_nt.h \
parallel.h usb_port.h network.h
parallel.h usb_port.h network.h cm108.h

264
src/cm108.c 100644
Wyświetl plik

@ -0,0 +1,264 @@
/*
* Hamlib Interface - CM108 HID communication low-level support
* Copyright (c) 2000-2010 by Stephane Fillod
* Copyright (c) 2011 by Andrew Errington
* CM108 detection code Copyright (c) Thomas Sailer used with permission
*
* 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.
*
*/
/**
* \addtogroup rig_internal
* @{
*/
/**
* \brief CM108 GPIO
* \file cm108.c
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#include "par_nt.h"
#endif
#ifdef HAVE_WINIOCTL_H
#include <winioctl.h>
#endif
#ifdef HAVE_WINBASE_H
#include <winbase.h>
#endif
#ifdef HAVE_LINUX_HIDRAW_H
#include <linux/hidraw.h>
#endif
#include "hamlib/rig.h"
#include "cm108.h"
/**
* \brief Open CM108 HID port (/dev/hidrawX)
* \param port
* \return file descriptor
*/
int cm108_open(hamlib_port_t *port)
{
int fd;
rig_debug(RIG_DEBUG_VERBOSE,"cm108:cm108_open called \n");
if (!port->pathname)
return -RIG_EINVAL;
fd = open(port->pathname, O_RDWR);
if (fd < 0) {
rig_debug(RIG_DEBUG_ERR, "cm108:Opening device \"%s\": %s\n", port->pathname, strerror(errno));
return -RIG_EIO;
}
#ifdef HAVE_LINUX_HIDRAW_H
// CM108 detection copied from Thomas Sailer's soundmodem code
rig_debug(RIG_DEBUG_VERBOSE,"cm108:Checking for cm108 (or compatible) device \n");
struct hidraw_devinfo hiddevinfo;
if (!ioctl(fd, HIDIOCGRAWINFO, &hiddevinfo)
&&
(
(hiddevinfo.vendor == 0x0d8c // CM108/109/119
&& hiddevinfo.product >= 0x0008
&& hiddevinfo.product <= 0x000f
)
||
(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
{
rig_debug(RIG_DEBUG_VERBOSE,"cm108:No cm108 (or compatible) device detected \n");
return -RIG_EINVAL;
}
#endif
port->fd = fd;
return fd;
}
/**
* \brief Close CM108 HID port
* \param port
*/
int cm108_close(hamlib_port_t *port)
{
rig_debug(RIG_DEBUG_VERBOSE,"cm108:cm108_close called \n");
return close(port->fd);
}
/**
* \brief Set or unset Push to talk bit on CM108 GPIO
* \param p
* \param pttx RIG_PTT_ON --> Set PTT
* \return RIG_OK or < 0 error
*/
int cm108_ptt_set(hamlib_port_t *p, ptt_t pttx)
{
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.
switch(p->type.ptt) {
case RIG_PTT_CM108:
{
int status;
// Build a packet for CM108 HID to turn GPIO bit on or off.
// 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
rig_debug(RIG_DEBUG_VERBOSE,"cm108:cm108_ptt_set bit number %d to state %d\n",
p->ptt_bitnum, (pttx == RIG_PTT_ON) ? 1 : 0);
char out_rep[] = {
0x00, // report number
// HID output report
0x00,
(pttx == RIG_PTT_ON) ? (1 << p->ptt_bitnum) : 0, // set GPIO
1 << p->ptt_bitnum, // Data direction register (1=output)
0x00
};
ssize_t nw;
if (p->fd == -1)
return -RIG_EINVAL;
// Send the HID packet
nw = write(p->fd, out_rep, sizeof(out_rep));
if (nw < 0) {
status = -RIG_EIO;
}
return RIG_OK;
}
default:
rig_debug(RIG_DEBUG_ERR,"Unsupported PTT type %d\n",
p->type.ptt);
return -RIG_EINVAL;
}
return RIG_OK;
}
/**
* \brief Get state of Push to Talk from CM108 GPIO
* \param p
* \param pttx return value (must be non NULL)
* \return RIG_OK or < 0 error
*/
int cm108_ptt_get(hamlib_port_t *p, ptt_t *pttx)
{
rig_debug(RIG_DEBUG_VERBOSE,"cm108:cm108_ptt_get called \n");
switch(p->type.ptt) {
case RIG_PTT_CM108:
{
unsigned char ctl;
int status;
return -RIG_ENIMPL;
return status;
}
default:
rig_debug(RIG_DEBUG_ERR,"Unsupported PTT type %d\n",
p->type.ptt);
return -RIG_ENAVAIL;
}
return RIG_OK;
}
/**
* \brief get Data Carrier Detect (squelch) from CM108 GPIO
* \param p
* \param dcdx return value (Must be non NULL)
* \return RIG_OK or < 0 error
*/
int cm108_dcd_get(hamlib_port_t *p, dcd_t *dcdx)
{
rig_debug(RIG_DEBUG_VERBOSE,"cm108:cm108_dcd_get called \n");
// 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
// in HID messages from the CM108 device, but I am not sure how
// to query this state on demand.
switch(p->type.dcd) {
case RIG_DCD_CM108:
{
unsigned char reg;
int status;
return -RIG_ENIMPL;
return status;
}
default:
rig_debug(RIG_DEBUG_ERR,"Unsupported DCD type %d\n",
p->type.dcd);
return -RIG_ENAVAIL;
}
return RIG_OK;
}
/** @} */

49
src/cm108.h 100644
Wyświetl plik

@ -0,0 +1,49 @@
/*
* Hamlib Interface - CM108 GPIO communication header
* Copyright (c) 2000-2003 by Frank Singleton
* Copyright (c) 2000-2010 by Stephane Fillod
* Copyright (c) 2011 by Andrew Errington
*
* 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 _CM108_H
#define _CM108_H 1
#include <hamlib/rig.h>
#include "iofunc.h"
__BEGIN_DECLS
/* Hamlib internal use, see rig.c */
int cm108_open(hamlib_port_t *p);
int cm108_close(hamlib_port_t *p);
int cm108_ptt_set(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);
extern HAMLIB_EXPORT(int) cm108_write_data(hamlib_port_t *p, unsigned char data);
extern HAMLIB_EXPORT(int) cm108_write_control(hamlib_port_t *p, 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_unlock(hamlib_port_t *p);
__END_DECLS
#endif /* _CM108_H */

Wyświetl plik

@ -80,15 +80,19 @@ static const struct confparams frontend_cfg_params[] = {
},
{ TOK_PTT_TYPE, "ptt_type", "PTT type",
"Push-To-Talk interface type override",
"RIG", RIG_CONF_COMBO, { .c = {{ "RIG", "DTR", "RTS", "Parallel", "None", NULL }} }
"RIG", RIG_CONF_COMBO, { .c = {{ "RIG", "DTR", "RTS", "Parallel", "CM108", "None", NULL }} }
},
{ TOK_PTT_PATHNAME, "ptt_pathname", "PTT path name",
"Path name to the device file of the Push-To-Talk",
"/dev/rig", RIG_CONF_STRING,
},
{ TOK_PTT_BITNUM, "ptt_bitnum", "PTT bit [0-7]",
"Push-To-Talk GPIO bit number",
"2", RIG_CONF_NUMERIC, { .n = { 0, 7, 1 } }
},
{ TOK_DCD_TYPE, "dcd_type", "DCD type",
"Data Carrier Detect (or squelch) interface type override",
"RIG", RIG_CONF_COMBO, { .c = {{ "RIG", "DSR", "CTS", "CD", "Parallel", "None", NULL }} }
"RIG", RIG_CONF_COMBO, { .c = {{ "RIG", "DSR", "CTS", "CD", "Parallel", "CM108", "None", NULL }} }
},
{ TOK_DCD_PATHNAME, "dcd_pathname", "DCD path name",
"Path name to the device file of the Data Carrier Detect (or squelch)",
@ -290,6 +294,8 @@ static int frontend_set_conf(RIG *rig, token_t token, const char *val)
rs->pttport.type.ptt = RIG_PTT_SERIAL_RTS;
else if (!strcmp(val, "Parallel"))
rs->pttport.type.ptt = RIG_PTT_PARALLEL;
else if (!strcmp(val, "CM108"))
rs->pttport.type.ptt = RIG_PTT_CM108;
else if (!strcmp(val, "None"))
rs->pttport.type.ptt = RIG_PTT_NONE;
else
@ -300,6 +306,13 @@ static int frontend_set_conf(RIG *rig, token_t token, const char *val)
strncpy(rs->pttport.pathname, val, FILPATHLEN-1);
break;
case TOK_PTT_BITNUM:
if (1 != sscanf(val, "%d", &val_i)){
return -RIG_EINVAL;//value format error
}
rs->pttport.ptt_bitnum=val_i;
break;
case TOK_DCD_TYPE:
if (!strcmp(val, "RIG"))
rs->dcdport.type.dcd = RIG_DCD_RIG;
@ -311,6 +324,8 @@ static int frontend_set_conf(RIG *rig, token_t token, const char *val)
rs->dcdport.type.dcd = RIG_DCD_SERIAL_CAR;
else if (!strcmp(val, "Parallel"))
rs->dcdport.type.dcd = RIG_DCD_PARALLEL;
else if (!strcmp(val, "CM108"))
rs->dcdport.type.dcd = RIG_DCD_CM108;
else if (!strcmp(val, "None"))
rs->dcdport.type.dcd = RIG_DCD_NONE;
else

Wyświetl plik

@ -52,7 +52,7 @@
#include "parallel.h"
#include "usb_port.h"
#include "network.h"
#include "cm108.h"
/**
* \brief Open a hamlib_port based on its rig port type
@ -101,6 +101,12 @@ int HAMLIB_API port_open(hamlib_port_t *p)
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)
@ -153,6 +159,9 @@ int HAMLIB_API port_close(hamlib_port_t *p, rig_port_t port_type)
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;

Wyświetl plik

@ -66,6 +66,7 @@
#include "usb_port.h"
#include "network.h"
#include "event.h"
#include "cm108.h"
/**
* \brief Hamlib release number
@ -108,6 +109,23 @@ const char hamlib_copyright[231] = /* hamlib 1.2 ABI specifies 231 bytes */
#define DEFAULT_PARALLEL_PORT "/dev/parport0"
#endif
#if defined(WIN32) && !defined(__CYGWIN__)
#define DEFAULT_CM108_PORT "fixme"
#elif BSD
#define DEFAULT_CM108_PORT "fixme"
#else
#define DEFAULT_CM108_PORT "/dev/hidraw0"
#endif
#if defined(WIN32) && !defined(__CYGWIN__)
#define DEFAULT_CM108_PTT_BITNUM "fixme"
#elif BSD
#define DEFAULT_CM108_PTT_BITNUM "fixme"
#else
#define DEFAULT_CM108_PTT_BITNUM 2
#endif
#define CHECK_RIG_ARG(r) (!(r) || !(r)->caps || !(r)->state.comm_state)
/*
@ -304,6 +322,14 @@ RIG * HAMLIB_API rig_init(rig_model_t rig_model)
strncpy(rs->rigport.pathname, DEFAULT_PARALLEL_PORT, FILPATHLEN - 1);
break;
/* Adding support for CM108 GPIO. This is compatible with CM108 series
* USB audio chips from CMedia and SSS1623 series USB audio chips from 3S
*/
case RIG_PORT_CM108:
strncpy(rs->rigport.pathname, DEFAULT_CM108_PORT, FILPATHLEN);
rs->rigport.ptt_bitnum = DEFAULT_CM108_PTT_BITNUM;
break;
case RIG_PORT_NETWORK:
case RIG_PORT_UDP_NETWORK:
strncpy(rs->rigport.pathname, "127.0.0.1:4532", FILPATHLEN - 1);
@ -500,6 +526,14 @@ int HAMLIB_API rig_open(RIG *rig)
else
par_ptt_set(&rs->pttport, RIG_PTT_OFF);
break;
case RIG_PTT_CM108:
rs->pttport.fd = cm108_open(&rs->pttport);
if (rs->pttport.fd < 0)
rig_debug(RIG_DEBUG_ERR, "Cannot open PTT device \"%s\"\n",
rs->pttport.pathname);
else
cm108_ptt_set(&rs->pttport, RIG_PTT_OFF);
break;
default:
rig_debug(RIG_DEBUG_ERR, "Unsupported PTT type %d\n",
rs->pttport.type.ptt);
@ -628,6 +662,10 @@ int HAMLIB_API rig_close(RIG *rig)
par_ptt_set(&rs->pttport, RIG_PTT_OFF);
port_close(&rs->pttport, RIG_PORT_PARALLEL);
break;
case RIG_PTT_CM108:
cm108_ptt_set(&rs->pttport, RIG_PTT_OFF);
port_close(&rs->pttport, RIG_PORT_CM108);
break;
default:
rig_debug(RIG_DEBUG_ERR, "Unsupported PTT type %d\n",
rs->pttport.type.ptt);
@ -1173,6 +1211,9 @@ int HAMLIB_API rig_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt)
case RIG_PTT_PARALLEL:
return par_ptt_set(&rig->state.pttport, ptt);
case RIG_PTT_CM108:
return cm108_ptt_set(&rig->state.pttport, ptt);
case RIG_PTT_NONE:
return -RIG_ENAVAIL; /* not available */
default:
@ -1252,6 +1293,12 @@ int HAMLIB_API rig_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt)
return par_ptt_get(&rig->state.pttport, ptt);
case RIG_PTT_CM108:
if (caps->get_ptt)
return caps->get_ptt(rig, vfo, ptt);
return cm108_ptt_get(&rig->state.pttport, ptt);
case RIG_PTT_NONE:
return -RIG_ENAVAIL; /* not available */

Wyświetl plik

@ -85,7 +85,8 @@
#define TOK_DCD_TYPE TOKEN_FRONTEND(32)
/** \brief DCD pathname override */
#define TOK_DCD_PATHNAME TOKEN_FRONTEND(33)
/** \brief CM108 GPIO bit number for PTT */
#define TOK_PTT_BITNUM TOKEN_FRONTEND(34)
/*
* rig specific tokens
*/

Wyświetl plik

@ -163,6 +163,8 @@ int main (int argc, char *argv[])
ptt_type = RIG_PTT_SERIAL_RTS;
else if (!strcmp(optarg, "PARALLEL"))
ptt_type = RIG_PTT_PARALLEL;
else if (!strcmp(optarg, "CM108"))
ptt_type = RIG_PTT_CM108;
else if (!strcmp(optarg, "NONE"))
ptt_type = RIG_PTT_NONE;
else
@ -183,6 +185,8 @@ int main (int argc, char *argv[])
dcd_type = RIG_DCD_SERIAL_CAR;
else if (!strcmp(optarg, "PARALLEL"))
dcd_type = RIG_DCD_PARALLEL;
else if (!strcmp(optarg, "CM108"))
dcd_type = RIG_DCD_CM108;
else if (!strcmp(optarg, "NONE"))
dcd_type = RIG_DCD_NONE;
else

Wyświetl plik

@ -195,6 +195,8 @@ int main (int argc, char *argv[])
ptt_type = RIG_PTT_SERIAL_RTS;
else if (!strcmp(optarg, "PARALLEL"))
ptt_type = RIG_PTT_PARALLEL;
else if (!strcmp(optarg, "CM108"))
ptt_type = RIG_PTT_CM108;
else if (!strcmp(optarg, "NONE"))
ptt_type = RIG_PTT_NONE;
else