wavecom/sysmocom: Directly send GPS/AIS via UDP to gpsd

This avoids having to have another client program which then passes
messages from gsmd into gpsd.  Rather, gpsd can directly receive the
messages via UDP.
This commit is contained in:
Harald Welte 2013-03-14 20:20:50 +01:00
parent 06253f3620
commit 805406e9fb
1 changed files with 64 additions and 2 deletions

View File

@ -26,6 +26,10 @@
#include <errno.h>
#include <stdint.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "gsmd.h"
#include <gsmd/gsmd.h>
@ -37,6 +41,13 @@
#include <gsmd/vendorplugin.h>
#include <gsmd/unsolicited.h>
#define AISGPS_UDP_HOST "127.0.0.1"
#define GPS_UDP_PORT 12345
#define AIS_UDP_PORT 12346
static int gps_udp_fd = -1;
static int ais_udp_fd = -1;
struct cell_info_fsq {
uint8_t cur;
uint8_t full;
@ -144,11 +155,39 @@ struct gsmd_ucmd *usock_build_gps(uint8_t subtype, const char *data, uint16_t le
return ucmd;
}
const char *crlf = "\r\n";
static int send_crlf(int fd, const char *buf, int len)
{
struct iovec iov[2];
struct msghdr mh;
if (len <= strlen(AIS_PFX))
return 0;
len -= strlen(AIS_PFX);
buf += strlen(AIS_PFX);
iov[0].iov_base = (void *) buf;
iov[0].iov_len = len;
iov[1].iov_base = (void *) crlf;
iov[1].iov_len = strlen(crlf);
memset(&mh, 0, sizeof(mh));
mh.msg_iov = iov;
mh.msg_iovlen = ARRAY_SIZE(iov);
return sendmsg(fd, &mh, MSG_DONTWAIT);
}
static int sgps_parse(const char *buf, int len, const char *param,
struct gsmd *gsmd)
{
struct gsmd_ucmd *ucmd = usock_build_gps(GSMD_EVT_GPS, buf, len);
struct gsmd_ucmd *ucmd;
send_crlf(gps_udp_fd, buf, len);
ucmd = usock_build_gps(GSMD_EVT_GPS, buf, len);
if (!ucmd)
return -ENOMEM;
@ -161,8 +200,11 @@ static int sais_parse(const char *buf, int len, const char *param,
struct gsmd *gsmd)
{
struct gsmd_ucmd *ucmd = usock_build_gps(GSMD_EVT_AIS, buf, len);
struct gsmd_ucmd *ucmd;
send_crlf(ais_udp_fd, buf, len);
ucmd = usock_build_gps(GSMD_EVT_AIS, buf, len);
if (!ucmd)
return -ENOMEM;
@ -187,6 +229,26 @@ static int wavecom_initsettings(struct gsmd *g)
{
int rc = 0;
struct gsmd_atcmd *cmd;
struct sockaddr_in sin;
gps_udp_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
ais_udp_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (gps_udp_fd < 0 || ais_udp_fd < 0)
return -1;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
inet_aton(AISGPS_UDP_HOST, &sin.sin_addr);
sin.sin_port = htons(GPS_UDP_PORT);
rc = connect(gps_udp_fd, (struct sockaddr *)&sin, sizeof(sin));
if (rc < 0)
return rc;
sin.sin_port = htons(AIS_UDP_PORT);
rc = connect(ais_udp_fd, (struct sockaddr *)&sin, sizeof(sin));
if (rc < 0)
return rc;
/* use +WREGC to enter "spy mode" (no transmit / registration) */
rc |= gsmd_simplecmd(g, "AT+WREGC=0");