From 805406e9fbb38f45a2ecea94ca58dbe94509c36f Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 14 Mar 2013 20:20:50 +0100 Subject: 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. --- src/gsmd/vendor_wavecom.c | 66 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file 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 #include +#include +#include +#include + #include "gsmd.h" #include @@ -37,6 +41,13 @@ #include #include +#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"); -- cgit v1.2.3