summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2013-03-14 20:20:50 +0100
committerHarald Welte <laforge@gnumonks.org>2013-03-14 20:20:50 +0100
commit805406e9fbb38f45a2ecea94ca58dbe94509c36f (patch)
treea119c69faf19aaa2f5346bf6ed5221bbfc167887 /src
parent06253f362045c792baaf1430200c8964885d13a5 (diff)
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.
Diffstat (limited to 'src')
-rw-r--r--src/gsmd/vendor_wavecom.c66
1 files changed, 64 insertions, 2 deletions
diff --git a/src/gsmd/vendor_wavecom.c b/src/gsmd/vendor_wavecom.c
index 1331053..883ea39 100644
--- a/src/gsmd/vendor_wavecom.c
+++ b/src/gsmd/vendor_wavecom.c
@@ -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");
personal git repositories of Harald Welte. Your mileage may vary