diff options
Diffstat (limited to 'dynamic-layers/openembedded-layer')
-rw-r--r-- | dynamic-layers/openembedded-layer/recipes-devtools/android-tools/android-tools-adbd-cmdline.bb | 17 | ||||
-rw-r--r-- | dynamic-layers/openembedded-layer/recipes-devtools/android-tools/android-tools-adbd-cmdline/50-adbd-cmdline.conf | 6 | ||||
-rw-r--r-- | dynamic-layers/openembedded-layer/recipes-devtools/android-tools/android-tools-conf-configfs/qcom/android-gadget-setup.machine | 1 | ||||
-rw-r--r-- | dynamic-layers/openembedded-layer/recipes-navigation/gpsd/gpsd-3.23.1/0001-Introduce-Qualcomm-PDS-service-support.patch (renamed from dynamic-layers/openembedded-layer/recipes-navigation/gpsd/gpsd/0001-Introduce-Qualcomm-PDS-service-support.patch) | 460 | ||||
-rw-r--r-- | dynamic-layers/openembedded-layer/recipes-navigation/gpsd/gpsd-3.24/0001-Introduce-Qualcomm-PDS-service-support.patch | 640 | ||||
-rw-r--r-- | dynamic-layers/openembedded-layer/recipes-navigation/gpsd/gpsd_%.bbappend | 9 |
6 files changed, 950 insertions, 183 deletions
diff --git a/dynamic-layers/openembedded-layer/recipes-devtools/android-tools/android-tools-adbd-cmdline.bb b/dynamic-layers/openembedded-layer/recipes-devtools/android-tools/android-tools-adbd-cmdline.bb new file mode 100644 index 0000000..482109a --- /dev/null +++ b/dynamic-layers/openembedded-layer/recipes-devtools/android-tools/android-tools-adbd-cmdline.bb @@ -0,0 +1,17 @@ +DESCRIPTION = "An override for adbd unit - start adbd depending on the kernel command line" +SECTION = "console/utils" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +SRC_URI = " \ + file://50-adbd-cmdline.conf \ +" + +do_install() { + install -d ${D}${systemd_unitdir}/system/android-tools-adbd.service.d + install -m 0644 ${WORKDIR}/50-adbd-cmdline.conf ${D}${systemd_unitdir}/system/android-tools-adbd.service.d +} + +FILES:${PN} += " \ + ${systemd_unitdir}/system/ \ +" diff --git a/dynamic-layers/openembedded-layer/recipes-devtools/android-tools/android-tools-adbd-cmdline/50-adbd-cmdline.conf b/dynamic-layers/openembedded-layer/recipes-devtools/android-tools/android-tools-adbd-cmdline/50-adbd-cmdline.conf new file mode 100644 index 0000000..b1613e0 --- /dev/null +++ b/dynamic-layers/openembedded-layer/recipes-devtools/android-tools/android-tools-adbd-cmdline/50-adbd-cmdline.conf @@ -0,0 +1,6 @@ +[Unit] +# Clear all conditions +ConditionPathExists= +# And start if kernel adbd argument is provided or if the file exists +ConditionPathExists=|/var/usb-debugging-enabled +ConditionKernelCommandLine=|adbd diff --git a/dynamic-layers/openembedded-layer/recipes-devtools/android-tools/android-tools-conf-configfs/qcom/android-gadget-setup.machine b/dynamic-layers/openembedded-layer/recipes-devtools/android-tools/android-tools-conf-configfs/qcom/android-gadget-setup.machine index 37f26bb..09ca8d5 100644 --- a/dynamic-layers/openembedded-layer/recipes-devtools/android-tools/android-tools-conf-configfs/qcom/android-gadget-setup.machine +++ b/dynamic-layers/openembedded-layer/recipes-devtools/android-tools/android-tools-conf-configfs/qcom/android-gadget-setup.machine @@ -2,3 +2,4 @@ manufacturer=Qualcomm model=`hostname` androidserial="$(sed -n -e '/androidboot.serialno/ s/.*androidboot.serialno=\([^ ]*\).*/\1/gp ' /proc/cmdline)" [ -n "$androidserial" ] && serial="$androidserial" +true diff --git a/dynamic-layers/openembedded-layer/recipes-navigation/gpsd/gpsd/0001-Introduce-Qualcomm-PDS-service-support.patch b/dynamic-layers/openembedded-layer/recipes-navigation/gpsd/gpsd-3.23.1/0001-Introduce-Qualcomm-PDS-service-support.patch index b502fae..6df450b 100644 --- a/dynamic-layers/openembedded-layer/recipes-navigation/gpsd/gpsd/0001-Introduce-Qualcomm-PDS-service-support.patch +++ b/dynamic-layers/openembedded-layer/recipes-navigation/gpsd/gpsd-3.23.1/0001-Introduce-Qualcomm-PDS-service-support.patch @@ -1,4 +1,4 @@ -From 3f46e63ff08afba0ad532d4cac1957499769dc69 Mon Sep 17 00:00:00 2001 +From 0f0a1495b3b2ae9da09ea1a05510492bae05a928 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson <bjorn.andersson@linaro.org> Date: Wed, 4 Apr 2018 04:29:09 +0000 Subject: [PATCH] Introduce Qualcomm PDS service support @@ -33,33 +33,35 @@ string "any". Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> Signed-off-by: Aníbal Limón <anibal.limon@linaro.org> --- - SConscript | 10 ++ - driver_pds.c | 325 +++++++++++++++++++++++++++++++++++++++++++++++++ - driver_pds.h | 20 +++ - drivers.c | 5 + - gpsd.h | 2 + - libgpsd_core.c | 15 ++- - 6 files changed, 376 insertions(+), 1 deletion(-) - create mode 100644 driver_pds.c - create mode 100644 driver_pds.h + SConscript | 11 ++ + drivers/driver_pds.c | 406 +++++++++++++++++++++++++++++++++++++++++++ + drivers/drivers.c | 5 + + gpsd/libgpsd_core.c | 16 +- + include/driver_pds.h | 20 +++ + include/gpsd.h | 9 + + man/gpsd.adoc | 8 + + 7 files changed, 474 insertions(+), 1 deletion(-) + create mode 100644 drivers/driver_pds.c + create mode 100644 include/driver_pds.h -diff --git a/SConscript b/SConstruct -index 33e0ff326..d4ae81979 100644 +diff --git a/SConscript b/SConscript +index e3fed4c27..cae23de9c 100644 --- a/SConscript +++ b/SConscript -@@ -192,6 +192,7 @@ boolopts = ( +@@ -315,6 +315,8 @@ boolopts = ( ("tripmate", True, "DeLorme TripMate support"), ("tsip", True, "Trimble TSIP support"), ("ublox", True, "u-blox Protocol support"), -+ ("pds", True, "Qualcomm PDS support"), ++ ("pds", sys.platform.startswith('linux'), ++ "Qualcomm PDS support"), # Non-GPS protocols ("aivdm", True, "AIVDM support"), ("gpsclock", True, "GPSClock support"), -@@ -977,6 +978,14 @@ else: +@@ -1156,6 +1158,14 @@ if not cleaning and not helping: announce("You do not have kernel CANbus available.") config.env["nmea2000"] = False -+ if config.CheckHeader(["bits/sockaddr.h", "linux/qrtr.h"]): ++ if config.CheckHeader(["linux/qrtr.h"]): + confdefs.append("#define HAVE_LINUX_QRTR_H 1\n") + announce("You have kernel QRTR available.") + else: @@ -70,7 +72,7 @@ index 33e0ff326..d4ae81979 100644 # check for C11 or better, and __STDC__NO_ATOMICS__ is not defined # before looking for stdatomic.h if ((config.CheckC11() and -@@ -1655,6 +1664,7 @@ libgpsd_sources = [ +@@ -1684,6 +1694,7 @@ libgpsd_sources = [ "drivers/driver_nmea0183.c", "drivers/driver_nmea2000.c", "drivers/driver_oncore.c", @@ -80,10 +82,19 @@ index 33e0ff326..d4ae81979 100644 "drivers/drivers.c", diff --git a/drivers/driver_pds.c b/drivers/driver_pds.c new file mode 100644 -index 000000000..734b40f83 +index 000000000..2ac77ec17 --- /dev/null +++ b/drivers/driver_pds.c -@@ -0,0 +1,327 @@ +@@ -0,0 +1,406 @@ ++/* ++ * Qualcomm PDS Interface driver. ++ * ++ * Tested in Dragonboard410c (APQ8016) PDS service. ++ * ++ * This file is Copyright 2020 by Linaro Limited ++ * SPDX-License-Identifier: BSD-2-clause ++ */ ++ +#include "../include/gpsd_config.h" /* must be before all includes */ + +#include <sys/socket.h> @@ -92,15 +103,16 @@ index 000000000..734b40f83 +#include <stdlib.h> +#include <unistd.h> +#include "../include/gpsd.h" -+#include "../include/libgps.h" + +#if defined(PDS_ENABLE) +#include "../include/driver_pds.h" + +#include <linux/qrtr.h> + ++#define QMI_PDS_MAX 16 +#define QMI_PDS_SERVICE_ID 0x10 +#define QMI_PDS_VERSION 0x2 ++#define QMI_PDS_PATH_STARTS 6 + +struct qmi_header { + uint8_t type; @@ -115,6 +127,8 @@ index 000000000..734b40f83 + uint8_t value[]; +} __attribute__((__packed__)); + ++static struct gps_device_t *pds_devices[QMI_PDS_MAX]; ++ +#define QMI_REQUEST 0 +#define QMI_INDICATION 4 + @@ -129,7 +143,84 @@ index 000000000..734b40f83 +#define QMI_LOC_EVENT_NMEA 0x26 +#define QMI_TLV_NMEA 1 + -+static ssize_t qmi_pds_get(struct gps_device_t *session) ++static ssize_t qmi_pds_connect(struct gps_device_t *session) ++{ ++ struct sockaddr_qrtr sq; ++ socklen_t sl = sizeof(sq); ++ struct qrtr_ctrl_pkt pkt; ++ char *hostname; ++ char *endptr; ++ int ret; ++ ++ session->lexer.outbuflen = 0; ++ ++ hostname = session->gpsdata.dev.path + QMI_PDS_PATH_STARTS; ++ if (!strcmp(hostname, "any")) { ++ session->driver.pds.hostid = -1; ++ } else { ++ session->driver.pds.hostid = (int)strtol(hostname, &endptr, 10); ++ if (endptr == hostname) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR open: Invalid node id.\n"); ++ return -1; ++ } ++ } ++ ++ ret = recvfrom(session->gpsdata.gps_fd, &pkt, sizeof(pkt), 0, ++ (struct sockaddr *)&sq, &sl); ++ if (ret < 0) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR connect: Unable to receive lookup request.\n"); ++ return -1; ++ } ++ ++ if (sl != sizeof(sq) || sq.sq_port != QRTR_PORT_CTRL) { ++ GPSD_LOG(LOG_INFO, &session->context->errout, ++ "QRTR connect: Received message is not ctrl message, ignoring.\n"); ++ return 1; ++ } ++ ++ if (pkt.cmd != QRTR_TYPE_NEW_SERVER) ++ return 1; ++ ++ /* All fields zero indicates end of lookup response */ ++ if (!pkt.server.service && !pkt.server.instance && ++ !pkt.server.node && !pkt.server.port) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR connect: End of lookup, No PDS service found for %s.\n", ++ session->gpsdata.dev.path); ++ return -1; ++ } ++ ++ /* Filter results based on specified node */ ++ if (session->driver.pds.hostid != -1 && ++ session->driver.pds.hostid != (int)pkt.server.node) ++ return 1; ++ ++ session->driver.pds.pds_node = pkt.server.node; ++ session->driver.pds.pds_port = pkt.server.port; ++ ++ GPSD_LOG(LOG_INF, &session->context->errout, ++ "QRTR open: Found PDS at %d %d.\n", ++ session->driver.pds.pds_node, ++ session->driver.pds.pds_port); ++ ++ sq.sq_family = AF_QIPCRTR; ++ sq.sq_node = session->driver.pds.pds_node; ++ sq.sq_port = session->driver.pds.pds_port; ++ ret = connect(session->gpsdata.gps_fd, (struct sockaddr *)&sq, sizeof(sq)); ++ if (ret < 0) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR connect: Failed to connect socket to PDS Service.\n"); ++ return -1; ++ } ++ ++ session->driver.pds.ready = 1; ++ session->device_type->event_hook(session, event_reactivate); ++ return 1; ++} ++ ++static ssize_t qmi_pds_get_packet(struct gps_device_t *session) +{ + struct sockaddr_qrtr sq; + socklen_t sl = sizeof(sq); @@ -153,8 +244,6 @@ index 000000000..734b40f83 + + /* TODO: Validate sq to be our peer */ + -+ session->lexer.type = QMI_PDS_PACKET; -+ + hdr = buf; + if (hdr->type != QMI_INDICATION || + hdr->msg != QMI_LOC_EVENT_NMEA) { @@ -171,6 +260,7 @@ index 000000000..734b40f83 + + if (tlv->key == QMI_TLV_NMEA) { + memcpy(session->lexer.outbuffer, tlv->value, tlv->len); ++ session->lexer.type = NMEA_PACKET; + session->lexer.outbuffer[tlv->len] = 0; + session->lexer.outbuflen = tlv->len; + break; @@ -182,9 +272,12 @@ index 000000000..734b40f83 + return ret; +} + -+static gps_mask_t qmi_pds_parse_input(struct gps_device_t *session) ++static ssize_t qmi_pds_get(struct gps_device_t *session) +{ -+ return nmea_parse((char *)session->lexer.outbuffer, session); ++ if (!session->driver.pds.ready) ++ return qmi_pds_connect(session); ++ else ++ return qmi_pds_get_packet(session); +} + +static void qmi_pds_event_hook(struct gps_device_t *session, event_t event) @@ -199,6 +292,9 @@ index 000000000..734b40f83 + + switch (event) { + case event_deactivate: ++ if (!session->driver.pds.ready) ++ return; ++ + ptr = buf; + hdr = (struct qmi_header *)ptr; + hdr->type = QMI_REQUEST; @@ -221,6 +317,9 @@ index 000000000..734b40f83 + } + break; + case event_reactivate: ++ if (!session->driver.pds.ready) ++ return; ++ + ptr = buf; + hdr = (struct qmi_header *)ptr; + hdr->type = QMI_REQUEST; @@ -268,40 +367,67 @@ index 000000000..734b40f83 + } +} + ++static ssize_t qmi_control_send(struct gps_device_t *session, ++ char *buf, size_t buflen) ++{ ++ /* do not write if -b (readonly) option set */ ++ if (session->context->readonly) ++ return true; ++ ++ session->msgbuflen = buflen; ++ (void)memcpy(session->msgbuf, buf, buflen); ++ return gpsd_write(session, session->msgbuf, session->msgbuflen); ++} ++ +int qmi_pds_open(struct gps_device_t *session) +{ + struct sockaddr_qrtr sq_ctrl; -+ struct qrtr_ctrl_pkt pkt; -+ struct sockaddr_qrtr sq; -+ unsigned int pds_node = 0; -+ unsigned int pds_port = 0; + socklen_t sl = sizeof(sq_ctrl); -+ char *hostname; -+ char *endptr; -+ int hostid; ++ struct qrtr_ctrl_pkt pkt; + int flags; + int sock; + int ret; ++ int i; + -+ hostname = session->gpsdata.dev.path + 6; -+ if (!strcmp(hostname, "any")) { -+ hostid = -1; -+ } else { -+ hostid = (int)strtol(hostname, &endptr, 10); -+ if (endptr == hostname) { ++ if (session->gpsdata.dev.path == NULL || ++ strlen(session->gpsdata.dev.path) < QMI_PDS_PATH_STARTS) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR open: Invalid PDS path.\n"); ++ return -1; ++ } ++ ++ for (i = 0; i < QMI_PDS_MAX; i++) { ++ if (pds_devices[i] == NULL) ++ continue; ++ ++ if (strcmp(pds_devices[i]->gpsdata.dev.path, ++ session->gpsdata.dev.path) == 0) { + GPSD_LOG(LOG_ERROR, &session->context->errout, -+ "QRTR open: Invalid node id.\n"); ++ "QRTR open: Invalid PDS path already specified.\n"); + return -1; + } + } + ++ for (i = 0; i < QMI_PDS_MAX; i++) { ++ if (pds_devices[i] == NULL) ++ break; ++ } ++ if (i == QMI_PDS_MAX) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR open: Limit of PDS devices reached.\n"); ++ return -1; ++ } ++ pds_devices[i] = session; + + sock = socket(AF_QIPCRTR, SOCK_DGRAM, 0); -+ if (sock < 0) { ++ if (BAD_SOCKET(sock)) { + GPSD_LOG(LOG_ERROR, &session->context->errout, + "QRTR open: Unable to get QRTR socket.\n"); + return -1; + } ++ flags = fcntl(sock, F_GETFL, 0); ++ flags |= O_NONBLOCK; ++ fcntl(sock, F_SETFL, flags); + + ret = getsockname(sock, (struct sockaddr *)&sq_ctrl, &sl); + if (ret < 0 || sq_ctrl.sq_family != AF_QIPCRTR || sl != sizeof(sq_ctrl)) { @@ -325,123 +451,52 @@ index 000000000..734b40f83 + return -1; + } + -+ for (;;) { -+ sl = sizeof(sq); -+ -+ ret = recvfrom(sock, &pkt, sizeof(pkt), 0, (struct sockaddr *)&sq, &sl); -+ if (ret < 0) { -+ GPSD_LOG(LOG_ERROR, &session->context->errout, -+ "QRTR open: Unable to receive lookup request.\n"); -+ close(sock); -+ return -1; -+ } -+ -+ if (sl != sizeof(sq) || sq.sq_node != sq_ctrl.sq_node || -+ sq.sq_port != sq_ctrl.sq_port) { -+ GPSD_LOG(LOG_ERROR, &session->context->errout, -+ "QRTR open: Received message is not ctrl message, ignoring.\n"); -+ continue; -+ } -+ -+ if (pkt.cmd != QRTR_TYPE_NEW_SERVER) -+ continue; -+ -+ /* All fields zero indicates end of lookup response */ -+ if (!pkt.server.service && !pkt.server.instance && -+ !pkt.server.node && !pkt.server.port) -+ break; -+ -+ /* Filter results based on specified node */ -+ if (hostid != -1 && hostid != (int)pkt.server.node) -+ continue; -+ -+ pds_node = pkt.server.node; -+ pds_port = pkt.server.port; -+ } -+ -+ if (!pds_node && !pds_port) { -+ GPSD_LOG(LOG_ERROR, &session->context->errout, -+ "QRTR open: No PDS service found.\n"); -+ close(sock); -+ return -1; -+ } -+ -+ flags = fcntl(sock, F_GETFL, 0); -+ flags |= O_NONBLOCK; -+ fcntl(sock, F_SETFL, flags); -+ -+ GPSD_LOG(LOG_INF, &session->context->errout, -+ "QRTR open: Found PDS at %d %d.\n", pds_node, pds_port); -+ -+ sq.sq_family = AF_QIPCRTR; -+ sq.sq_node = pds_node; -+ sq.sq_port = pds_port; -+ ret = connect(sock, (struct sockaddr *)&sq, sizeof(sq)); -+ if (ret < 0) { -+ GPSD_LOG(LOG_ERROR, &session->context->errout, -+ "QRTR open: Failed to connect socket.\n"); -+ close(sock); -+ return -1; -+ } -+ + gpsd_switch_driver(session, "Qualcomm PDS"); + session->gpsdata.gps_fd = sock; + session->sourcetype = SOURCE_QRTR; -+ session->servicetype = service_sensor; ++ session->servicetype = SERVICE_SENSOR; + + return session->gpsdata.gps_fd; +} + +void qmi_pds_close(struct gps_device_t *session) +{ ++ int i; ++ + if (!BAD_SOCKET(session->gpsdata.gps_fd)) { + close(session->gpsdata.gps_fd); + INVALIDATE_SOCKET(session->gpsdata.gps_fd); + } ++ ++ for (i = 0; i < QMI_PDS_MAX; i++) { ++ if (pds_devices[i] == NULL) ++ continue; ++ ++ if (strcmp(pds_devices[i]->gpsdata.dev.path, ++ session->gpsdata.dev.path) == 0) { ++ pds_devices[i] = NULL; ++ break; ++ } ++ } +} + +const struct gps_type_t driver_pds = { + .type_name = "Qualcomm PDS", /* full name of type */ -+ .packet_type = QMI_PDS_PACKET, /* associated lexer packet type */ ++ .packet_type = NMEA_PACKET, /* associated lexer packet type */ + .flags = DRIVER_STICKY, /* remember this */ + .channels = 12, /* not an actual GPS at all */ + .get_packet = qmi_pds_get, /* how to get a packet */ -+ .parse_packet = qmi_pds_parse_input, /* how to interpret a packet */ ++ .parse_packet = generic_parse_input, /* how to interpret a packet */ + .event_hook = qmi_pds_event_hook, ++ .control_send = qmi_control_send, +}; + +#endif /* of defined(PDS_ENABLE) */ -diff --git a/include/driver_pds.h b/include/driver_pds.h -new file mode 100644 -index 000000000..3b373743d ---- /dev/null -+++ b/include/driver_pds.h -@@ -0,0 +1,20 @@ -+/* -+ * PDS on QRTR. -+ * -+ * The entry points for driver_pds -+ * -+ * This file is Copyright (c) 2018 by the GPSD project -+ * SPDX-License-Identifier: BSD-2-clause -+ */ -+ -+#ifndef _DRIVER_PDS_H_ -+#define _DRIVER_PDS_H_ -+ -+#if defined(PDS_ENABLE) -+ -+int qmi_pds_open(struct gps_device_t *session); -+ -+void qmi_pds_close(struct gps_device_t *session); -+ -+#endif /* of defined(PDS_ENABLE) */ -+#endif /* of ifndef _DRIVER_PDS_H_ */ diff --git a/drivers/drivers.c b/drivers/drivers.c -index 39e3d0a4c..7d788e1ab 100644 +index 5c7c67b30..47a292423 100644 --- a/drivers/drivers.c +++ b/drivers/drivers.c -@@ -1747,6 +1747,7 @@ extern const struct gps_type_t driver_greis; +@@ -1694,6 +1694,7 @@ extern const struct gps_type_t driver_greis; extern const struct gps_type_t driver_italk; extern const struct gps_type_t driver_navcom; extern const struct gps_type_t driver_nmea2000; @@ -449,7 +504,7 @@ index 39e3d0a4c..7d788e1ab 100644 extern const struct gps_type_t driver_oncore; extern const struct gps_type_t driver_sirf; extern const struct gps_type_t driver_skytraq; -@@ -1844,6 +1845,10 @@ static const struct gps_type_t *gpsd_driver_array[] = { +@@ -1787,6 +1788,10 @@ static const struct gps_type_t *gpsd_driver_array[] = { &driver_nmea2000, #endif /* NMEA2000_ENABLE */ @@ -460,85 +515,126 @@ index 39e3d0a4c..7d788e1ab 100644 #ifdef RTCM104V2_ENABLE &driver_rtcm104v2, #endif /* RTCM104V2_ENABLE */ -diff --git a/include/gpsd.h b/include/gpsd.h -index 57e4b0553..e9f61cc71 100644 ---- a/include/gpsd.h -+++ b/include/gpsd.h -@@ -220,12 +220,13 @@ struct gps_lexer_t { - #define GEOSTAR_PACKET 14 - #define NMEA2000_PACKET 15 - #define GREIS_PACKET 16 --#define MAX_GPSPACKET_TYPE 16 /* increment this as necessary */ --#define RTCM2_PACKET 17 --#define RTCM3_PACKET 18 --#define JSON_PACKET 19 --#define PACKET_TYPES 20 /* increment this as necessary */ --#define SKY_PACKET 21 -+#define QMI_PDS_PACKET 17 -+#define MAX_GPSPACKET_TYPE 17 /* increment this as necessary */ -+#define RTCM2_PACKET 18 -+#define RTCM3_PACKET 19 -+#define JSON_PACKET 20 -+#define PACKET_TYPES 21 /* increment this as necessary */ -+#define SKY_PACKET 22 - #define TEXTUAL_PACKET_TYPE(n) ((((n)>=NMEA_PACKET) && ((n)<=MAX_TEXTUAL_TYPE)) || (n)==JSON_PACKET) - #define GPS_PACKET_TYPE(n) (((n)>=NMEA_PACKET) && ((n)<=MAX_GPSPACKET_TYPE)) - #define LOSSLESS_PACKET_TYPE(n) (((n)>=RTCM2_PACKET) && ((n)<=RTCM3_PACKET)) -@@ -462,6 +463,7 @@ typedef enum {SOURCE_UNKNOWN, - SOURCE_USB, // potential GPS source, discoverable - SOURCE_BLUETOOTH, // potential GPS source, discoverable - SOURCE_CAN, // potential GPS source, fixed CAN format -+ SOURCE_QRTR, // potential GPS source, discoverable - SOURCE_PTY, // PTY: we don't require exclusive access - SOURCE_TCP, // TCP/IP stream: case detected but not used - SOURCE_UDP, // UDP stream: case detected but not used diff --git a/gpsd/libgpsd_core.c b/gpsd/libgpsd_core.c -index 52bf8e5ae..a8a2ec0d3 100644 +index 60a7c2e2f..ceebb1a2a 100644 --- a/gpsd/libgpsd_core.c +++ b/gpsd/libgpsd_core.c @@ -39,6 +39,9 @@ #if defined(NMEA2000_ENABLE) - #include "../include/driver_nmea2000.h" + #include "../include/driver_nmea2000.h" #endif /* defined(NMEA2000_ENABLE) */ +#if defined(PDS_ENABLE) +#include "../include/driver_pds.h" +#endif /* defined(PDS_ENABLE) */ - /* pass low-level data to devices straight through */ + // pass low-level data to devices straight through ssize_t gpsd_write(struct gps_device_t *session, -@@ -351,6 +354,11 @@ void gpsd_deactivate(struct gps_device_t *session) - (void)nmea2000_close(session); +@@ -358,6 +361,11 @@ void gpsd_deactivate(struct gps_device_t *session) } else - #endif /* of defined(NMEA2000_ENABLE) */ + #endif // of defined(NMEA2000_ENABLE) + { +#if defined(PDS_ENABLE) -+ if (session->sourcetype == SOURCE_QRTR) ++ if (SOURCE_QRTR == session->sourcetype) + (void)qmi_pds_close(session); + else +#endif /* of defined(PDS_ENABLE) */ (void)gpsd_close(session); - if (session->mode == O_OPTIMIZE) - gpsd_run_device_hook(&session->context->errout, -@@ -553,6 +561,11 @@ int gpsd_open(struct gps_device_t *session) - return nmea2000_open(session); } - #endif /* defined(NMEA2000_ENABLE) */ + if (O_OPTIMIZE == session->mode) { +@@ -629,6 +637,11 @@ int gpsd_open(struct gps_device_t *session) + #endif // defined(NMEA2000_ENABLE) + /* fall through to plain serial open. + * could be a naked /dev/ppsX */ +#if defined(PDS_ENABLE) + if (str_starts_with(session->gpsdata.dev.path, "pds://")) { + return qmi_pds_open(session); + } +#endif /* defined(PDS_ENABLE) */ - /* fall through to plain serial open */ - /* could be a naked /dev/ppsX */ return gpsd_serial_open(session); -@@ -581,7 +594,7 @@ int gpsd_activate(struct gps_device_t *session, const int mode) + } + +@@ -656,7 +669,8 @@ int gpsd_activate(struct gps_device_t *session, const int mode) #ifdef NON_NMEA0183_ENABLE - /* if it's a sensor, it must be probed */ - if ((session->servicetype == service_sensor) && + // if it's a sensor, it must be probed + if ((SERVICE_SENSOR == session->servicetype) && - (SOURCE_CAN != session->sourcetype)) { -+ (SOURCE_CAN != session->sourcetype && SOURCE_QRTR != session->sourcetype)) { ++ (SOURCE_CAN != session->sourcetype) && ++ (SOURCE_QRTR != session->sourcetype)) { const struct gps_type_t **dp; for (dp = gpsd_drivers; *dp; dp++) { +diff --git a/include/driver_pds.h b/include/driver_pds.h +new file mode 100644 +index 000000000..3b373743d +--- /dev/null ++++ b/include/driver_pds.h +@@ -0,0 +1,20 @@ ++/* ++ * PDS on QRTR. ++ * ++ * The entry points for driver_pds ++ * ++ * This file is Copyright (c) 2018 by the GPSD project ++ * SPDX-License-Identifier: BSD-2-clause ++ */ ++ ++#ifndef _DRIVER_PDS_H_ ++#define _DRIVER_PDS_H_ ++ ++#if defined(PDS_ENABLE) ++ ++int qmi_pds_open(struct gps_device_t *session); ++ ++void qmi_pds_close(struct gps_device_t *session); ++ ++#endif /* of defined(PDS_ENABLE) */ ++#endif /* of ifndef _DRIVER_PDS_H_ */ +diff --git a/include/gpsd.h b/include/gpsd.h +index 110c5601f..b55f1913c 100644 +--- a/include/gpsd.h ++++ b/include/gpsd.h +@@ -464,6 +464,7 @@ typedef enum {SOURCE_UNKNOWN, + SOURCE_USB, // potential GPS source, discoverable + SOURCE_BLUETOOTH, // potential GPS source, discoverable + SOURCE_CAN, // potential GPS source, fixed CAN format ++ SOURCE_QRTR, // potential GPS source, discoverable + SOURCE_PTY, // PTY: we don't require exclusive access + SOURCE_TCP, // TCP/IP stream: case detected but not used + SOURCE_UDP, // UDP stream: case detected but not used +@@ -800,6 +801,14 @@ struct gps_device_t { + char ais_channel; + } aivdm; + #endif /* AIVDM_ENABLE */ ++#ifdef PDS_ENABLE ++ struct { ++ int ready; ++ int hostid; ++ unsigned int pds_node; ++ unsigned int pds_port; ++ } pds; ++#endif /* PDS_ENABLE */ + } driver; + + /* +diff --git a/man/gpsd.adoc b/man/gpsd.adoc +index 348c6b2b0..61013a8c3 100644 +--- a/man/gpsd.adoc ++++ b/man/gpsd.adoc +@@ -242,6 +242,14 @@ NMEA2000 CAN data:: + there is more than one unit on the CAN bus that provides GPS data, + *gpsd* chooses the unit from which a GPS message is first seen. Example: + *nmea2000://can0*. ++PDS service data:: ++ URI with the prefix "pds://", followed by "any" or host id ++ a numerical identifier of the PDS node. Only Linux socket PDS interfaces ++ are supported. The daemon will open a AF_QIPCRTR socket sending/listening for ++ UDP datagrams arriving in form of the QRTR encoded messages for setup and after ++ QMI encoded messages containing GPS NMEA data. ++ If "any" is send the PDS driver chooses the first PDS service ++ found. Example: *pds://any* or *pds://0*. + + (The "ais:://" source type supported in some older versions of the + daemon has been retired in favor of the more general "tcp://".) -- -2.27.0.rc0 +2.33.0 diff --git a/dynamic-layers/openembedded-layer/recipes-navigation/gpsd/gpsd-3.24/0001-Introduce-Qualcomm-PDS-service-support.patch b/dynamic-layers/openembedded-layer/recipes-navigation/gpsd/gpsd-3.24/0001-Introduce-Qualcomm-PDS-service-support.patch new file mode 100644 index 0000000..639e84a --- /dev/null +++ b/dynamic-layers/openembedded-layer/recipes-navigation/gpsd/gpsd-3.24/0001-Introduce-Qualcomm-PDS-service-support.patch @@ -0,0 +1,640 @@ +From 0f0a1495b3b2ae9da09ea1a05510492bae05a928 Mon Sep 17 00:00:00 2001 +From: Bjorn Andersson <bjorn.andersson@linaro.org> +Date: Wed, 4 Apr 2018 04:29:09 +0000 +Subject: [PATCH] Introduce Qualcomm PDS service support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The Qualcomm PDS service provides location data on a wide range of +Qualcomm platforms. It used QMI encoded messages sent over a shared +memory link, implemented in Linux as AF_QIPCRTR. + +A special service is available on port -2 on the local node in the +network, which provides functionality to the node address and port of +registered services by id. As the driver is opened this mechanism is +used to search for a registered PDS service in the system. + +As the PDS driver is activated two messages are sent to the PDS service, +the first one configures which events the service will send to the +client (in our case NMEA reports) and the second starts the transmission +of these packets. Similarly when the driver is deactivated a stop +request is sent to the service. + +Between the start and stop request the PDS service will send NMEA +messages to the PDS client at a rate of 1 Hz, the NMEA string is +extracted from the QMI encoded message and handed to the nmea_parse() +function. + +The PDS driver is selected by the url pds://<host>, where host is either +a numerical identifier of the node in the AF_QIPCRTR network or the +string "any". + +Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> +Signed-off-by: Aníbal Limón <anibal.limon@linaro.org> +--- + SConscript | 11 ++ + drivers/driver_pds.c | 406 +++++++++++++++++++++++++++++++++++++++++++ + drivers/drivers.c | 5 + + gpsd/libgpsd_core.c | 16 +- + include/driver_pds.h | 20 +++ + include/gpsd.h | 9 + + man/gpsd.adoc | 8 + + 7 files changed, 474 insertions(+), 1 deletion(-) + create mode 100644 drivers/driver_pds.c + create mode 100644 include/driver_pds.h + +diff --git a/SConscript b/SConscript +index e3fed4c27..cae23de9c 100644 +--- a/SConscript ++++ b/SConscript +@@ -315,6 +315,8 @@ boolopts = ( + ("tripmate", True, "DeLorme TripMate support"), + ("tsip", True, "Trimble TSIP support"), + ("ublox", True, "u-blox Protocol support"), ++ ("pds", sys.platform.startswith('linux'), ++ "Qualcomm PDS support"), + # Non-GPS protocols + ("aivdm", True, "AIVDM support"), + ("gpsclock", True, "Furuno GPSClock support"), +@@ -1156,6 +1158,14 @@ if not cleaning and not helping: + announce("You do not have kernel CANbus available.") + config.env["nmea2000"] = False + ++ if config.CheckHeader(["linux/qrtr.h"]): ++ confdefs.append("#define HAVE_LINUX_QRTR_H 1\n") ++ announce("You have kernel QRTR available.") ++ else: ++ confdefs.append("/* #undef HAVE_LINUX_QRTR_H */\n") ++ announce("You do not have kernel QRTR available.") ++ env["pds"] = False ++ + # check for C11 or better, and __STDC__NO_ATOMICS__ is not defined + # before looking for stdatomic.h + if ((config.CheckC11() and +@@ -1684,6 +1694,7 @@ libgpsd_sources = [ + "drivers/driver_nmea0183.c", + "drivers/driver_nmea2000.c", + "drivers/driver_oncore.c", ++ "drivers/driver_pds.c", + "drivers/driver_rtcm2.c", + "drivers/driver_rtcm3.c", + "drivers/drivers.c", +diff --git a/drivers/driver_pds.c b/drivers/driver_pds.c +new file mode 100644 +index 000000000..2ac77ec17 +--- /dev/null ++++ b/drivers/driver_pds.c +@@ -0,0 +1,406 @@ ++/* ++ * Qualcomm PDS Interface driver. ++ * ++ * Tested in Dragonboard410c (APQ8016) PDS service. ++ * ++ * This file is Copyright 2020 by Linaro Limited ++ * SPDX-License-Identifier: BSD-2-clause ++ */ ++ ++#include "../include/gpsd_config.h" /* must be before all includes */ ++ ++#include <sys/socket.h> ++#include <errno.h> ++#include <fcntl.h> ++#include <stdlib.h> ++#include <unistd.h> ++#include "../include/gpsd.h" ++ ++#if defined(PDS_ENABLE) ++#include "../include/driver_pds.h" ++ ++#include <linux/qrtr.h> ++ ++#define QMI_PDS_MAX 16 ++#define QMI_PDS_SERVICE_ID 0x10 ++#define QMI_PDS_VERSION 0x2 ++#define QMI_PDS_PATH_STARTS 6 ++ ++struct qmi_header { ++ uint8_t type; ++ uint16_t txn; ++ uint16_t msg; ++ uint16_t len; ++} __attribute__((__packed__)); ++ ++struct qmi_tlv { ++ uint8_t key; ++ uint16_t len; ++ uint8_t value[]; ++} __attribute__((__packed__)); ++ ++static struct gps_device_t *pds_devices[QMI_PDS_MAX]; ++ ++#define QMI_REQUEST 0 ++#define QMI_INDICATION 4 ++ ++#define QMI_LOC_REG_EVENTS 0x21 ++#define QMI_TLV_EVENT_MASK 1 ++#define QMI_EVENT_MASK_NMEA 4 ++ ++#define QMI_LOC_START 0x22 ++#define QMI_LOC_STOP 0x23 ++#define QMI_TLV_SESSION_ID 1 ++ ++#define QMI_LOC_EVENT_NMEA 0x26 ++#define QMI_TLV_NMEA 1 ++ ++static ssize_t qmi_pds_connect(struct gps_device_t *session) ++{ ++ struct sockaddr_qrtr sq; ++ socklen_t sl = sizeof(sq); ++ struct qrtr_ctrl_pkt pkt; ++ char *hostname; ++ char *endptr; ++ int ret; ++ ++ session->lexer.outbuflen = 0; ++ ++ hostname = session->gpsdata.dev.path + QMI_PDS_PATH_STARTS; ++ if (!strcmp(hostname, "any")) { ++ session->driver.pds.hostid = -1; ++ } else { ++ session->driver.pds.hostid = (int)strtol(hostname, &endptr, 10); ++ if (endptr == hostname) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR open: Invalid node id.\n"); ++ return -1; ++ } ++ } ++ ++ ret = recvfrom(session->gpsdata.gps_fd, &pkt, sizeof(pkt), 0, ++ (struct sockaddr *)&sq, &sl); ++ if (ret < 0) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR connect: Unable to receive lookup request.\n"); ++ return -1; ++ } ++ ++ if (sl != sizeof(sq) || sq.sq_port != QRTR_PORT_CTRL) { ++ GPSD_LOG(LOG_INFO, &session->context->errout, ++ "QRTR connect: Received message is not ctrl message, ignoring.\n"); ++ return 1; ++ } ++ ++ if (pkt.cmd != QRTR_TYPE_NEW_SERVER) ++ return 1; ++ ++ /* All fields zero indicates end of lookup response */ ++ if (!pkt.server.service && !pkt.server.instance && ++ !pkt.server.node && !pkt.server.port) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR connect: End of lookup, No PDS service found for %s.\n", ++ session->gpsdata.dev.path); ++ return -1; ++ } ++ ++ /* Filter results based on specified node */ ++ if (session->driver.pds.hostid != -1 && ++ session->driver.pds.hostid != (int)pkt.server.node) ++ return 1; ++ ++ session->driver.pds.pds_node = pkt.server.node; ++ session->driver.pds.pds_port = pkt.server.port; ++ ++ GPSD_LOG(LOG_INF, &session->context->errout, ++ "QRTR open: Found PDS at %d %d.\n", ++ session->driver.pds.pds_node, ++ session->driver.pds.pds_port); ++ ++ sq.sq_family = AF_QIPCRTR; ++ sq.sq_node = session->driver.pds.pds_node; ++ sq.sq_port = session->driver.pds.pds_port; ++ ret = connect(session->gpsdata.gps_fd, (struct sockaddr *)&sq, sizeof(sq)); ++ if (ret < 0) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR connect: Failed to connect socket to PDS Service.\n"); ++ return -1; ++ } ++ ++ session->driver.pds.ready = 1; ++ session->device_type->event_hook(session, event_reactivate); ++ return 1; ++} ++ ++static ssize_t qmi_pds_get_packet(struct gps_device_t *session) ++{ ++ struct sockaddr_qrtr sq; ++ socklen_t sl = sizeof(sq); ++ struct qmi_header *hdr; ++ struct qmi_tlv *tlv; ++ size_t buflen = sizeof(session->lexer.inbuffer); ++ size_t offset; ++ void *buf = session->lexer.inbuffer; ++ int ret; ++ ++ ret = recvfrom(session->gpsdata.gps_fd, buf, buflen, 0, ++ (struct sockaddr *)&sq, &sl); ++ if (ret < 0 && errno == EAGAIN) { ++ session->lexer.outbuflen = 0; ++ return 1; ++ } else if (ret < 0) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR get: Unable to receive packet.\n"); ++ return -1; ++ } ++ ++ /* TODO: Validate sq to be our peer */ ++ ++ hdr = buf; ++ if (hdr->type != QMI_INDICATION || ++ hdr->msg != QMI_LOC_EVENT_NMEA) { ++ session->lexer.outbuflen = 0; ++ return ret; ++ } ++ ++ offset = sizeof(*hdr); ++ while (offset < (size_t)ret) { ++ tlv = (struct qmi_tlv *)((char*)buf + offset); ++ ++ if (offset + sizeof(*tlv) + tlv->len > (size_t)ret) ++ break; ++ ++ if (tlv->key == QMI_TLV_NMEA) { ++ memcpy(session->lexer.outbuffer, tlv->value, tlv->len); ++ session->lexer.type = NMEA_PACKET; ++ session->lexer.outbuffer[tlv->len] = 0; ++ session->lexer.outbuflen = tlv->len; ++ break; ++ } ++ ++ offset += tlv->len; ++ } ++ ++ return ret; ++} ++ ++static ssize_t qmi_pds_get(struct gps_device_t *session) ++{ ++ if (!session->driver.pds.ready) ++ return qmi_pds_connect(session); ++ else ++ return qmi_pds_get_packet(session); ++} ++ ++static void qmi_pds_event_hook(struct gps_device_t *session, event_t event) ++{ ++ struct qmi_header *hdr; ++ struct qmi_tlv *tlv; ++ static int txn_id; ++ char buf[128]; ++ char *ptr; ++ int sock = session->gpsdata.gps_fd; ++ int ret; ++ ++ switch (event) { ++ case event_deactivate: ++ if (!session->driver.pds.ready) ++ return; ++ ++ ptr = buf; ++ hdr = (struct qmi_header *)ptr; ++ hdr->type = QMI_REQUEST; ++ hdr->txn = txn_id++; ++ hdr->msg = QMI_LOC_STOP; ++ hdr->len = sizeof(*tlv) + sizeof(uint8_t); ++ ptr += sizeof(*hdr); ++ ++ tlv = (struct qmi_tlv *)ptr; ++ tlv->key = QMI_TLV_SESSION_ID; ++ tlv->len = sizeof(uint8_t); ++ *(uint8_t*)tlv->value = 1; ++ ptr += sizeof(*tlv) + sizeof(uint8_t); ++ ++ ret = send(sock, buf, ptr - buf, 0); ++ if (ret < 0) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR event_hook: failed to send STOP request.\n"); ++ return; ++ } ++ break; ++ case event_reactivate: ++ if (!session->driver.pds.ready) ++ return; ++ ++ ptr = buf; ++ hdr = (struct qmi_header *)ptr; ++ hdr->type = QMI_REQUEST; ++ hdr->txn = txn_id++; ++ hdr->msg = QMI_LOC_REG_EVENTS; ++ hdr->len = sizeof(*tlv) + sizeof(uint64_t); ++ ptr += sizeof(*hdr); ++ ++ tlv = (struct qmi_tlv *)ptr; ++ tlv->key = QMI_TLV_EVENT_MASK; ++ tlv->len = sizeof(uint64_t); ++ *(uint64_t*)tlv->value = QMI_EVENT_MASK_NMEA; ++ ptr += sizeof(*tlv) + sizeof(uint64_t); ++ ++ ret = send(sock, buf, ptr - buf, 0); ++ if (ret < 0) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR event_hook: failed to send REG_EVENTS request.\n"); ++ return; ++ } ++ ++ ptr = buf; ++ hdr = (struct qmi_header *)ptr; ++ hdr->type = QMI_REQUEST; ++ hdr->txn = txn_id++; ++ hdr->msg = QMI_LOC_START; ++ hdr->len = sizeof(*tlv) + sizeof(uint8_t); ++ ptr += sizeof(*hdr); ++ ++ tlv = (struct qmi_tlv *)(buf + sizeof(*hdr)); ++ tlv->key = QMI_TLV_SESSION_ID; ++ tlv->len = sizeof(uint8_t); ++ *(uint8_t*)tlv->value = 1; ++ ptr += sizeof(*tlv) + sizeof(uint8_t); ++ ++ ret = send(sock, buf, ptr - buf, 0); ++ if (ret < 0) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR event_hook: failed to send START request.\n"); ++ return; ++ } ++ break; ++ default: ++ break; ++ } ++} ++ ++static ssize_t qmi_control_send(struct gps_device_t *session, ++ char *buf, size_t buflen) ++{ ++ /* do not write if -b (readonly) option set */ ++ if (session->context->readonly) ++ return true; ++ ++ session->msgbuflen = buflen; ++ (void)memcpy(session->msgbuf, buf, buflen); ++ return gpsd_write(session, session->msgbuf, session->msgbuflen); ++} ++ ++int qmi_pds_open(struct gps_device_t *session) ++{ ++ struct sockaddr_qrtr sq_ctrl; ++ socklen_t sl = sizeof(sq_ctrl); ++ struct qrtr_ctrl_pkt pkt; ++ int flags; ++ int sock; ++ int ret; ++ int i; ++ ++ if (session->gpsdata.dev.path == NULL || ++ strlen(session->gpsdata.dev.path) < QMI_PDS_PATH_STARTS) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR open: Invalid PDS path.\n"); ++ return -1; ++ } ++ ++ for (i = 0; i < QMI_PDS_MAX; i++) { ++ if (pds_devices[i] == NULL) ++ continue; ++ ++ if (strcmp(pds_devices[i]->gpsdata.dev.path, ++ session->gpsdata.dev.path) == 0) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR open: Invalid PDS path already specified.\n"); ++ return -1; ++ } ++ } ++ ++ for (i = 0; i < QMI_PDS_MAX; i++) { ++ if (pds_devices[i] == NULL) ++ break; ++ } ++ if (i == QMI_PDS_MAX) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR open: Limit of PDS devices reached.\n"); ++ return -1; ++ } ++ pds_devices[i] = session; ++ ++ sock = socket(AF_QIPCRTR, SOCK_DGRAM, 0); ++ if (BAD_SOCKET(sock)) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR open: Unable to get QRTR socket.\n"); ++ return -1; ++ } ++ flags = fcntl(sock, F_GETFL, 0); ++ flags |= O_NONBLOCK; ++ fcntl(sock, F_SETFL, flags); ++ ++ ret = getsockname(sock, (struct sockaddr *)&sq_ctrl, &sl); ++ if (ret < 0 || sq_ctrl.sq_family != AF_QIPCRTR || sl != sizeof(sq_ctrl)) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR open: Unable to acquire local address.\n"); ++ close(sock); ++ return -1; ++ } ++ ++ memset(&pkt, 0, sizeof(pkt)); ++ pkt.cmd = QRTR_TYPE_NEW_LOOKUP; ++ pkt.server.service = QMI_PDS_SERVICE_ID; ++ pkt.server.instance = QMI_PDS_VERSION; ++ ++ sq_ctrl.sq_port = QRTR_PORT_CTRL; ++ ret = sendto(sock, &pkt, sizeof(pkt), 0, (struct sockaddr *)&sq_ctrl, sizeof(sq_ctrl)); ++ if (ret < 0) { ++ GPSD_LOG(LOG_ERROR, &session->context->errout, ++ "QRTR open: Unable to send lookup request.\n"); ++ close(sock); ++ return -1; ++ } ++ ++ gpsd_switch_driver(session, "Qualcomm PDS"); ++ session->gpsdata.gps_fd = sock; ++ session->sourcetype = SOURCE_QRTR; ++ session->servicetype = SERVICE_SENSOR; ++ ++ return session->gpsdata.gps_fd; ++} ++ ++void qmi_pds_close(struct gps_device_t *session) ++{ ++ int i; ++ ++ if (!BAD_SOCKET(session->gpsdata.gps_fd)) { ++ close(session->gpsdata.gps_fd); ++ INVALIDATE_SOCKET(session->gpsdata.gps_fd); ++ } ++ ++ for (i = 0; i < QMI_PDS_MAX; i++) { ++ if (pds_devices[i] == NULL) ++ continue; ++ ++ if (strcmp(pds_devices[i]->gpsdata.dev.path, ++ session->gpsdata.dev.path) == 0) { ++ pds_devices[i] = NULL; ++ break; ++ } ++ } ++} ++ ++const struct gps_type_t driver_pds = { ++ .type_name = "Qualcomm PDS", /* full name of type */ ++ .packet_type = NMEA_PACKET, /* associated lexer packet type */ ++ .flags = DRIVER_STICKY, /* remember this */ ++ .channels = 12, /* not an actual GPS at all */ ++ .get_packet = qmi_pds_get, /* how to get a packet */ ++ .parse_packet = generic_parse_input, /* how to interpret a packet */ ++ .event_hook = qmi_pds_event_hook, ++ .control_send = qmi_control_send, ++}; ++ ++#endif /* of defined(PDS_ENABLE) */ +diff --git a/drivers/drivers.c b/drivers/drivers.c +index 5c7c67b30..47a292423 100644 +--- a/drivers/drivers.c ++++ b/drivers/drivers.c +@@ -1694,6 +1694,7 @@ extern const struct gps_type_t driver_greis; + extern const struct gps_type_t driver_italk; + extern const struct gps_type_t driver_navcom; + extern const struct gps_type_t driver_nmea2000; ++extern const struct gps_type_t driver_pds; + extern const struct gps_type_t driver_oncore; + extern const struct gps_type_t driver_sirf; + extern const struct gps_type_t driver_skytraq; +@@ -1787,6 +1788,10 @@ static const struct gps_type_t *gpsd_driver_array[] = { + &driver_nmea2000, + #endif // NMEA2000_ENABLE + ++#ifdef PDS_ENABLE ++ &driver_pds, ++#endif /* PDS_ENABLE */ ++ + #ifdef RTCM104V2_ENABLE + &driver_rtcm104v2, + #endif // RTCM104V2_ENABLE +diff --git a/gpsd/libgpsd_core.c b/gpsd/libgpsd_core.c +index 60a7c2e2f..ceebb1a2a 100644 +--- a/gpsd/libgpsd_core.c ++++ b/gpsd/libgpsd_core.c +@@ -39,6 +39,9 @@ + #if defined(NMEA2000_ENABLE) + #include "../include/driver_nmea2000.h" + #endif // defined(NMEA2000_ENABLE) ++#if defined(PDS_ENABLE) ++#include "../include/driver_pds.h" ++#endif /* defined(PDS_ENABLE) */ + + // pass low-level data to devices straight through + ssize_t gpsd_write(struct gps_device_t *session, +@@ -358,6 +361,11 @@ void gpsd_deactivate(struct gps_device_t *session) + (void)nmea2000_close(session); + } else + #endif // NMEA2000_ENABLE ++#if defined(PDS_ENABLE) ++ if (SOURCE_QRTR == session->sourcetype) ++ (void)qmi_pds_close(session); ++ else ++#endif /* of defined(PDS_ENABLE) */ + { + // could be serial, udp://, tcp://, etc. + gpsd_close(session); +@@ -629,6 +637,11 @@ int gpsd_open(struct gps_device_t *session) + #endif // defined(NMEA2000_ENABLE) + /* fall through to plain serial open. + * could be a naked /dev/ppsX */ ++#if defined(PDS_ENABLE) ++ if (str_starts_with(session->gpsdata.dev.path, "pds://")) { ++ return qmi_pds_open(session); ++ } ++#endif /* defined(PDS_ENABLE) */ + return gpsd_serial_open(session); + } + +@@ -656,7 +669,8 @@ int gpsd_activate(struct gps_device_t *session, const int mode) + #ifdef NON_NMEA0183_ENABLE + // if it's a sensor, it must be probed + if ((SERVICE_SENSOR == session->servicetype) && +- (SOURCE_CAN != session->sourcetype)) { ++ (SOURCE_CAN != session->sourcetype) && ++ (SOURCE_QRTR != session->sourcetype)) { + const struct gps_type_t **dp; + + for (dp = gpsd_drivers; *dp; dp++) { +diff --git a/include/driver_pds.h b/include/driver_pds.h +new file mode 100644 +index 000000000..3b373743d +--- /dev/null ++++ b/include/driver_pds.h +@@ -0,0 +1,20 @@ ++/* ++ * PDS on QRTR. ++ * ++ * The entry points for driver_pds ++ * ++ * This file is Copyright (c) 2018 by the GPSD project ++ * SPDX-License-Identifier: BSD-2-clause ++ */ ++ ++#ifndef _DRIVER_PDS_H_ ++#define _DRIVER_PDS_H_ ++ ++#if defined(PDS_ENABLE) ++ ++int qmi_pds_open(struct gps_device_t *session); ++ ++void qmi_pds_close(struct gps_device_t *session); ++ ++#endif /* of defined(PDS_ENABLE) */ ++#endif /* of ifndef _DRIVER_PDS_H_ */ +diff --git a/include/gpsd.h b/include/gpsd.h +index 110c5601f..b55f1913c 100644 +--- a/include/gpsd.h ++++ b/include/gpsd.h +@@ -464,6 +464,7 @@ typedef enum {SOURCE_UNKNOWN, + SOURCE_USB, // potential GPS source, discoverable + SOURCE_BLUETOOTH, // potential GPS source, discoverable + SOURCE_CAN, // potential GPS source, fixed CAN format ++ SOURCE_QRTR, // potential GPS source, discoverable + SOURCE_PTY, // PTY: we don't require exclusive access + SOURCE_TCP, // TCP/IP stream: case detected but not used + SOURCE_UDP, // UDP stream: case detected but not used +@@ -800,6 +801,14 @@ struct gps_device_t { + char ais_channel; + } aivdm; + #endif /* AIVDM_ENABLE */ ++#ifdef PDS_ENABLE ++ struct { ++ int ready; ++ int hostid; ++ unsigned int pds_node; ++ unsigned int pds_port; ++ } pds; ++#endif /* PDS_ENABLE */ + } driver; + + /* +diff --git a/man/gpsd.adoc b/man/gpsd.adoc +index 348c6b2b0..61013a8c3 100644 +--- a/man/gpsd.adoc ++++ b/man/gpsd.adoc +@@ -242,6 +242,14 @@ NMEA2000 CAN data:: + there is more than one unit on the CAN bus that provides GPS data, + *gpsd* chooses the unit from which a GPS message is first seen. Example: + *nmea2000://can0*. ++PDS service data:: ++ URI with the prefix "pds://", followed by "any" or host id ++ a numerical identifier of the PDS node. Only Linux socket PDS interfaces ++ are supported. The daemon will open a AF_QIPCRTR socket sending/listening for ++ UDP datagrams arriving in form of the QRTR encoded messages for setup and after ++ QMI encoded messages containing GPS NMEA data. ++ If "any" is send the PDS driver chooses the first PDS service ++ found. Example: *pds://any* or *pds://0*. + + (The "ais:://" source type supported in some older versions of the + daemon has been retired in favor of the more general "tcp://".) +-- +2.33.0 + diff --git a/dynamic-layers/openembedded-layer/recipes-navigation/gpsd/gpsd_%.bbappend b/dynamic-layers/openembedded-layer/recipes-navigation/gpsd/gpsd_%.bbappend index cc6e886..5b3a849 100644 --- a/dynamic-layers/openembedded-layer/recipes-navigation/gpsd/gpsd_%.bbappend +++ b/dynamic-layers/openembedded-layer/recipes-navigation/gpsd/gpsd_%.bbappend @@ -1,4 +1,11 @@ -FILESEXTRAPATHS:prepend := "${THISDIR}/${BPN}:" +# We can not use PV here, it will be expanded too early (to the '%' value). +# Thus use a temporal variable which substituted later. Note the difference +# between immediate expansion (to get THISDIR) and regular expansion. +# +# The order of these assignments is also important + +FILESEXTRAPATHS:prepend := "${THISDIR}/${BPN}-${gpsPV}:${THISDIR}/${BPN}:" +gpsPV = "${PV}" SRC_URI += " \ file://0001-Introduce-Qualcomm-PDS-service-support.patch \ |