123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- /*
- * This file is Copyright (c)2010-2018 by the GPSD project
- * SPDX-License-Identifier: BSD-2-clause
- */
- #include "gpsd_config.h" /* must be before all includes */
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdbool.h>
- #include <string.h>
- #include <math.h>
- #include <time.h>
- #include <errno.h>
- #include <libgen.h>
- #include <signal.h>
- #include <unistd.h>
- #include "gps.h"
- #include "libgps.h"
- #if defined(DBUS_EXPORT_ENABLE)
- #include <syslog.h>
- struct privdata_t
- {
- void (*handler)(struct gps_data_t *);
- };
- #include <dbus/dbus.h>
- /*
- * Unpleasant that we have to declare a static context pointer here - means
- * you can't have multiple DBUS sessions open (not that this matters
- * much in practice). The problem is the DBUS API lacks some hook
- * arguments that it ought to have.
- */
- static struct gps_data_t *share_gpsdata;
- static DBusConnection *connection;
- static DBusHandlerResult handle_gps_fix(DBusMessage * message)
- {
- DBusError error;
- const char *gpsd_devname = NULL;
- dbus_error_init(&error);
- dbus_message_get_args(message,
- &error,
- DBUS_TYPE_DOUBLE, &share_gpsdata->fix.time,
- DBUS_TYPE_INT32, &share_gpsdata->fix.mode,
- DBUS_TYPE_DOUBLE, &share_gpsdata->fix.ept,
- DBUS_TYPE_DOUBLE, &share_gpsdata->fix.latitude,
- DBUS_TYPE_DOUBLE, &share_gpsdata->fix.longitude,
- DBUS_TYPE_DOUBLE, &share_gpsdata->fix.eph,
- /* The debus doc does not seem to specify
- * altHAE or altMSL */
- DBUS_TYPE_DOUBLE, &share_gpsdata->fix.altHAE,
- DBUS_TYPE_DOUBLE, &share_gpsdata->fix.epv,
- DBUS_TYPE_DOUBLE, &share_gpsdata->fix.track,
- DBUS_TYPE_DOUBLE, &share_gpsdata->fix.epd,
- DBUS_TYPE_DOUBLE, &share_gpsdata->fix.speed,
- DBUS_TYPE_DOUBLE, &share_gpsdata->fix.eps,
- DBUS_TYPE_DOUBLE, &share_gpsdata->fix.climb,
- DBUS_TYPE_DOUBLE, &share_gpsdata->fix.epc,
- DBUS_TYPE_STRING, &gpsd_devname, DBUS_TYPE_INVALID);
- if (share_gpsdata->fix.mode > MODE_NO_FIX )
- share_gpsdata->status = STATUS_FIX;
- else
- share_gpsdata->status = STATUS_NO_FIX;
- dbus_error_free(&error);
- PRIVATE(share_gpsdata)->handler(share_gpsdata);
- return DBUS_HANDLER_RESULT_HANDLED;
- }
- /*
- * Message dispatching function
- *
- */
- static DBusHandlerResult signal_handler(DBusConnection * connection UNUSED,
- DBusMessage * message,
- void *user_data UNUSED)
- {
- if (dbus_message_is_signal(message, "org.gpsd", "fix"))
- return handle_gps_fix(message);
- /*
- * ignore all other messages
- */
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- }
- int gps_dbus_open(struct gps_data_t *gpsdata)
- {
- DBusError error;
- gpsdata->privdata = (void *)malloc(sizeof(struct privdata_t));
- if (gpsdata->privdata == NULL)
- return -1;
- dbus_error_init(&error);
- connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
- if (dbus_error_is_set(&error)) {
- syslog(LOG_CRIT, "%s: %s", error.name, error.message);
- dbus_error_free(&error);
- return 3;
- }
- dbus_bus_add_match(connection, "type='signal'", &error);
- if (dbus_error_is_set(&error)) {
- syslog(LOG_CRIT, "unable to add match for signals %s: %s", error.name,
- error.message);
- dbus_error_free(&error);
- return 4;
- }
- if (!dbus_connection_add_filter
- (connection, (DBusHandleMessageFunction) signal_handler, NULL,
- NULL)) {
- syslog(LOG_CRIT, "unable to register filter with the connection");
- return 5;
- }
- #ifndef USE_QT
- gpsdata->gps_fd = DBUS_PSEUDO_FD;
- #else
- gpsdata->gps_fd = (void *)(intptr_t)DBUS_PSEUDO_FD;
- #endif /* USE_QT */
- share_gpsdata = gpsdata;
- return 0;
- }
- int gps_dbus_mainloop(struct gps_data_t *gpsdata,
- int timeout,
- void (*hook)(struct gps_data_t *))
- /* run a DBUS main loop with a specified handler */
- {
- share_gpsdata = gpsdata;
- PRIVATE(share_gpsdata)->handler = (void (*)(struct gps_data_t *))hook;
- for (;;)
- if (dbus_connection_read_write_dispatch(connection, (int)(timeout/1000)) != TRUE)
- return -1;
- return 0;
- }
- #endif /* defined(DBUS_EXPORT_ENABLE) */
|