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 /src/gsmd | |
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.
Diffstat (limited to 'src/gsmd')
-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"); |