diff options
author | Harald Welte <laforge@gnumonks.org> | 2013-03-14 20:20:50 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2013-03-14 20:20:50 +0100 |
commit | 805406e9fbb38f45a2ecea94ca58dbe94509c36f (patch) | |
tree | a119c69faf19aaa2f5346bf6ed5221bbfc167887 | |
parent | 06253f362045c792baaf1430200c8964885d13a5 (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.
-rw-r--r-- | src/gsmd/vendor_wavecom.c | 66 |
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"); |