diff options
author | Kibum Kim <kb0929.kim@samsung.com> | 2012-01-07 00:46:29 +0900 |
---|---|---|
committer | Kibum Kim <kb0929.kim@samsung.com> | 2012-01-07 00:46:29 +0900 |
commit | 0c44dc6cd8d3ede16172f22fa2b7c6af4459e55d (patch) | |
tree | 327fd58b5a721a2ecf835f2eccffde08cdbc4070 /.pc/tizen.patch/providers | |
parent | 9f11ee482a4a28d6e85613ac5c765c588fdf20aa (diff) | |
download | geoclue-0c44dc6cd8d3ede16172f22fa2b7c6af4459e55d.tar.gz geoclue-0c44dc6cd8d3ede16172f22fa2b7c6af4459e55d.tar.bz2 geoclue-0c44dc6cd8d3ede16172f22fa2b7c6af4459e55d.zip |
Git init
Diffstat (limited to '.pc/tizen.patch/providers')
24 files changed, 4656 insertions, 0 deletions
diff --git a/.pc/tizen.patch/providers/example/Makefile.am b/.pc/tizen.patch/providers/example/Makefile.am new file mode 100755 index 0000000..bb052fc --- /dev/null +++ b/.pc/tizen.patch/providers/example/Makefile.am @@ -0,0 +1,30 @@ +libexec_PROGRAMS = geoclue-example + +geoclue_example_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) + +geoclue_example_LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + +geoclue_example_SOURCES = \ + geoclue-example.c + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-example.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Example.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/providers/example/geoclue-example.c b/.pc/tizen.patch/providers/example/geoclue-example.c new file mode 100755 index 0000000..a7ef6f7 --- /dev/null +++ b/.pc/tizen.patch/providers/example/geoclue-example.c @@ -0,0 +1,168 @@ +/* + * Geoclue + * geoclue-example.c - Example provider which doesn't do anything. + * + * Author: Iain Holmes <iain@openedhand.com> + * Copyright 2007 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <geoclue/gc-provider.h> +#include <geoclue/gc-iface-position.h> + +typedef struct { + GcProvider parent; + + GMainLoop *loop; +} GeoclueExample; + +typedef struct { + GcProviderClass parent_class; +} GeoclueExampleClass; + +#define GEOCLUE_TYPE_EXAMPLE (geoclue_example_get_type ()) +#define GEOCLUE_EXAMPLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_EXAMPLE, GeoclueExample)) + +static void geoclue_example_position_init (GcIfacePositionClass *iface); + +G_DEFINE_TYPE_WITH_CODE (GeoclueExample, geoclue_example, GC_TYPE_PROVIDER, + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION, + geoclue_example_position_init)) + + +static gboolean +get_status (GcIfaceGeoclue *gc, + GeoclueStatus *status, + GError **error) +{ + *status = GEOCLUE_STATUS_AVAILABLE; + + return TRUE; +} + +static void +print_option (gpointer key, + gpointer value, + gpointer data) +{ + if (G_VALUE_TYPE (value) == G_TYPE_STRING) + g_print (" %s - %s\n", key, g_value_get_string (value)); + else + g_print (" %s - %d\n", key, g_value_get_int (value)); +} + +static gboolean +set_options (GcIfaceGeoclue *gc, + GHashTable *options, + GError **error) +{ + g_print ("Options received---\n"); + g_hash_table_foreach (options, print_option, NULL); + return TRUE; +} + +static void +shutdown (GcProvider *provider) +{ + GeoclueExample *example = GEOCLUE_EXAMPLE (provider); + + g_main_loop_quit (example->loop); +} + +static void +geoclue_example_class_init (GeoclueExampleClass *klass) +{ + GcProviderClass *p_class = (GcProviderClass *) klass; + + p_class->get_status = get_status; + p_class->set_options = set_options; + p_class->shutdown = shutdown; +} + +static void +geoclue_example_init (GeoclueExample *example) +{ + gc_provider_set_details (GC_PROVIDER (example), + "org.freedesktop.Geoclue.Providers.Example", + "/org/freedesktop/Geoclue/Providers/Example", + "Example", "Example provider"); +} + +static gboolean +get_position (GcIfacePosition *gc, + GeocluePositionFields *fields, + int *timestamp, + double *latitude, + double *longitude, + double *altitude, + GeoclueAccuracy **accuracy, + GError **error) +{ + *timestamp = time (NULL); + + /* We're not emitting location details here because we don't want + geoclue to accidently use this as a source */ + *fields = GEOCLUE_POSITION_FIELDS_NONE; + *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0.0, 0.0); + return TRUE; +} + +static void +geoclue_example_position_init (GcIfacePositionClass *iface) +{ + iface->get_position = get_position; +} + +static gboolean +emit_position_signal (gpointer data) +{ + GeoclueExample *example = data; + GeoclueAccuracy *accuracy; + + accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, + 0.0, 0.0); + + gc_iface_position_emit_position_changed + (GC_IFACE_POSITION (example), + GEOCLUE_POSITION_FIELDS_NONE, + time (NULL), 0.0, 0.0, 0.0, accuracy); + + geoclue_accuracy_free (accuracy); + + return TRUE; +} + +int +main (int argc, + char **argv) +{ + GeoclueExample *example; + + g_type_init (); + + example = g_object_new (GEOCLUE_TYPE_EXAMPLE, NULL); + + g_timeout_add (5000, emit_position_signal, example); + + example->loop = g_main_loop_new (NULL, TRUE); + g_main_loop_run (example->loop); + + return 0; +} diff --git a/.pc/tizen.patch/providers/geonames/Makefile.am b/.pc/tizen.patch/providers/geonames/Makefile.am new file mode 100755 index 0000000..55f31e3 --- /dev/null +++ b/.pc/tizen.patch/providers/geonames/Makefile.am @@ -0,0 +1,35 @@ +libexec_PROGRAMS = \ + geoclue-geonames + +NOINST_H_FILES = \ + geoclue-geonames.h + +geoclue_geonames_SOURCES = \ + $(NOINST_H_FILES) \ + geoclue-geonames.c + +geoclue_geonames_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) + +geoclue_geonames_LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-geonames.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Geonames.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/providers/gpsd/Makefile.am b/.pc/tizen.patch/providers/gpsd/Makefile.am new file mode 100755 index 0000000..cc2764e --- /dev/null +++ b/.pc/tizen.patch/providers/gpsd/Makefile.am @@ -0,0 +1,32 @@ +libexec_PROGRAMS = geoclue-gpsd + +geoclue_gpsd_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) \ + $(GPSD_CFLAGS) + +geoclue_gpsd_LDADD = \ + $(GEOCLUE_LIBS) \ + $(GPSD_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + +geoclue_gpsd_SOURCES = \ + geoclue-gpsd.c + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-gpsd.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Gpsd.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/providers/gpsd/geoclue-gpsd.c b/.pc/tizen.patch/providers/gpsd/geoclue-gpsd.c new file mode 100755 index 0000000..dba91be --- /dev/null +++ b/.pc/tizen.patch/providers/gpsd/geoclue-gpsd.c @@ -0,0 +1,519 @@ +/* + * Geoclue + * geoclue-gpsd.c - Geoclue Position backend for gpsd + * + * Authors: Jussi Kukkonen <jku@o-hand.com> + * Copyright 2007 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/* TODO: + * + * call to gps_set_callback blocks for a long time if + * BT device is not present. + * + **/ + +#include <config.h> + +#include <math.h> +#include <gps.h> +#include <string.h> + +#include <geoclue/geoclue-error.h> +#include <geoclue/gc-provider.h> +#include <geoclue/gc-iface-position.h> +#include <geoclue/gc-iface-velocity.h> + +typedef struct gps_data_t gps_data; +typedef struct gps_fix_t gps_fix; + +/* only listing used tags */ +typedef enum { + NMEA_NONE, + NMEA_GSA, + NMEA_GGA, + NMEA_GSV, + NMEA_RMC +} NmeaTag; + + +typedef struct { + GcProvider parent; + + char *host; + char *port; + + gps_data *gpsdata; + + gps_fix *last_fix; + + GeoclueStatus last_status; + GeocluePositionFields last_pos_fields; + GeoclueAccuracy *last_accuracy; + GeoclueVelocityFields last_velo_fields; + + GMainLoop *loop; + +} GeoclueGpsd; + +typedef struct { + GcProviderClass parent_class; +} GeoclueGpsdClass; + +static void geoclue_gpsd_position_init (GcIfacePositionClass *iface); +static void geoclue_gpsd_velocity_init (GcIfaceVelocityClass *iface); + +#define GEOCLUE_TYPE_GPSD (geoclue_gpsd_get_type ()) +#define GEOCLUE_GPSD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_GPSD, GeoclueGpsd)) + +G_DEFINE_TYPE_WITH_CODE (GeoclueGpsd, geoclue_gpsd, GC_TYPE_PROVIDER, + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION, + geoclue_gpsd_position_init) + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_VELOCITY, + geoclue_gpsd_velocity_init)) + +static void geoclue_gpsd_stop_gpsd (GeoclueGpsd *self); +static gboolean geoclue_gpsd_start_gpsd (GeoclueGpsd *self); + + +/* defining global GeoclueGpsd because gpsd does not support "user_data" + * pointers in callbacks */ +GeoclueGpsd *gpsd; + + + +/* Geoclue interface */ +static gboolean +get_status (GcIfaceGeoclue *gc, + GeoclueStatus *status, + GError **error) +{ + GeoclueGpsd *gpsd = GEOCLUE_GPSD (gc); + + *status = gpsd->last_status; + return TRUE; +} + +static void +shutdown (GcProvider *provider) +{ + GeoclueGpsd *gpsd = GEOCLUE_GPSD (provider); + + g_main_loop_quit (gpsd->loop); +} + +static void +geoclue_gpsd_set_status (GeoclueGpsd *self, GeoclueStatus status) +{ + if (status != self->last_status) { + self->last_status = status; + + /* make position and velocity invalid if no fix */ + if (status != GEOCLUE_STATUS_AVAILABLE) { + self->last_pos_fields = GEOCLUE_POSITION_FIELDS_NONE; + self->last_velo_fields = GEOCLUE_VELOCITY_FIELDS_NONE; + } + gc_iface_geoclue_emit_status_changed (GC_IFACE_GEOCLUE (self), + status); + } +} + +static gboolean +set_options (GcIfaceGeoclue *gc, + GHashTable *options, + GError **error) +{ + GeoclueGpsd *gpsd = GEOCLUE_GPSD (gc); + GValue *port_value, *host_value; + const char *port, *host; + gboolean changed = FALSE; + + host_value = g_hash_table_lookup (options, + "org.freedesktop.Geoclue.GPSHost"); + host = host_value ? g_value_get_string (host_value) : NULL; + port_value = g_hash_table_lookup (options, + "org.freedesktop.Geoclue.GPSPort"); + port = port_value ? g_value_get_string (port_value) : NULL; + + if (port == NULL) { + port = DEFAULT_GPSD_PORT; + } + + /* new values? */ + if (g_strcmp0 (host, gpsd->host) != 0 || + g_strcmp0 (port, gpsd->port) != 0) { + changed = TRUE; + } + + if (!changed) { + return TRUE; + } + + /* update private values with new ones, restart gpsd */ + g_free (gpsd->port); + gpsd->port = NULL; + g_free (gpsd->host); + gpsd->host = NULL; + + geoclue_gpsd_stop_gpsd (gpsd); + + if (host == NULL) { + return TRUE; + } + + gpsd->port = g_strdup (port); + gpsd->host = g_strdup (host); + if (!geoclue_gpsd_start_gpsd (gpsd)) { + geoclue_gpsd_set_status (gpsd, GEOCLUE_STATUS_ERROR); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_FAILED, "Gpsd not found"); + return FALSE; + } + return TRUE; +} + +static void +finalize (GObject *object) +{ + GeoclueGpsd *gpsd = GEOCLUE_GPSD (object); + + geoclue_gpsd_stop_gpsd (gpsd); + g_free (gpsd->last_fix); + geoclue_accuracy_free (gpsd->last_accuracy); + + g_free (gpsd->port); + if (gpsd->host) { + g_free (gpsd->host); + } + + ((GObjectClass *) geoclue_gpsd_parent_class)->finalize (object); +} + +static void +geoclue_gpsd_class_init (GeoclueGpsdClass *klass) +{ + GObjectClass *o_class = (GObjectClass *) klass; + GcProviderClass *p_class = (GcProviderClass *) klass; + + o_class->finalize = finalize; + + p_class->get_status = get_status; + p_class->set_options = set_options; + p_class->shutdown = shutdown; +} + + +static gboolean +equal_or_nan (double a, double b) +{ + if (isnan (a) && isnan (b)) { + return TRUE; + } + return a == b; +} + +static void +geoclue_gpsd_update_position (GeoclueGpsd *gpsd, NmeaTag nmea_tag) +{ + gps_fix *fix = &gpsd->gpsdata->fix; + gps_fix *last_fix = gpsd->last_fix; + + last_fix->time = fix->time; + + /* If a flag is not set, bail out.*/ + if (!((gpsd->gpsdata->set & LATLON_SET) || (gpsd->gpsdata->set & ALTITUDE_SET))) { + return; + } + gpsd->gpsdata->set &= ~(LATLON_SET | ALTITUDE_SET); + + if (equal_or_nan (fix->latitude, last_fix->latitude) && + equal_or_nan (fix->longitude, last_fix->longitude) && + equal_or_nan (fix->altitude, last_fix->altitude)) { + /* position has not changed */ + return; + } + + /* save values */ + last_fix->latitude = fix->latitude; + last_fix->longitude = fix->longitude; + last_fix->altitude = fix->altitude; + + /* Could use fix.eph for accuracy, but eph is + * often NaN... what then? + * Could also use fix mode (2d/3d) to decide vertical accuracy, + * but gpsd updates that so erratically that I couldn't + * be arsed so far */ + geoclue_accuracy_set_details (gpsd->last_accuracy, + GEOCLUE_ACCURACY_LEVEL_DETAILED, + 24, 60); + + gpsd->last_pos_fields = GEOCLUE_POSITION_FIELDS_NONE; + gpsd->last_pos_fields |= (isnan (fix->latitude)) ? + 0 : GEOCLUE_POSITION_FIELDS_LATITUDE; + gpsd->last_pos_fields |= (isnan (fix->longitude)) ? + 0 : GEOCLUE_POSITION_FIELDS_LONGITUDE; + gpsd->last_pos_fields |= (isnan (fix->altitude)) ? + 0 : GEOCLUE_POSITION_FIELDS_ALTITUDE; + + gc_iface_position_emit_position_changed + (GC_IFACE_POSITION (gpsd), gpsd->last_pos_fields, + (int)(last_fix->time+0.5), + last_fix->latitude, last_fix->longitude, last_fix->altitude, + gpsd->last_accuracy); + +} + +static void +geoclue_gpsd_update_velocity (GeoclueGpsd *gpsd, NmeaTag nmea_tag) +{ + gps_fix *fix = &gpsd->gpsdata->fix; + gps_fix *last_fix = gpsd->last_fix; + gboolean changed = FALSE; + + /* at least with my devices, gpsd updates + * - climb on GGA, GSA and GSV messages (speed and track are set to NaN). + * - speed and track on RMC message (climb is set to NaN). + * + * couldn't think of an smart way to handle this, I don't think there is one + */ + + if (((gpsd->gpsdata->set & TRACK_SET) || (gpsd->gpsdata->set & SPEED_SET)) && + nmea_tag == NMEA_RMC) { + + gpsd->gpsdata->set &= ~(TRACK_SET | SPEED_SET); + + last_fix->time = fix->time; + + if (!equal_or_nan (fix->track, last_fix->track) || + !equal_or_nan (fix->speed, last_fix->speed)){ + + /* velocity has changed */ + changed = TRUE; + last_fix->track = fix->track; + last_fix->speed = fix->speed; + } + } else if ((gpsd->gpsdata->set & CLIMB_SET) && + (nmea_tag == NMEA_GGA || + nmea_tag == NMEA_GSA || + nmea_tag == NMEA_GSV)) { + + gpsd->gpsdata->set &= ~(CLIMB_SET); + + last_fix->time = fix->time; + + if (!equal_or_nan (fix->climb, last_fix->climb)){ + + /* velocity has changed */ + changed = TRUE; + last_fix->climb = fix->climb; + } + } + + if (changed) { + gpsd->last_velo_fields = GEOCLUE_VELOCITY_FIELDS_NONE; + gpsd->last_velo_fields |= (isnan (last_fix->track)) ? + 0 : GEOCLUE_VELOCITY_FIELDS_DIRECTION; + gpsd->last_velo_fields |= (isnan (last_fix->speed)) ? + 0 : GEOCLUE_VELOCITY_FIELDS_SPEED; + gpsd->last_velo_fields |= (isnan (last_fix->climb)) ? + 0 : GEOCLUE_VELOCITY_FIELDS_CLIMB; + + gc_iface_velocity_emit_velocity_changed + (GC_IFACE_VELOCITY (gpsd), gpsd->last_velo_fields, + (int)(last_fix->time+0.5), + last_fix->speed, last_fix->track, last_fix->climb); + } +} + +static void +geoclue_gpsd_update_status (GeoclueGpsd *gpsd, NmeaTag nmea_tag) +{ + GeoclueStatus status; + + /* gpsdata->online is supposedly always up-to-date */ + if (gpsd->gpsdata->online <= 0) { + status = GEOCLUE_STATUS_UNAVAILABLE; + } else if (gpsd->gpsdata->set & STATUS_SET) { + gpsd->gpsdata->set &= ~(STATUS_SET); + + if (gpsd->gpsdata->status > 0) { + status = GEOCLUE_STATUS_AVAILABLE; + } else { + status = GEOCLUE_STATUS_ACQUIRING; + } + } else { + return; + } + + geoclue_gpsd_set_status (gpsd, status); +} + +static void +gpsd_raw_hook (struct gps_data_t *gpsdata, char *message, size_t len) +{ + char *tag_str = gpsd->gpsdata->tag; + NmeaTag nmea_tag = NMEA_NONE; + + if (tag_str[0] == 'G' && tag_str[1] == 'S' && tag_str[2] == 'A') { + nmea_tag = NMEA_GSA; + } else if (tag_str[0] == 'G' && tag_str[1] == 'G' && tag_str[2] == 'A') { + nmea_tag = NMEA_GGA; + } else if (tag_str[0] == 'G' && tag_str[1] == 'S' && tag_str[2] == 'V') { + nmea_tag = NMEA_GSV; + } else if (tag_str[0] == 'R' && tag_str[1] == 'M' && tag_str[2] == 'C') { + nmea_tag = NMEA_RMC; + } + + geoclue_gpsd_update_status (gpsd, nmea_tag); + geoclue_gpsd_update_position (gpsd, nmea_tag); + geoclue_gpsd_update_velocity (gpsd, nmea_tag); +} + +static void +geoclue_gpsd_stop_gpsd (GeoclueGpsd *self) +{ + if (self->gpsdata) { + gps_close (self->gpsdata); + self->gpsdata = NULL; + } +} + +static gboolean +geoclue_gpsd_start_gpsd (GeoclueGpsd *self) +{ + self->gpsdata = gps_open (self->host, self->port); + if (self->gpsdata) { + gps_stream(self->gpsdata, WATCH_ENABLE | WATCH_NMEA | POLL_NONBLOCK, NULL); + gps_set_raw_hook (self->gpsdata, gpsd_raw_hook); + return TRUE; + } else { + g_warning ("gps_open() failed, is gpsd running (host=%s,port=%s)?", self->host, self->port); + return FALSE; + } +} + +gboolean +gpsd_poll(gpointer data) +{ + GeoclueGpsd *self = (GeoclueGpsd*)data; + if (self->gpsdata) { + if (gps_poll(self->gpsdata) < 0) { + geoclue_gpsd_set_status (self, GEOCLUE_STATUS_ERROR); + geoclue_gpsd_stop_gpsd(self); + return FALSE; + } + } + return TRUE; +} + +static void +geoclue_gpsd_init (GeoclueGpsd *self) +{ + self->gpsdata = NULL; + self->last_fix = g_new0 (gps_fix, 1); + + self->last_pos_fields = GEOCLUE_POSITION_FIELDS_NONE; + self->last_velo_fields = GEOCLUE_VELOCITY_FIELDS_NONE; + self->last_accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0, 0); + + gc_provider_set_details (GC_PROVIDER (self), + "org.freedesktop.Geoclue.Providers.Gpsd", + "/org/freedesktop/Geoclue/Providers/Gpsd", + "Gpsd", "Gpsd provider"); + + self->port = g_strdup (DEFAULT_GPSD_PORT); + self->host = NULL; + geoclue_gpsd_set_status (self, GEOCLUE_STATUS_ACQUIRING); + if (!geoclue_gpsd_start_gpsd (self)) { + geoclue_gpsd_set_status (self, GEOCLUE_STATUS_ERROR); + } +} + +static gboolean +get_position (GcIfacePosition *gc, + GeocluePositionFields *fields, + int *timestamp, + double *latitude, + double *longitude, + double *altitude, + GeoclueAccuracy **accuracy, + GError **error) +{ + GeoclueGpsd *gpsd = GEOCLUE_GPSD (gc); + + *timestamp = (int)(gpsd->last_fix->time+0.5); + *latitude = gpsd->last_fix->latitude; + *longitude = gpsd->last_fix->longitude; + *altitude = gpsd->last_fix->altitude; + *fields = gpsd->last_pos_fields; + *accuracy = geoclue_accuracy_copy (gpsd->last_accuracy); + + return TRUE; +} + +static void +geoclue_gpsd_position_init (GcIfacePositionClass *iface) +{ + iface->get_position = get_position; +} + +static gboolean +get_velocity (GcIfaceVelocity *gc, + GeoclueVelocityFields *fields, + int *timestamp, + double *speed, + double *direction, + double *climb, + GError **error) +{ + GeoclueGpsd *gpsd = GEOCLUE_GPSD (gc); + + *timestamp = (int)(gpsd->last_fix->time+0.5); + *speed = gpsd->last_fix->speed; + *direction = gpsd->last_fix->track; + *climb = gpsd->last_fix->climb; + *fields = gpsd->last_velo_fields; + + return TRUE; +} + +static void +geoclue_gpsd_velocity_init (GcIfaceVelocityClass *iface) +{ + iface->get_velocity = get_velocity; +} + +int +main (int argc, + char **argv) +{ + g_type_init (); + + gpsd = g_object_new (GEOCLUE_TYPE_GPSD, NULL); + + gpsd->loop = g_main_loop_new (NULL, TRUE); + g_timeout_add(500, gpsd_poll, (gpointer)gpsd); + + g_main_loop_run (gpsd->loop); + + g_main_loop_unref (gpsd->loop); + g_object_unref (gpsd); + + return 0; +} diff --git a/.pc/tizen.patch/providers/gsmloc/Makefile.am b/.pc/tizen.patch/providers/gsmloc/Makefile.am new file mode 100755 index 0000000..1820f8c --- /dev/null +++ b/.pc/tizen.patch/providers/gsmloc/Makefile.am @@ -0,0 +1,77 @@ +libexec_PROGRAMS = \ + geoclue-gsmloc + +nodist_geoclue_gsmloc_SOURCES = \ + ofono-marshal.c \ + ofono-marshal.h \ + ofono-manager-bindings.h \ + ofono-modem-bindings.h \ + ofono-network-registration-bindings.h \ + ofono-network-operator-bindings.h \ + mm-marshal.c \ + mm-marshal.h + +BUILT_SOURCES = \ + $(nodist_geoclue_gsmloc_SOURCES) + +geoclue_gsmloc_SOURCES = \ + mcc.h \ + geoclue-gsmloc.c \ + geoclue-gsmloc-ofono.c \ + geoclue-gsmloc-ofono.h \ + geoclue-gsmloc-mm.c \ + geoclue-gsmloc-mm.h + + +geoclue_gsmloc_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) + +geoclue_gsmloc_LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-gsmloc.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Gsmloc.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + ofono-marshal.list \ + ofono-manager.xml \ + ofono-modem.xml \ + ofono-network-operator.xml \ + ofono-network-registration.xml \ + mm-marshal.list \ + $(service_in_files) \ + $(providers_DATA) + +CLEANFILES = \ + $(BUILT_SOURCES) + +DISTCLEANFILES = \ + $(service_DATA) + +%-bindings.h: stamp-%-bindings.h + @true +stamp-%-bindings.h: %.xml + $(AM_V_GEN) $(DBUS_BINDING_TOOL) --mode=glib-client $< > xgen-$(@F) \ + && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \ + && rm -f xgen-$(@F) \ + && echo timestamp > $(@F) + +ofono-marshal.h: ofono-marshal.list $(GLIB_GENMARSHAL) + $(GLIB_GENMARSHAL) $< --header --prefix=ofono_marshal > $@ +ofono-marshal.c: ofono-marshal.list ofono-marshal.h $(GLIB_GENMARSHAL) + $(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=ofono_marshal $(srcdir)/ofono-marshal.list --header --body >> $@ + +mm-marshal.h: mm-marshal.list $(GLIB_GENMARSHAL) + $(AM_V_GEN) $(GLIB_GENMARSHAL) $< --header --prefix=mm_marshal > $@ +mm-marshal.c: mm-marshal.list mm-marshal.h $(GLIB_GENMARSHAL) + $(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=mm_marshal $(srcdir)/mm-marshal.list --header --body >> $@ diff --git a/.pc/tizen.patch/providers/gsmloc/geoclue-gsmloc-mm.c b/.pc/tizen.patch/providers/gsmloc/geoclue-gsmloc-mm.c new file mode 100755 index 0000000..bd882d1 --- /dev/null +++ b/.pc/tizen.patch/providers/gsmloc/geoclue-gsmloc-mm.c @@ -0,0 +1,779 @@ +/* + * Geoclue + * geoclue-gsmloc-mm.c - An Address/Position provider for ModemManager + * + * Author: Dan Williams <dcbw@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <config.h> + +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +#include <glib-object.h> +#include <dbus/dbus.h> +#include <dbus/dbus-glib-bindings.h> + +#include "geoclue-gsmloc-mm.h" + +#include "mm-marshal.h" + +#define MM_DBUS_SERVICE "org.freedesktop.ModemManager" +#define MM_DBUS_PATH "/org/freedesktop/ModemManager" +#define MM_DBUS_INTERFACE "org.freedesktop.ModemManager" +#define MM_DBUS_LOC_INTERFACE "org.freedesktop.ModemManager.Modem.Location" +#define DBUS_PROPS_INTERFACE "org.freedesktop.DBus.Properties" +#define MM_DBUS_MODEM_INTERFACE "org.freedesktop.ModemManager.Modem" + +G_DEFINE_TYPE (GeoclueGsmlocMm, geoclue_gsmloc_mm, G_TYPE_OBJECT) + +#define GEOCLUE_GSMLOC_MM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GEOCLUE_TYPE_GSMLOC_MM, GeoclueGsmlocMmPrivate)) + +typedef struct { + char *path; + + DBusGProxy *loc_proxy; + DBusGProxy *props_proxy; + DBusGProxy *modem_proxy; + + gboolean got_enabled; + gboolean enabled; + gboolean enabling; + + gboolean got_loc_enabled; + gboolean loc_enabled; + gboolean loc_enabling; + gboolean got_initial_loc; + + /* Whether the modem signals its location or whether we + * have to poll for it. + */ + gboolean signals; + guint loc_idle; + + gboolean has_location; + + gpointer owner; +} Modem; + +typedef struct { + DBusGConnection *bus; + DBusGProxy *dbus_proxy; + + /* Listens for device add/remove events */ + DBusGProxy *mm_proxy; + DBusGProxy *props_proxy; + + /* List of Modem objects */ + GSList *modems; +} GeoclueGsmlocMmPrivate; + +enum { + PROP_0, + PROP_AVAILABLE, +}; + +enum { + NETWORK_DATA_CHANGED, + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = {0}; + +#define LOC_CAP_GSM_LACCI 0x02 + +gboolean mm_debug = FALSE; + +#define debugmsg(fmt, args...) \ + { if (mm_debug) { g_debug (fmt, ##args); } } + + +static gboolean +is_available (GeoclueGsmlocMm *self) +{ + GeoclueGsmlocMmPrivate *priv = GEOCLUE_GSMLOC_MM_GET_PRIVATE (self); + GSList *iter; + + for (iter = priv->modems; iter; iter = g_slist_next (iter)) { + Modem *modem = iter->data; + + if (modem->enabled && modem->loc_enabled && modem->has_location) + return TRUE; + } + + return FALSE; +} + +static Modem * +find_modem (GeoclueGsmlocMm *self, const char *path) +{ + GeoclueGsmlocMmPrivate *priv = GEOCLUE_GSMLOC_MM_GET_PRIVATE (self); + GSList *iter; + + g_return_val_if_fail (path != NULL, NULL); + + for (iter = priv->modems; iter; iter = g_slist_next (iter)) { + Modem *modem = iter->data; + + if (strcmp (path, modem->path) == 0) + return modem; + } + + return NULL; +} + +static void +recheck_available (GeoclueGsmlocMm *self) +{ + g_object_notify (G_OBJECT (self), "available"); +} + +static void +location_update (GeoclueGsmlocMm *self, const char *loc) +{ + char **components = NULL; + char *dec_lac = NULL, *dec_cid = NULL; + unsigned long int num; + + components = g_strsplit (loc, ",", 0); + if (!components || g_strv_length (components) < 4) { + g_warning ("%s: invalid GSM LAC/CI location: '%s'", __func__, loc); + goto out; + } + + /* convert lac to decimal */ + errno = 0; + num = strtoul (components[2], NULL, 16); + if (errno != 0) { + g_warning ("%s: cannot convert LAC '%s' to decimal!", + __func__, components[2]); + goto out; + } + dec_lac = g_strdup_printf ("%u", num); + + /* convert cell id to decimal */ + errno = 0; + num = strtoul (components[3], NULL, 16); + if (errno != 0) { + g_warning ("%s: cannot convert Cell ID '%s' to decimal!", + __func__, components[3]); + goto out; + } + dec_cid = g_strdup_printf ("%u", num); + + debugmsg ("%s: emitting location: %s/%s/%s/%s", + __func__, components[0], components[1], dec_lac, dec_cid); + g_signal_emit (G_OBJECT (self), signals[NETWORK_DATA_CHANGED], 0, + components[0], /* MCC */ + components[1], /* MNC */ + dec_lac, /* LAC */ + dec_cid); /* CID */ + +out: + if (components) + g_strfreev (components); + g_free (dec_lac); + g_free (dec_cid); +} + +static void +modem_location_update (Modem *modem, GHashTable *locations) +{ + GValue *lacci; + + /* GSMLOC only handles GSM LAC/CI location info */ + lacci = g_hash_table_lookup (locations, GUINT_TO_POINTER (LOC_CAP_GSM_LACCI)); + if (!lacci) + return; + if (!G_VALUE_HOLDS_STRING (lacci)) { + g_warning ("%s: GSM LAC/CI location member not a string!", __func__); + return; + } + + debugmsg ("%s: GSM LAC/CI: %s", __func__, g_value_get_string (lacci)); + location_update (modem->owner, g_value_get_string (lacci)); +} + +#define DBUS_TYPE_LOCATIONS (dbus_g_type_get_map ("GHashTable", G_TYPE_UINT, G_TYPE_VALUE)) +#define DBUS_TYPE_G_MAP_OF_VARIANT (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)) + +static void +loc_poll_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + GError *error = NULL; + GHashTable *locations = NULL; + + if (!dbus_g_proxy_end_call (proxy, call, &error, + DBUS_TYPE_LOCATIONS, &locations, + G_TYPE_INVALID)) { + g_warning ("%s: failed to get location: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + + modem_location_update ((Modem *) user_data, locations); + g_hash_table_destroy (locations); +} + +static gboolean +modem_loc_poll (gpointer user_data) +{ + Modem *modem = user_data; + + dbus_g_proxy_begin_call (modem->loc_proxy, "GetLocation", + loc_poll_cb, modem, NULL, + G_TYPE_INVALID); + + return TRUE; +} + +static void +modem_loc_enable_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + Modem *modem = user_data; + GError *error = NULL; + + modem->loc_enabling = FALSE; + if (!dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) { + g_warning ("%s: failed to enable modem location services: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } +} + +static void +modem_try_loc_enable (Modem *modem) +{ + /* Don't enable location services if we don't have all the modem's + * status yet or if location services are already enabled. + */ + + if (!modem->got_loc_enabled || + !modem->enabled || + !modem->has_location || + !modem->got_loc_enabled || + modem->loc_enabled || + modem->loc_enabling) + return; + + modem->loc_enabling = TRUE; + debugmsg ("%s: (%s) enabling location services...", __func__, modem->path); + dbus_g_proxy_begin_call (modem->loc_proxy, "Enable", + modem_loc_enable_cb, modem, NULL, + G_TYPE_BOOLEAN, TRUE, /* enable */ + G_TYPE_BOOLEAN, TRUE, /* signal location changes */ + G_TYPE_INVALID); +} + +static void +modem_enable_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + Modem *modem = user_data; + GError *error = NULL; + + modem->enabling = FALSE; + if (!dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) { + g_warning ("%s: failed to enable modem: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + + /* enable location services */ + modem_try_loc_enable (modem); +} + +static void +modem_properties_changed (DBusGProxy *proxy, + const char *interface, + GHashTable *props, + gpointer user_data) +{ + Modem *modem = user_data; + GValue *value; + gboolean old_avail = modem->enabled && modem->loc_enabled && modem->has_location; + gboolean new_avail; + + if (strcmp (interface, MM_DBUS_MODEM_INTERFACE) == 0) { + value = g_hash_table_lookup (props, "Enabled"); + if (value && G_VALUE_HOLDS_BOOLEAN (value)) { + modem->enabled = g_value_get_boolean (value); + modem->got_enabled = TRUE; + debugmsg ("%s: (%s) modem %s", __func__, modem->path, + modem->enabled ? "enabled" : "disabled"); + } + } else if (strcmp (interface, MM_DBUS_LOC_INTERFACE) == 0) { + value = g_hash_table_lookup (props, "Enabled"); + if (value && G_VALUE_HOLDS_BOOLEAN (value)) { + modem->loc_enabled = g_value_get_boolean (value); + modem->got_loc_enabled = TRUE; + debugmsg ("%s: (%s) modem location services %s", + __func__, modem->path, + modem->loc_enabled ? "enabled" : "disabled"); + } + + value = g_hash_table_lookup (props, "SignalsLocation"); + if (value && G_VALUE_HOLDS_BOOLEAN (value)) { + modem->signals = g_value_get_boolean (value); + debugmsg ("%s: (%s) modem %s signal location updates", + __func__, modem->path, + modem->signals ? "will" : "does not"); + } + + value = g_hash_table_lookup (props, "Capabilities"); + if (value && G_VALUE_HOLDS_UINT (value)) { + debugmsg ("%s: (%s) modem location capabilities: 0x%X", + __func__, modem->path, + g_value_get_uint (value)); + + if (g_value_get_uint (value) & LOC_CAP_GSM_LACCI) + modem->has_location = TRUE; + } + + value = g_hash_table_lookup (props, "Location"); + if (value && G_VALUE_HOLDS_BOXED (value)) + modem_location_update (modem, (GHashTable *) g_value_get_boxed (value)); + } + + new_avail = modem->enabled && modem->loc_enabled && modem->has_location; + + /* If the modem doesn't signal its location, start polling for the + * location now. + */ + if (new_avail && !modem->signals && !modem->loc_idle) { + modem->loc_idle = g_timeout_add_seconds (20, modem_loc_poll, modem); + /* Kick off a quick location request */ + modem_loc_poll (modem); + } + + /* If the modem is no longer enabled, or it now signals its location + * then we no longer need to poll. + */ + if ((!new_avail || modem->signals) && modem->loc_idle) + g_source_remove (modem->loc_idle); + + /* Tell the manager to recheck availability of location info */ + if (old_avail != new_avail) + recheck_available (modem->owner); + + /* If we've successfully retrieved modem properties and the modem + * isn't enabled, do that now. + */ + if (modem->got_enabled && !modem->enabled && !modem->enabling) { + debugmsg ("%s: (%s) enabling...", __func__, modem->path); + modem->enabling = TRUE; + dbus_g_proxy_begin_call (modem->modem_proxy, "Enable", + modem_enable_cb, modem, NULL, + G_TYPE_BOOLEAN, TRUE, G_TYPE_INVALID); + } + + /* If the modem was already enabled but location services weren't, + * enable them now. + */ + modem_try_loc_enable (modem); + + /* After location is enabled, try to get the location ASAP */ + if (modem->has_location && modem->loc_enabled && !modem->got_initial_loc) { + modem->got_initial_loc = TRUE; + modem_loc_poll (modem); + } +} + +static void +modem_props_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + GError *error = NULL; + GHashTable *props = NULL; + Modem *modem = user_data; + + if (!dbus_g_proxy_end_call (proxy, call, &error, + DBUS_TYPE_G_MAP_OF_VARIANT, &props, + G_TYPE_INVALID)) { + g_warning ("%s: failed to get modem interface properties: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + + modem_properties_changed (modem->loc_proxy, MM_DBUS_MODEM_INTERFACE, props, modem); + g_hash_table_destroy (props); +} + +static void +loc_props_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + GError *error = NULL; + GHashTable *props = NULL; + Modem *modem = user_data; + + if (!dbus_g_proxy_end_call (proxy, call, &error, + DBUS_TYPE_G_MAP_OF_VARIANT, &props, + G_TYPE_INVALID)) { + g_warning ("%s: failed to get location interface properties: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + + modem_properties_changed (modem->loc_proxy, MM_DBUS_LOC_INTERFACE, props, modem); + g_hash_table_destroy (props); + + /* Now that we know the device supports location services, get basic + * modem properties and start grabbing location info. + */ + dbus_g_proxy_begin_call (modem->props_proxy, "GetAll", + modem_props_cb, modem, NULL, + G_TYPE_STRING, MM_DBUS_MODEM_INTERFACE, G_TYPE_INVALID); +} + +static Modem * +modem_new (DBusGConnection *bus, const char *path, gpointer owner) +{ + Modem *modem; + + modem = g_slice_new0 (Modem); + modem->owner = owner; + modem->path = g_strdup (path); + + modem->loc_proxy = dbus_g_proxy_new_for_name (bus, + MM_DBUS_SERVICE, + path, + MM_DBUS_LOC_INTERFACE); + + modem->modem_proxy = dbus_g_proxy_new_for_name (bus, + MM_DBUS_SERVICE, + path, + MM_DBUS_MODEM_INTERFACE); + + /* Listen for property changes */ + modem->props_proxy = dbus_g_proxy_new_for_name (bus, + MM_DBUS_SERVICE, + path, + "org.freedesktop.DBus.Properties"); + dbus_g_object_register_marshaller (mm_marshal_VOID__STRING_BOXED, + G_TYPE_NONE, + G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_add_signal (modem->props_proxy, "MmPropertiesChanged", + G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (modem->props_proxy, "MmPropertiesChanged", + G_CALLBACK (modem_properties_changed), + modem, + NULL); + + debugmsg ("%s: (%s) modem created", __func__, path); + + /* Check if the Location interface is actually supported before doing + * anything with the modem, because if it's not, we don't care about + * the modem at all. + */ + dbus_g_proxy_begin_call (modem->props_proxy, "GetAll", + loc_props_cb, modem, NULL, + G_TYPE_STRING, MM_DBUS_LOC_INTERFACE, G_TYPE_INVALID); + + return modem; +} + +static void +modem_free (Modem *modem) +{ + + debugmsg ("%s: (%s) modem removed", __func__, modem->path); + + g_free (modem->path); + g_object_unref (modem->loc_proxy); + g_object_unref (modem->modem_proxy); + g_object_unref (modem->props_proxy); + + if (modem->loc_idle) + g_source_remove (modem->loc_idle); + + memset (modem, 0, sizeof (Modem)); + g_slice_free (Modem, modem); +} + +static void +modem_added (DBusGProxy *proxy, const char *path, gpointer user_data) +{ + GeoclueGsmlocMm *self = GEOCLUE_GSMLOC_MM (user_data); + GeoclueGsmlocMmPrivate *priv = GEOCLUE_GSMLOC_MM_GET_PRIVATE (self); + Modem *modem; + + if (!find_modem (self, path)) { + modem = modem_new (priv->bus, path, self); + priv->modems = g_slist_prepend (priv->modems, modem); + } +} + +static void +enumerate_modems_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + GPtrArray *modems; + GError *error = NULL; + int i; + + if (!dbus_g_proxy_end_call (proxy, call, &error, + dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &modems, + G_TYPE_INVALID)) { + g_warning ("%s: failed to enumerate modems: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + + for (i = 0; i < modems->len; i++) { + char *path = g_ptr_array_index (modems, i); + + modem_added (NULL, path, GEOCLUE_GSMLOC_MM (user_data)); + g_free (path); + } + g_ptr_array_free (modems, TRUE); +} + +static void +enumerate_modems (GeoclueGsmlocMm *self) +{ + GeoclueGsmlocMmPrivate *priv = GEOCLUE_GSMLOC_MM_GET_PRIVATE (self); + + dbus_g_proxy_begin_call (priv->mm_proxy, "EnumerateDevices", + enumerate_modems_cb, self, NULL, + G_TYPE_INVALID); +} + +static void +modem_removed (DBusGProxy *proxy, const char *path, gpointer user_data) +{ + GeoclueGsmlocMm *self = GEOCLUE_GSMLOC_MM (user_data); + GeoclueGsmlocMmPrivate *priv = GEOCLUE_GSMLOC_MM_GET_PRIVATE (self); + Modem *modem; + + modem = find_modem (self, path); + if (modem) { + gboolean old_available = is_available (self); + + priv->modems = g_slist_remove (priv->modems, modem); + modem_free (modem); + if (is_available (self) != old_available) + g_object_notify (G_OBJECT (self), "available"); + } +} + +static void +kill_modems (GeoclueGsmlocMm *self) +{ + GeoclueGsmlocMmPrivate *priv = GEOCLUE_GSMLOC_MM_GET_PRIVATE (self); + gboolean old_available = is_available (self); + GSList *iter; + + /* Kill all modems */ + for (iter = priv->modems; iter; iter = g_slist_next (iter)) + modem_free ((Modem *) iter->data); + g_slist_free (priv->modems); + priv->modems = NULL; + + /* No more modems; clearly location is no longer available */ + if (old_available) + g_object_notify (G_OBJECT (self), "available"); +} + +static void +name_owner_changed (DBusGProxy *proxy, + const char *name, + const char *old_owner, + const char *new_owner, + gpointer user_data) +{ + gboolean old_owner_good; + gboolean new_owner_good; + + if (strcmp (MM_DBUS_SERVICE, name) != 0) + return; + + old_owner_good = (old_owner && strlen (old_owner)); + new_owner_good = (new_owner && strlen (new_owner)); + + if (!old_owner_good && new_owner_good) { + debugmsg ("ModemManager appeared"); + enumerate_modems (GEOCLUE_GSMLOC_MM (user_data)); + } else if (old_owner_good && !new_owner_good) { + debugmsg ("ModemManager disappeared"); + kill_modems (GEOCLUE_GSMLOC_MM (user_data)); + } +} + +GeoclueGsmlocMm * +geoclue_gsmloc_mm_new (void) +{ + return (GeoclueGsmlocMm *) g_object_new (GEOCLUE_TYPE_GSMLOC_MM, NULL); +} + +static gboolean +mm_alive (DBusGProxy *proxy) +{ + char *owner = NULL; + gboolean owned = FALSE; + GError *error = NULL; + + if (dbus_g_proxy_call_with_timeout (proxy, + "GetNameOwner", 2000, &error, + G_TYPE_STRING, MM_DBUS_SERVICE, + G_TYPE_INVALID, + G_TYPE_STRING, &owner, + G_TYPE_INVALID)) { + owned = !!owner; + g_free (owner); + } + return owned; +} + +static void +geoclue_gsmloc_mm_init (GeoclueGsmlocMm *self) +{ + GeoclueGsmlocMmPrivate *priv = GEOCLUE_GSMLOC_MM_GET_PRIVATE (self); + + if (getenv ("GEOCLUE_GSMLOC_MM_DEBUG")) + mm_debug = TRUE; + + priv->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL); + if (!priv->bus) { + g_warning ("Failed to acquire a connection to the D-Bus system bus."); + return; + } + + priv->dbus_proxy = dbus_g_proxy_new_for_name (priv->bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS); + /* Handle ModemManager restarts */ + dbus_g_proxy_add_signal (priv->dbus_proxy, "NameOwnerChanged", + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->dbus_proxy, "NameOwnerChanged", + G_CALLBACK (name_owner_changed), + self, NULL); + + priv->mm_proxy = dbus_g_proxy_new_for_name (priv->bus, + MM_DBUS_SERVICE, + MM_DBUS_PATH, + MM_DBUS_INTERFACE); + g_assert (priv->mm_proxy); + + dbus_g_proxy_add_signal (priv->mm_proxy, "DeviceAdded", + DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->mm_proxy, "DeviceAdded", + G_CALLBACK (modem_added), self, NULL); + dbus_g_proxy_add_signal (priv->mm_proxy, "DeviceRemoved", + DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->mm_proxy, "DeviceRemoved", + G_CALLBACK (modem_removed), self, NULL); + + if (mm_alive (priv->dbus_proxy)) { + debugmsg ("ModemManager is alive"); + enumerate_modems (self); + } +} + +static void +dispose (GObject *object) +{ + GeoclueGsmlocMmPrivate *priv = GEOCLUE_GSMLOC_MM_GET_PRIVATE (object); + + kill_modems (GEOCLUE_GSMLOC_MM (object)); + + /* Stop listening to ModemManager */ + if (priv->mm_proxy) { + g_object_unref (priv->mm_proxy); + priv->mm_proxy = NULL; + } + + if (priv->props_proxy) { + g_object_unref (priv->props_proxy); + priv->props_proxy = NULL; + } + + if (priv->dbus_proxy) { + g_object_unref (priv->dbus_proxy); + priv->dbus_proxy = NULL; + } + + G_OBJECT_CLASS (geoclue_gsmloc_mm_parent_class)->dispose (object); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_AVAILABLE: + g_value_set_boolean (value, is_available (GEOCLUE_GSMLOC_MM (object))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +geoclue_gsmloc_mm_class_init (GeoclueGsmlocMmClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GeoclueGsmlocMmPrivate)); + + /* virtual methods */ + object_class->get_property = get_property; + object_class->dispose = dispose; + + /* properties */ + g_object_class_install_property + (object_class, PROP_AVAILABLE, + g_param_spec_boolean ("available", + "Available", + "Whether any mobile broadband device is " + "providing location information at this " + "time.", + FALSE, + G_PARAM_READABLE)); + + /* signals */ + signals[NETWORK_DATA_CHANGED] = + g_signal_new ("network-data-changed", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, 0, + NULL, NULL, + mm_marshal_VOID__STRING_STRING_STRING_STRING, + G_TYPE_NONE, 4, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); +} + diff --git a/.pc/tizen.patch/providers/gsmloc/geoclue-gsmloc-mm.h b/.pc/tizen.patch/providers/gsmloc/geoclue-gsmloc-mm.h new file mode 100755 index 0000000..8daf1eb --- /dev/null +++ b/.pc/tizen.patch/providers/gsmloc/geoclue-gsmloc-mm.h @@ -0,0 +1,56 @@ +/* + * Geoclue + * geoclue-gsmloc-mm.h - An Address/Position provider for ModemManager + * + * Author: Dan Williams <dcbw@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _GEOCLUE_GSMLOC_MM +#define _GEOCLUE_GSMLOC_MM + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define GEOCLUE_TYPE_GSMLOC_MM (geoclue_gsmloc_mm_get_type ()) + +#define GEOCLUE_GSMLOC_MM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_GSMLOC_MM, GeoclueGsmlocMm)) +#define GEOCLUE_GSMLOC_MM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEOCLUE_TYPE_GSMLOC_MM, GeoclueGsmlocMmClass)) +#define GEOCLUE_IS_GSMLOC_MM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_GSMLOC_MM)) +#define GEOCLUE_IS_GSMLOC_MM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEOCLUE_TYPE_GSMLOC_MM)) + +typedef struct _GeoclueGsmlocMm { + GObject parent; +} GeoclueGsmlocMm; + +typedef struct _GeoclueGsmlocMmClass { + GObjectClass parent_class; + + void (*network_data_changed) (GeoclueGsmlocMm *mm, + char *mcc, char *mnc, + char *lac, char *cid); +} GeoclueGsmlocMmClass; + +GType geoclue_gsmloc_mm_get_type (void); + +GeoclueGsmlocMm *geoclue_gsmloc_mm_new (void); + +G_END_DECLS + +#endif /* _GEOCLUE_GSMLOC_MM */ + diff --git a/.pc/tizen.patch/providers/gsmloc/geoclue-gsmloc.c b/.pc/tizen.patch/providers/gsmloc/geoclue-gsmloc.c new file mode 100755 index 0000000..6d8b5ba --- /dev/null +++ b/.pc/tizen.patch/providers/gsmloc/geoclue-gsmloc.c @@ -0,0 +1,459 @@ +/* + * Geoclue + * geoclue-gsmloc.c - A GSM cell based Position provider + * + * Author: Jussi Kukkonen <jku@linux.intel.com> + * Copyright 2008 by Garmin Ltd. or its subsidiaries + * 2010 Intel Corporation + * 2010 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + /** + * Gsmloc provider is a position and address provider that uses GSM cell + * location and the webservice http://www.opencellid.org/ (a similar service + * used to live at gsmloc.org, hence the name). The web service does not + * provide any address data: that is done with a + * "mobile country code -> ISO country code" lookup table: as a result address + * will only ever have country code and country fields. + * + * Gsmloc requires the oFono or ModemManager telephony stacks to work -- more + * IMSI data sources could be added fairly easily. + **/ + +#include <config.h> + +#include <time.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include <glib-object.h> +#include <dbus/dbus-glib-bindings.h> + +#include <geoclue/gc-web-service.h> +#include <geoclue/gc-provider.h> +#include <geoclue/geoclue-error.h> +#include <geoclue/gc-iface-position.h> +#include <geoclue/gc-iface-address.h> + +/* ofono implementation */ +#include "geoclue-gsmloc-ofono.h" + +/* ModemManager implementation */ +#include "geoclue-gsmloc-mm.h" + +/* country code list */ +#include "mcc.h" + +#define GEOCLUE_DBUS_SERVICE_GSMLOC "org.freedesktop.Geoclue.Providers.Gsmloc" +#define GEOCLUE_DBUS_PATH_GSMLOC "/org/freedesktop/Geoclue/Providers/Gsmloc" + +#define OPENCELLID_URL "http://www.opencellid.org/cell/get" +#define OPENCELLID_LAT "/rsp/cell/@lat" +#define OPENCELLID_LON "/rsp/cell/@lon" +#define OPENCELLID_CID "/rsp/cell/@cellId" + +#define GEOCLUE_TYPE_GSMLOC (geoclue_gsmloc_get_type ()) +#define GEOCLUE_GSMLOC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_GSMLOC, GeoclueGsmloc)) + +typedef struct _GeoclueGsmloc GeoclueGsmloc; + +struct _GeoclueGsmloc { + GcProvider parent; + GMainLoop *loop; + GcWebService *web_service; + + GeoclueGsmlocOfono *ofono; + GeoclueGsmlocMm *mm; + + /* current data */ + char *mcc; + char *mnc; + char *lac; + char *cid; + GeocluePositionFields last_position_fields; + GeoclueAccuracyLevel last_accuracy_level; + double last_lat; + double last_lon; + + GHashTable *address; +}; + +typedef struct _GeoclueGsmlocClass { + GcProviderClass parent_class; +} GeoclueGsmlocClass; + + +static void geoclue_gsmloc_init (GeoclueGsmloc *gsmloc); +static void geoclue_gsmloc_position_init (GcIfacePositionClass *iface); +static void geoclue_gsmloc_address_init (GcIfaceAddressClass *iface); + +G_DEFINE_TYPE_WITH_CODE (GeoclueGsmloc, geoclue_gsmloc, GC_TYPE_PROVIDER, + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION, + geoclue_gsmloc_position_init) + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_ADDRESS, + geoclue_gsmloc_address_init)) + + +/* Geoclue interface implementation */ +static gboolean +geoclue_gsmloc_get_status (GcIfaceGeoclue *iface, + GeoclueStatus *status, + GError **error) +{ + GeoclueGsmloc *gsmloc = GEOCLUE_GSMLOC (iface); + gboolean ofono_available; + gboolean mm_available; + + g_object_get (gsmloc->ofono, "available", &ofono_available, NULL); + g_object_get (gsmloc->mm, "available", &mm_available, NULL); + + if (!ofono_available && !mm_available) { + *status = GEOCLUE_STATUS_ERROR; + } else if (!gsmloc->mcc || !gsmloc->mnc || + !gsmloc->lac || !gsmloc->cid) { + *status = GEOCLUE_STATUS_UNAVAILABLE; + } else { + *status = GEOCLUE_STATUS_AVAILABLE; + } + return TRUE; +} + +static void +shutdown (GcProvider *provider) +{ + GeoclueGsmloc *gsmloc = GEOCLUE_GSMLOC (provider); + g_main_loop_quit (gsmloc->loop); +} + +static gboolean +geoclue_gsmloc_query_opencellid (GeoclueGsmloc *gsmloc) +{ + double lat, lon; + GeocluePositionFields fields = GEOCLUE_POSITION_FIELDS_NONE; + GeoclueAccuracyLevel level = GEOCLUE_ACCURACY_LEVEL_NONE; + + if (gsmloc->mcc && gsmloc->mnc && + gsmloc->lac && gsmloc->cid) { + + if (gc_web_service_query (gsmloc->web_service, NULL, + "mcc", gsmloc->mcc, + "mnc", gsmloc->mnc, + "lac", gsmloc->lac, + "cellid", gsmloc->cid, + (char *)0)) { + + if (gc_web_service_get_double (gsmloc->web_service, + &lat, OPENCELLID_LAT)) { + fields |= GEOCLUE_POSITION_FIELDS_LATITUDE; + } + if (gc_web_service_get_double (gsmloc->web_service, + &lon, OPENCELLID_LON)) { + fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE; + } + + if (fields != GEOCLUE_POSITION_FIELDS_NONE) { + char *retval_cid; + /* if cellid is not present, location is for the local area code. + * the accuracy might be an overstatement -- I have no idea how + * big LACs typically are */ + level = GEOCLUE_ACCURACY_LEVEL_LOCALITY; + if (gc_web_service_get_string (gsmloc->web_service, + &retval_cid, OPENCELLID_CID)) { + if (retval_cid && strlen (retval_cid) != 0) { + level = GEOCLUE_ACCURACY_LEVEL_POSTALCODE; + } + g_free (retval_cid); + } + } + } + } + + if (fields != gsmloc->last_position_fields || + (fields != GEOCLUE_POSITION_FIELDS_NONE && + (lat != gsmloc->last_lat || + lon != gsmloc->last_lon || + level != gsmloc->last_accuracy_level))) { + GeoclueAccuracy *acc; + + /* position changed */ + + gsmloc->last_position_fields = fields; + gsmloc->last_accuracy_level = level; + gsmloc->last_lat = lat; + gsmloc->last_lon = lon; + + acc = geoclue_accuracy_new (gsmloc->last_accuracy_level, 0.0, 0.0); + gc_iface_position_emit_position_changed (GC_IFACE_POSITION (gsmloc), + fields, + time (NULL), + lat, lon, 0.0, + acc); + geoclue_accuracy_free (acc); + return TRUE; + } + + return FALSE; +} + +static void +geoclue_gsmloc_update_address (GeoclueGsmloc *gsmloc) +{ + char *countrycode = NULL; + const char *old_countrycode; + gboolean changed = FALSE; + GeoclueAccuracy *acc; + + if (gsmloc->mcc) { + gint64 i; + i = g_ascii_strtoll (gsmloc->mcc, NULL, 10); + if (i > 0 && i < 800 && mcc_country_codes[i]) { + countrycode = mcc_country_codes[i]; + } + } + + old_countrycode = g_hash_table_lookup (gsmloc->address, + GEOCLUE_ADDRESS_KEY_COUNTRYCODE); + if (g_strcmp0 (old_countrycode, countrycode) != 0) { + changed = TRUE; + } + + if (countrycode) { + g_hash_table_insert (gsmloc->address, + GEOCLUE_ADDRESS_KEY_COUNTRYCODE, g_strdup (countrycode)); + acc = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_COUNTRY, 0.0, 0.0); + } else { + g_hash_table_remove (gsmloc->address, GEOCLUE_ADDRESS_KEY_COUNTRYCODE); + g_hash_table_remove (gsmloc->address, GEOCLUE_ADDRESS_KEY_COUNTRY); + acc = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0.0, 0.0); + } + geoclue_address_details_set_country_from_code (gsmloc->address); + + if (changed) { + gc_iface_address_emit_address_changed (GC_IFACE_ADDRESS (gsmloc), + time (NULL), + gsmloc->address, + acc); + + } + geoclue_accuracy_free (acc); +} +static void +geoclue_gsmloc_set_cell (GeoclueGsmloc *gsmloc, + const char *mcc, const char *mnc, + const char *lac, const char *cid) +{ + g_free (gsmloc->mcc); + g_free (gsmloc->mnc); + g_free (gsmloc->lac); + g_free (gsmloc->cid); + + gsmloc->mcc = g_strdup (mcc); + gsmloc->mnc = g_strdup (mnc); + gsmloc->lac = g_strdup (lac); + gsmloc->cid = g_strdup (cid); + + geoclue_gsmloc_update_address (gsmloc); + geoclue_gsmloc_query_opencellid (gsmloc); +} + +static void +network_data_changed_cb (gpointer connection_manager, + const char *mcc, const char *mnc, + const char *lac, const char *cid, + GeoclueGsmloc *gsmloc) +{ + if (g_strcmp0 (mcc, gsmloc->mcc) != 0 || + g_strcmp0 (mnc, gsmloc->mnc) != 0 || + g_strcmp0 (lac, gsmloc->lac) != 0 || + g_strcmp0 (cid, gsmloc->cid) != 0) { + + /* new cell data, do a opencellid lookup */ + geoclue_gsmloc_set_cell (gsmloc, mcc, mnc, lac, cid); + } +} + +/* Position interface implementation */ + +static gboolean +geoclue_gsmloc_get_position (GcIfacePosition *iface, + GeocluePositionFields *fields, + int *timestamp, + double *latitude, + double *longitude, + double *altitude, + GeoclueAccuracy **accuracy, + GError **error) +{ + GeoclueGsmloc *gsmloc; + + gsmloc = (GEOCLUE_GSMLOC (iface)); + + if (gsmloc->last_position_fields == GEOCLUE_POSITION_FIELDS_NONE) { + /* re-query in case there was a network problem */ + geoclue_gsmloc_query_opencellid (gsmloc); + } + + if (timestamp) { + *timestamp = time (NULL); + } + + if (fields) { + *fields = gsmloc->last_position_fields; + } + if (latitude) { + *latitude = gsmloc->last_lat; + } + if (longitude) { + *longitude = gsmloc->last_lon; + } + if (accuracy) { + *accuracy = geoclue_accuracy_new (gsmloc->last_accuracy_level, 0, 0); + } + + return TRUE; +} + +/* Address interface implementation */ +static gboolean +geoclue_gsmloc_get_address (GcIfaceAddress *iface, + int *timestamp, + GHashTable **address, + GeoclueAccuracy **accuracy, + GError **error) +{ + GeoclueGsmloc *obj = GEOCLUE_GSMLOC (iface); + + if (address) { + *address = geoclue_address_details_copy (obj->address); + } + if (accuracy) { + GeoclueAccuracyLevel level = GEOCLUE_ACCURACY_LEVEL_NONE; + if (g_hash_table_lookup (obj->address, GEOCLUE_ADDRESS_KEY_COUNTRY)) { + level = GEOCLUE_ACCURACY_LEVEL_COUNTRY; + } + *accuracy = geoclue_accuracy_new (level, 0.0, 0.0); + } + if (timestamp) { + *timestamp = time (NULL); + } + + return TRUE; +} + + +static void +geoclue_gsmloc_dispose (GObject *obj) +{ + GeoclueGsmloc *gsmloc = GEOCLUE_GSMLOC (obj); + + if (gsmloc->ofono) { + g_signal_handlers_disconnect_by_func (gsmloc->ofono, + network_data_changed_cb, + gsmloc); + g_object_unref (gsmloc->ofono); + gsmloc->ofono = NULL; + } + + if (gsmloc->mm) { + g_signal_handlers_disconnect_by_func (gsmloc->mm, + network_data_changed_cb, + gsmloc); + g_object_unref (gsmloc->mm); + gsmloc->mm = NULL; + } + + if (gsmloc->address) { + g_hash_table_destroy (gsmloc->address); + gsmloc->address = NULL; + } + + ((GObjectClass *) geoclue_gsmloc_parent_class)->dispose (obj); +} + + +/* Initialization */ + +static void +geoclue_gsmloc_class_init (GeoclueGsmlocClass *klass) +{ + GcProviderClass *p_class = (GcProviderClass *)klass; + GObjectClass *o_class = (GObjectClass *)klass; + + p_class->shutdown = shutdown; + p_class->get_status = geoclue_gsmloc_get_status; + + o_class->dispose = geoclue_gsmloc_dispose; +} + +static void +geoclue_gsmloc_init (GeoclueGsmloc *gsmloc) +{ + gsmloc->address = geoclue_address_details_new (); + + gc_provider_set_details (GC_PROVIDER (gsmloc), + GEOCLUE_DBUS_SERVICE_GSMLOC, + GEOCLUE_DBUS_PATH_GSMLOC, + "Gsmloc", "GSM cell based position provider"); + + gsmloc->web_service = g_object_new (GC_TYPE_WEB_SERVICE, NULL); + gc_web_service_set_base_url (gsmloc->web_service, OPENCELLID_URL); + + geoclue_gsmloc_set_cell (gsmloc, NULL, NULL, NULL, NULL); + + gsmloc->address = geoclue_address_details_new (); + + /* init ofono*/ + gsmloc->ofono = geoclue_gsmloc_ofono_new (); + g_signal_connect (gsmloc->ofono, "network-data-changed", + G_CALLBACK (network_data_changed_cb), gsmloc); + + /* init mm */ + gsmloc->mm = geoclue_gsmloc_mm_new (); + g_signal_connect (gsmloc->mm, "network-data-changed", + G_CALLBACK (network_data_changed_cb), gsmloc); +} + +static void +geoclue_gsmloc_position_init (GcIfacePositionClass *iface) +{ + iface->get_position = geoclue_gsmloc_get_position; +} + +static void +geoclue_gsmloc_address_init (GcIfaceAddressClass *iface) +{ + iface->get_address = geoclue_gsmloc_get_address; +} + +int +main() +{ + g_type_init(); + + GeoclueGsmloc *o = g_object_new (GEOCLUE_TYPE_GSMLOC, NULL); + o->loop = g_main_loop_new (NULL, TRUE); + + g_main_loop_run (o->loop); + + g_main_loop_unref (o->loop); + g_object_unref (o); + + return 0; +} diff --git a/.pc/tizen.patch/providers/gsmloc/mm-marshal.list b/.pc/tizen.patch/providers/gsmloc/mm-marshal.list new file mode 100755 index 0000000..d2ce65a --- /dev/null +++ b/.pc/tizen.patch/providers/gsmloc/mm-marshal.list @@ -0,0 +1,2 @@ +VOID:STRING,STRING,STRING,STRING +VOID:STRING,BOXED diff --git a/.pc/tizen.patch/providers/gypsy/Makefile.am b/.pc/tizen.patch/providers/gypsy/Makefile.am new file mode 100755 index 0000000..937bf06 --- /dev/null +++ b/.pc/tizen.patch/providers/gypsy/Makefile.am @@ -0,0 +1,32 @@ +libexec_PROGRAMS = geoclue-gypsy + +geoclue_gypsy_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) \ + $(GYPSY_CFLAGS) + +geoclue_gypsy_LDADD = \ + $(GEOCLUE_LIBS) \ + $(GYPSY_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + +geoclue_gypsy_SOURCES = \ + geoclue-gypsy.c + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-gypsy.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Gypsy.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/providers/gypsy/geoclue-gypsy.c b/.pc/tizen.patch/providers/gypsy/geoclue-gypsy.c new file mode 100755 index 0000000..bc390ce --- /dev/null +++ b/.pc/tizen.patch/providers/gypsy/geoclue-gypsy.c @@ -0,0 +1,623 @@ +/* + * Geoclue + * geoclue-gypsy.c - Geoclue backend for Gypsy which provides the Position. + * + * Authors: Iain Holmes <iain@openedhand.com> + * Copyright 2007 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <gypsy/gypsy-control.h> +#include <gypsy/gypsy-device.h> +#include <gypsy/gypsy-position.h> +#include <gypsy/gypsy-course.h> +#include <gypsy/gypsy-accuracy.h> + +#include <geoclue/gc-provider.h> +#include <geoclue/gc-iface-position.h> +#include <geoclue/gc-iface-velocity.h> + +typedef struct { + GcProvider parent; + + char *device_name; + guint baud_rate; + + GypsyControl *control; + GypsyDevice *device; + GypsyPosition *position; + GypsyCourse *course; + GypsyAccuracy *acc; + + GMainLoop *loop; + + int timestamp; + + GeoclueStatus status; + + /* Cached so we don't have to make D-Bus method calls all the time */ + GypsyPositionFields position_fields; + double latitude; + double longitude; + double altitude; + + GypsyCourseFields course_fields; + double speed; + double direction; + double climb; + + GeoclueAccuracy *accuracy; +} GeoclueGypsy; + +typedef struct { + GcProviderClass parent_class; +} GeoclueGypsyClass; + +static void geoclue_gypsy_position_init (GcIfacePositionClass *iface); +static void geoclue_gypsy_velocity_init (GcIfaceVelocityClass *iface); + +#define GEOCLUE_TYPE_GYPSY (geoclue_gypsy_get_type ()) +#define GEOCLUE_GYPSY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_GYPSY, GeoclueGypsy)) + +G_DEFINE_TYPE_WITH_CODE (GeoclueGypsy, geoclue_gypsy, GC_TYPE_PROVIDER, + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION, + geoclue_gypsy_position_init) + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_VELOCITY, + geoclue_gypsy_velocity_init)) + + +/* GcIfaceGeoclue methods */ + +static gboolean +get_status (GcIfaceGeoclue *gc, + GeoclueStatus *status, + GError **error) +{ + GeoclueGypsy *gypsy = GEOCLUE_GYPSY (gc); + + *status = gypsy->status; + + return TRUE; +} + + +/* Compare the two fields and return TRUE if they have changed */ +static gboolean +compare_field (GypsyPositionFields fields_a, + double value_a, + GypsyPositionFields fields_b, + double value_b, + GypsyPositionFields field) +{ + /* If both fields are valid, compare the values */ + if ((fields_a & field) && (fields_b & field)) { + if (value_a == value_b) { + return FALSE; + } else { + return TRUE; + } + } + + /* Otherwise return if both the fields set are the same */ + return ((fields_a & field) != (fields_b & field)); +} + +static GeocluePositionFields +gypsy_position_to_geoclue (GypsyPositionFields fields) +{ + GeocluePositionFields gc_fields = GEOCLUE_POSITION_FIELDS_NONE; + + gc_fields |= (fields & GYPSY_POSITION_FIELDS_LATITUDE) ? GEOCLUE_POSITION_FIELDS_LATITUDE : 0; + gc_fields |= (fields & GYPSY_POSITION_FIELDS_LONGITUDE) ? GEOCLUE_POSITION_FIELDS_LONGITUDE : 0; + gc_fields |= (fields & GYPSY_POSITION_FIELDS_ALTITUDE) ? GEOCLUE_POSITION_FIELDS_ALTITUDE : 0; + + return gc_fields; +} + +static GeoclueVelocityFields +gypsy_course_to_geoclue (GypsyCourseFields fields) +{ + GeoclueVelocityFields gc_fields = GEOCLUE_VELOCITY_FIELDS_NONE; + + gc_fields |= (fields & GYPSY_COURSE_FIELDS_SPEED) ? GEOCLUE_VELOCITY_FIELDS_SPEED : 0; + gc_fields |= (fields & GYPSY_COURSE_FIELDS_DIRECTION) ? GEOCLUE_VELOCITY_FIELDS_DIRECTION : 0; + gc_fields |= (fields & GYPSY_COURSE_FIELDS_CLIMB) ? GEOCLUE_VELOCITY_FIELDS_CLIMB : 0; + + return gc_fields; +} + +static void +position_changed (GypsyPosition *position, + GypsyPositionFields fields, + int timestamp, + double latitude, + double longitude, + double altitude, + GeoclueGypsy *gypsy) +{ + gboolean changed = FALSE; + + g_print ("Gypsy position changed\n"); + gypsy->timestamp = timestamp; + if (compare_field (gypsy->position_fields, gypsy->latitude, + fields, latitude, GYPSY_POSITION_FIELDS_LATITUDE)) { + if (fields | GYPSY_POSITION_FIELDS_LATITUDE) { + gypsy->position_fields |= GYPSY_POSITION_FIELDS_LATITUDE; + gypsy->latitude = latitude; + changed = TRUE; + } + } + + if (compare_field (gypsy->position_fields, gypsy->longitude, + fields, longitude, GYPSY_POSITION_FIELDS_LONGITUDE)) { + if (fields | GYPSY_POSITION_FIELDS_LONGITUDE) { + gypsy->position_fields |= GYPSY_POSITION_FIELDS_LONGITUDE; + gypsy->longitude = longitude; + changed = TRUE; + } + } + + if (compare_field (gypsy->position_fields, gypsy->altitude, + fields, altitude, GYPSY_POSITION_FIELDS_ALTITUDE)) { + if (fields | GYPSY_POSITION_FIELDS_ALTITUDE) { + gypsy->position_fields |= GYPSY_POSITION_FIELDS_ALTITUDE; + gypsy->altitude = altitude; + changed = TRUE; + } + } + + if (changed) { + GeocluePositionFields fields; + + g_print ("Emitting signal\n"); + fields = gypsy_position_to_geoclue (gypsy->position_fields); + gc_iface_position_emit_position_changed + (GC_IFACE_POSITION (gypsy), fields, + timestamp, gypsy->latitude, gypsy->longitude, + gypsy->altitude, gypsy->accuracy); + } +} + +static void +course_changed (GypsyCourse *course, + GypsyCourseFields fields, + int timestamp, + double speed, + double direction, + double climb, + GeoclueGypsy *gypsy) +{ + gboolean changed = FALSE; + + gypsy->timestamp = timestamp; + if (compare_field (gypsy->course_fields, gypsy->speed, + fields, speed, GYPSY_COURSE_FIELDS_SPEED)) { + if (fields & GYPSY_COURSE_FIELDS_SPEED) { + gypsy->course_fields |= GYPSY_COURSE_FIELDS_SPEED; + gypsy->speed = speed; + changed = TRUE; + } + } + + if (compare_field (gypsy->course_fields, gypsy->direction, + fields, direction, GYPSY_COURSE_FIELDS_DIRECTION)) { + if (fields & GYPSY_COURSE_FIELDS_DIRECTION) { + gypsy->course_fields |= GYPSY_COURSE_FIELDS_DIRECTION; + gypsy->direction = direction; + changed = TRUE; + } + } + + if (compare_field (gypsy->course_fields, gypsy->climb, + fields, climb, GYPSY_COURSE_FIELDS_CLIMB)) { + if (fields & GYPSY_COURSE_FIELDS_CLIMB) { + gypsy->course_fields |= GYPSY_COURSE_FIELDS_CLIMB; + gypsy->climb = climb; + changed = TRUE; + } + } + + if (changed) { + GeoclueVelocityFields fields; + + fields = gypsy_course_to_geoclue (gypsy->course_fields); + gc_iface_velocity_emit_velocity_changed + (GC_IFACE_VELOCITY (gypsy), fields, + timestamp, gypsy->speed, gypsy->direction, gypsy->climb); + } +} + +static void +accuracy_changed (GypsyAccuracy *accuracy, + GypsyAccuracyFields fields, + double pdop, + double hdop, + double vdop, + GeoclueGypsy *gypsy) +{ + gboolean changed = FALSE; + GeoclueAccuracyLevel level; + double horiz, vert; + + geoclue_accuracy_get_details (gypsy->accuracy, &level, &horiz, &vert); + if (fields & (GYPSY_ACCURACY_FIELDS_HORIZONTAL | + GYPSY_ACCURACY_FIELDS_VERTICAL)){ + if (level != GEOCLUE_ACCURACY_LEVEL_DETAILED || + horiz != hdop || vert != vdop) { + changed = TRUE; + } + + geoclue_accuracy_set_details (gypsy->accuracy, + GEOCLUE_ACCURACY_LEVEL_DETAILED, + hdop, vdop); + } else { + + if (level != GEOCLUE_ACCURACY_LEVEL_NONE || + horiz != 0.0 || vert != 0.0) { + changed = TRUE; + } + + geoclue_accuracy_set_details (gypsy->accuracy, + GEOCLUE_ACCURACY_LEVEL_NONE, + 0.0, 0.0); + } + + if (changed) { + GeocluePositionFields fields; + + fields = gypsy_position_to_geoclue (gypsy->position_fields); + gc_iface_position_emit_position_changed + (GC_IFACE_POSITION (gypsy), fields, + gypsy->timestamp, gypsy->latitude, gypsy->longitude, + gypsy->altitude, gypsy->accuracy); + } +} + +static void +connection_changed (GypsyDevice *device, + gboolean connected, + GeoclueGypsy *gypsy) +{ + if (connected == FALSE && + gypsy->status != GEOCLUE_STATUS_UNAVAILABLE) { + gypsy->status = GEOCLUE_STATUS_UNAVAILABLE; + gc_iface_geoclue_emit_status_changed (GC_IFACE_GEOCLUE (gypsy), + gypsy->status); + } +} + +static void +fix_status_changed (GypsyDevice *device, + GypsyDeviceFixStatus status, + GeoclueGypsy *gypsy) +{ + gboolean changed = FALSE; + + switch (status) { + case GYPSY_DEVICE_FIX_STATUS_INVALID: + if (gypsy->status != GEOCLUE_STATUS_UNAVAILABLE) { + changed = TRUE; + gypsy->status = GEOCLUE_STATUS_UNAVAILABLE; + } + break; + + case GYPSY_DEVICE_FIX_STATUS_NONE: + if (gypsy->status != GEOCLUE_STATUS_ACQUIRING) { + changed = TRUE; + gypsy->status = GEOCLUE_STATUS_ACQUIRING; + } + break; + + case GYPSY_DEVICE_FIX_STATUS_2D: + case GYPSY_DEVICE_FIX_STATUS_3D: + if (gypsy->status != GEOCLUE_STATUS_AVAILABLE) { + changed = TRUE; + gypsy->status = GEOCLUE_STATUS_AVAILABLE; + } + break; + } + + if (changed) { + gc_iface_geoclue_emit_status_changed (GC_IFACE_GEOCLUE (gypsy), + gypsy->status); + } +} + +static void +get_initial_status (GeoclueGypsy *gypsy) +{ + gboolean connected; + GypsyDeviceFixStatus status; + GError *error = NULL; + + connected = gypsy_device_get_connection_status (gypsy->device, &error); + if (connected == FALSE) { + gypsy->status = GEOCLUE_STATUS_UNAVAILABLE; + g_print ("Initial status - %d (disconnected)\n", gypsy->status); + return; + } + + status = gypsy_device_get_fix_status (gypsy->device, &error); + switch (status) { + case GYPSY_DEVICE_FIX_STATUS_INVALID: + gypsy->status = GEOCLUE_STATUS_UNAVAILABLE; + break; + + case GYPSY_DEVICE_FIX_STATUS_NONE: + gypsy->status = GEOCLUE_STATUS_ACQUIRING; + break; + + case GYPSY_DEVICE_FIX_STATUS_2D: + case GYPSY_DEVICE_FIX_STATUS_3D: + gypsy->status = GEOCLUE_STATUS_AVAILABLE; + break; + } + + g_print ("Initial status - %d (connected)\n", gypsy->status); +} + +static gboolean +set_options (GcIfaceGeoclue *gc, + GHashTable *options, + GError **error) +{ + GeoclueGypsy *gypsy = GEOCLUE_GYPSY (gc); + GValue *device_value, *baud_rate_value; + const char *device_name; + char *path; + int baud_rate; + + device_value = g_hash_table_lookup (options, + "org.freedesktop.Geoclue.GPSDevice"); + device_name = device_value ? g_value_get_string (device_value) : NULL; + baud_rate_value = g_hash_table_lookup (options, + "org.freedesktop.Geoclue.GPSBaudRate"); + baud_rate = baud_rate_value ? g_value_get_int (baud_rate_value) : 0; + + if (g_strcmp0 (gypsy->device_name, device_name) == 0 && + gypsy->baud_rate == baud_rate) + return TRUE; + + /* Disconnect from the old device, if any */ + if (gypsy->device != NULL) { + g_object_unref (gypsy->device); + gypsy->device = NULL; + } + + g_free (gypsy->device_name); + gypsy->device_name = NULL; + + if (device_name == NULL || *device_name == '\0') { + return TRUE; + } + + gypsy->device_name = g_strdup (device_name); + gypsy->baud_rate = baud_rate; + g_print ("Gypsy provider using '%s' at %d bps\n", gypsy->device_name, gypsy->baud_rate); + path = gypsy_control_create (gypsy->control, gypsy->device_name, + error); + if (*error != NULL) { + g_print ("Error - %s?\n", (*error)->message); + gypsy->status = GEOCLUE_STATUS_ERROR; + return FALSE; + } + + /* If we've got here, then we are out of the ERROR condition */ + gypsy->status = GEOCLUE_STATUS_UNAVAILABLE; + + gypsy->device = gypsy_device_new (path); + g_signal_connect (gypsy->device, "connection-changed", + G_CALLBACK (connection_changed), gypsy); + g_signal_connect (gypsy->device, "fix-status-changed", + G_CALLBACK (fix_status_changed), gypsy); + + gypsy->position = gypsy_position_new (path); + g_signal_connect (gypsy->position, "position-changed", + G_CALLBACK (position_changed), gypsy); + gypsy->course = gypsy_course_new (path); + g_signal_connect (gypsy->course, "course-changed", + G_CALLBACK (course_changed), gypsy); + gypsy->acc = gypsy_accuracy_new (path); + g_signal_connect (gypsy->acc, "accuracy-changed", + G_CALLBACK (accuracy_changed), gypsy); + + g_debug ("starting device"); + if (gypsy->baud_rate != 0) { + GHashTable *goptions; + GValue speed_val = { 0, }; + GError *err = NULL; + + g_value_init (&speed_val, G_TYPE_UINT); + g_value_set_uint (&speed_val, gypsy->baud_rate); + goptions = g_hash_table_new (g_str_hash, + g_str_equal); + g_hash_table_insert (goptions, "BaudRate", &speed_val); + if (!gypsy_device_set_start_options (gypsy->device, + goptions, + &err)) { + g_warning ("Error: %s", err->message); + g_error_free (err); + } + g_hash_table_destroy (goptions); + } + gypsy_device_start (gypsy->device, error); + if (*error != NULL) { + g_print ("Error - %s?\n", (*error)->message); + gypsy->status = GEOCLUE_STATUS_ERROR; + g_free (path); + return FALSE; + } + get_initial_status (gypsy); + g_free (path); + + return TRUE; +} + +static void +shutdown (GcProvider *provider) +{ + GeoclueGypsy *gypsy = GEOCLUE_GYPSY (provider); + + g_main_loop_quit (gypsy->loop); +} + +static void +finalize (GObject *object) +{ + GeoclueGypsy *gypsy = GEOCLUE_GYPSY (object); + + geoclue_accuracy_free (gypsy->accuracy); + g_free (gypsy->device_name); + + ((GObjectClass *) geoclue_gypsy_parent_class)->finalize (object); +} + +static void +dispose (GObject *object) +{ + GeoclueGypsy *gypsy = GEOCLUE_GYPSY (object); + + if (gypsy->control) { + g_object_unref (gypsy->control); + gypsy->control = NULL; + } + + if (gypsy->device) { + g_object_unref (gypsy->device); + gypsy->device = NULL; + } + + if (gypsy->position) { + g_object_unref (gypsy->position); + gypsy->position = NULL; + } + + ((GObjectClass *) geoclue_gypsy_parent_class)->dispose (object); +} + +static void +geoclue_gypsy_class_init (GeoclueGypsyClass *klass) +{ + GObjectClass *o_class = (GObjectClass *) klass; + GcProviderClass *p_class = (GcProviderClass *) klass; + + o_class->finalize = finalize; + o_class->dispose = dispose; + + p_class->get_status = get_status; + p_class->set_options = set_options; + p_class->shutdown = shutdown; +} + +static void +geoclue_gypsy_init (GeoclueGypsy *gypsy) +{ + gypsy->status = GEOCLUE_STATUS_ERROR; + gypsy->control = gypsy_control_get_default (); + + gc_provider_set_details (GC_PROVIDER (gypsy), + "org.freedesktop.Geoclue.Providers.Gypsy", + "/org/freedesktop/Geoclue/Providers/Gypsy", + "Gypsy", "Gypsy provider"); + + gypsy->position_fields = GYPSY_POSITION_FIELDS_NONE; + + gypsy->accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, + 0.0, 0.0); +} + +static gboolean +get_position (GcIfacePosition *gc, + GeocluePositionFields *fields, + int *timestamp, + double *latitude, + double *longitude, + double *altitude, + GeoclueAccuracy **accuracy, + GError **error) +{ + GeoclueGypsy *gypsy = GEOCLUE_GYPSY (gc); + GeoclueAccuracyLevel level; + double horizontal, vertical; + + *timestamp = gypsy->timestamp; + + *fields = GEOCLUE_POSITION_FIELDS_NONE; + if (gypsy->position_fields & GYPSY_POSITION_FIELDS_LATITUDE) { + *fields |= GEOCLUE_POSITION_FIELDS_LATITUDE; + *latitude = gypsy->latitude; + } + if (gypsy->position_fields & GYPSY_POSITION_FIELDS_LONGITUDE) { + *fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE; + *longitude = gypsy->longitude; + } + if (gypsy->position_fields & GYPSY_POSITION_FIELDS_ALTITUDE) { + *fields |= GEOCLUE_POSITION_FIELDS_ALTITUDE; + *altitude = gypsy->altitude; + } + + geoclue_accuracy_get_details (gypsy->accuracy, &level, + &horizontal, &vertical); + *accuracy = geoclue_accuracy_new (level, horizontal, vertical); + + return TRUE; +} + +static void +geoclue_gypsy_position_init (GcIfacePositionClass *iface) +{ + iface->get_position = get_position; +} + +static gboolean +get_velocity (GcIfaceVelocity *gc, + GeoclueVelocityFields *fields, + int *timestamp, + double *speed, + double *direction, + double *climb, + GError **error) +{ + return TRUE; +} + +static void +geoclue_gypsy_velocity_init (GcIfaceVelocityClass *iface) +{ + iface->get_velocity = get_velocity; +} + +int +main (int argc, + char **argv) +{ + GeoclueGypsy *gypsy; + + g_type_init (); + + gypsy = g_object_new (GEOCLUE_TYPE_GYPSY, NULL); + + gypsy->loop = g_main_loop_new (NULL, TRUE); + g_main_loop_run (gypsy->loop); + + /* Unref the object so that gypsy-daemon knows we've shutdown */ + g_object_unref (gypsy); + return 0; +} diff --git a/.pc/tizen.patch/providers/hostip/Makefile.am b/.pc/tizen.patch/providers/hostip/Makefile.am new file mode 100755 index 0000000..1131187 --- /dev/null +++ b/.pc/tizen.patch/providers/hostip/Makefile.am @@ -0,0 +1,35 @@ +libexec_PROGRAMS = \ + geoclue-hostip + +NOINST_H_FILES = \ + geoclue-hostip.h + +geoclue_hostip_SOURCES = \ + $(NOINST_H_FILES) \ + geoclue-hostip.c + +geoclue_hostip_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) + +geoclue_hostip_LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-hostip.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Hostip.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/providers/localnet/Makefile.am b/.pc/tizen.patch/providers/localnet/Makefile.am new file mode 100755 index 0000000..382f1b2 --- /dev/null +++ b/.pc/tizen.patch/providers/localnet/Makefile.am @@ -0,0 +1,56 @@ +libexec_PROGRAMS = geoclue-localnet + +noinst_DATA = \ + geoclue-localnet.xml + +nodist_geoclue_localnet_SOURCES = \ + geoclue-localnet-glue.h + +BUILT_SOURCES = \ + $(nodist_geoclue_localnet_SOURCES) + +geoclue_localnet_SOURCES = \ + geoclue-localnet.c + +geoclue_localnet_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/src \ + $(GEOCLUE_CFLAGS) + +geoclue_localnet_LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/src/libconnectivity.la \ + $(top_builddir)/geoclue/libgeoclue.la + + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-localnet.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Localnet.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +CLEANFILES = \ + stamp-geoclue-localnet-glue.h + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) \ + $(noinst_DATA) + +DISTCLEANFILES = \ + $(service_DATA) \ + $(nodist_geoclue_localnet_SOURCES) + +%-glue.h: stamp-%-glue.h + @true + +stamp-geoclue-localnet-glue.h: geoclue-localnet.xml + $(AM_V_GEN) $(DBUS_BINDING_TOOL) --prefix=geoclue_localnet --mode=glib-server $< > xgen-$(@F) \ + && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \ + && rm -f xgen-$(@F) \ + && echo timestamp > $(@F) diff --git a/.pc/tizen.patch/providers/localnet/geoclue-localnet.c b/.pc/tizen.patch/providers/localnet/geoclue-localnet.c new file mode 100755 index 0000000..b834b75 --- /dev/null +++ b/.pc/tizen.patch/providers/localnet/geoclue-localnet.c @@ -0,0 +1,512 @@ +/** + * + * Expects to find a keyfile in user config dir + * (~/.config/geoclue-localnet-gateways). + * + * The keyfile should contain entries like this: + * + * [00:1D:7E:55:8D:80] + * country=Finland + * street=Solnantie 24 + * locality=Helsinki + * + * Only address interface is supported so far. + * + * Any application that can obtain a reliable address can submit it + * to localnet provider through the D-Bus API -- it will then be provided + * whenever connected to the same router: + * org.freedesktop.Geoclue.Localnet.SetAddress + * org.freedesktop.Geoclue.Localnet.SetAddressFields + * + * SetAddress allows setting the current address as a GeoclueAddress, + * while SetAddressFields is a convenience version with separate + * address fields. Shell example using SetAddressFields: + * + dbus-send --print-reply --type=method_call \ + --dest=org.freedesktop.Geoclue.Providers.Localnet \ + /org/freedesktop/Geoclue/Providers/Localnet \ + org.freedesktop.Geoclue.Localnet.SetAddressFields \ + string: \ + string:"Finland" \ + string: \ + string:"Helsinki" \ + string: \ + string: \ + string:"Solnantie 24" + + * This would make the provider save the specified address with current + * router mac address. It will provide the address to clients whenever + * the computer is connected to the same router again. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include <dbus/dbus-glib-bindings.h> +#include <dbus/dbus.h> + +#include <geoclue/gc-provider.h> +#include <geoclue/geoclue-error.h> +#include <geoclue/gc-iface-address.h> + +#include "connectivity.h" + +#define KEYFILE_NAME "geoclue-localnet-gateways" + +typedef struct { + char *mac; + GHashTable *address; + GeoclueAccuracy *accuracy; +} Gateway; + + +typedef struct { + GcProvider parent; + + GMainLoop *loop; + GeoclueConnectivity *conn; + + char *keyfile_name; + GSList *gateways; +} GeoclueLocalnet; + +typedef struct { + GcProviderClass parent_class; +} GeoclueLocalnetClass; + +#define GEOCLUE_TYPE_LOCALNET (geoclue_localnet_get_type ()) +#define GEOCLUE_LOCALNET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_LOCALNET, GeoclueLocalnet)) + +static void geoclue_localnet_address_init (GcIfaceAddressClass *iface); + +G_DEFINE_TYPE_WITH_CODE (GeoclueLocalnet, geoclue_localnet, GC_TYPE_PROVIDER, + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_ADDRESS, + geoclue_localnet_address_init)) + +static gboolean geoclue_localnet_set_address (GeoclueLocalnet *localnet, GHashTable *address, GError **error); +static gboolean geoclue_localnet_set_address_fields (GeoclueLocalnet *localnet, char *country_code, char *country, char *region, char *locality, char *area, char *postalcode, char *street, GError **error); +#include "geoclue-localnet-glue.h" + + +static gboolean +get_status (GcIfaceGeoclue *gc, + GeoclueStatus *status, + GError **error) +{ + *status = GEOCLUE_STATUS_AVAILABLE; + return TRUE; +} + +static void +shutdown (GcProvider *provider) +{ + GeoclueLocalnet *localnet; + + localnet = GEOCLUE_LOCALNET (provider); + g_main_loop_quit (localnet->loop); +} + +static void +free_gateway_list (GSList *gateways) +{ + GSList *l; + + l = gateways; + while (l) { + Gateway *gw; + + gw = l->data; + g_free (gw->mac); + g_hash_table_destroy (gw->address); + geoclue_accuracy_free (gw->accuracy); + g_free (gw); + + l = l->next; + } + g_slist_free (gateways); +} + +static void +finalize (GObject *object) +{ + GeoclueLocalnet *localnet; + + localnet = GEOCLUE_LOCALNET (object); + + if (localnet->conn != NULL) { + g_object_unref (localnet->conn); + localnet->conn = NULL; + } + g_free (localnet->keyfile_name); + free_gateway_list (localnet->gateways); + + G_OBJECT_CLASS (geoclue_localnet_parent_class)->finalize (object); +} + +static void +geoclue_localnet_class_init (GeoclueLocalnetClass *klass) +{ + GcProviderClass *p_class = (GcProviderClass *) klass; + GObjectClass *o_class = (GObjectClass *) klass; + + o_class->finalize = finalize; + + p_class->get_status = get_status; + p_class->shutdown = shutdown; + + dbus_g_object_type_install_info (geoclue_localnet_get_type (), + &dbus_glib_geoclue_localnet_object_info); + +} + +static void +geoclue_localnet_load_gateways_from_keyfile (GeoclueLocalnet *localnet, + GKeyFile *keyfile) +{ + char **groups; + char **g; + GError *error = NULL; + + groups = g_key_file_get_groups (keyfile, NULL); + g = groups; + while (*g) { + GeoclueAccuracyLevel level; + char **keys; + char **k; + Gateway *gateway = g_new0 (Gateway, 1); + + gateway->mac = g_ascii_strdown (*g, -1); + gateway->address = geoclue_address_details_new (); + + /* read all keys in the group as address fields */ + keys = g_key_file_get_keys (keyfile, *g, + NULL, &error); + if (error) { + g_warning ("Could not load keys for group [%s] from %s: %s", + *g, localnet->keyfile_name, error->message); + g_error_free (error); + error = NULL; + } + + k = keys; + while (*k) { + char *value; + + value = g_key_file_get_string (keyfile, *g, *k, NULL); + g_hash_table_insert (gateway->address, + *k, value); + k++; + } + g_free (keys); + + level = geoclue_address_details_get_accuracy_level (gateway->address); + gateway->accuracy = geoclue_accuracy_new (level, 0, 0); + + localnet->gateways = g_slist_prepend (localnet->gateways, gateway); + + g++; + } + g_strfreev (groups); +} + +static Gateway * +geoclue_localnet_find_gateway (GeoclueLocalnet *localnet, char *mac) +{ + GSList *l; + + l = localnet->gateways; + /* eww, should be using a hashtable or something here */ + while (l) { + Gateway *gw = l->data; + + if (g_ascii_strcasecmp (gw->mac, mac) == 0) { + return gw; + } + + l = l->next; + } + + return NULL; +} + +static void +geoclue_localnet_init (GeoclueLocalnet *localnet) +{ + const char *dir; + GKeyFile *keyfile; + GError *error = NULL; + + gc_provider_set_details (GC_PROVIDER (localnet), + "org.freedesktop.Geoclue.Providers.Localnet", + "/org/freedesktop/Geoclue/Providers/Localnet", + "Localnet", "provides Address based on current gateway mac address and a local address file (which can be updated through D-Bus)"); + + + localnet->gateways = NULL; + + /* load known addresses from keyfile */ + dir = g_get_user_config_dir (); + g_mkdir_with_parents (dir, 0755); + localnet->keyfile_name = g_build_filename (dir, KEYFILE_NAME, NULL); + + keyfile = g_key_file_new (); + if (!g_key_file_load_from_file (keyfile, localnet->keyfile_name, + G_KEY_FILE_NONE, &error)) { + g_warning ("Could not load keyfile %s: %s", + localnet->keyfile_name, error->message); + g_error_free (error); + } + geoclue_localnet_load_gateways_from_keyfile (localnet, keyfile); + g_key_file_free (keyfile); + + localnet->conn = geoclue_connectivity_new (); +} + +typedef struct { + GKeyFile *keyfile; + char *group_name; +} localnet_keyfile_group; + +static void +add_address_detail_to_keyfile (char *key, char *value, + localnet_keyfile_group *group) +{ + g_key_file_set_string (group->keyfile, group->group_name, + key, value); +} + +static gboolean +geoclue_localnet_set_address (GeoclueLocalnet *localnet, + GHashTable *details, + GError **error) +{ + char *str, *mac; + GKeyFile *keyfile; + GError *int_err = NULL; + localnet_keyfile_group *keyfile_group; + Gateway *gw; + + if (!details) { + /* TODO set error */ + return FALSE; + } + + mac = geoclue_connectivity_get_router_mac (localnet->conn); + if (!mac) { + g_warning ("Couldn't get current gateway mac address"); + /* TODO set error */ + return FALSE; + } + /* reload keyfile just in case it's changed */ + keyfile = g_key_file_new (); + if (!g_key_file_load_from_file (keyfile, localnet->keyfile_name, + G_KEY_FILE_NONE, &int_err)) { + g_warning ("Could not load keyfile %s: %s", + localnet->keyfile_name, int_err->message); + g_error_free (int_err); + int_err = NULL; + } + + /* remove old group (if exists) and add new to GKeyFile */ + g_key_file_remove_group (keyfile, mac, NULL); + + keyfile_group = g_new0 (localnet_keyfile_group, 1); + keyfile_group->keyfile = keyfile; + keyfile_group->group_name = mac; + g_hash_table_foreach (details, (GHFunc) add_address_detail_to_keyfile, keyfile_group); + g_free (keyfile_group); + + /* save keyfile*/ + str = g_key_file_to_data (keyfile, NULL, &int_err); + if (int_err) { + g_warning ("Failed to get keyfile data as string: %s", int_err->message); + g_error_free (int_err); + g_key_file_free (keyfile); + g_free (mac); + /* TODO set error */ + return FALSE; + } + + g_file_set_contents (localnet->keyfile_name, str, -1, &int_err); + g_free (str); + if (int_err) { + g_warning ("Failed to save keyfile: %s", int_err->message); + g_error_free (int_err); + g_key_file_free (keyfile); + g_free (mac); + /* TODO set error */ + return FALSE; + } + + /* re-parse keyfile */ + free_gateway_list (localnet->gateways); + localnet->gateways = NULL; + geoclue_localnet_load_gateways_from_keyfile (localnet, keyfile); + g_key_file_free (keyfile); + + gw = geoclue_localnet_find_gateway (localnet, mac); + g_free (mac); + + if (gw) { + gc_iface_address_emit_address_changed (GC_IFACE_ADDRESS (localnet), + time (NULL), gw->address, gw->accuracy); + } else { + /* empty address -- should emit anyway? */ + } + return TRUE; +} + +static gboolean +geoclue_localnet_set_address_fields (GeoclueLocalnet *localnet, + char *country_code, + char *country, + char *region, + char *locality, + char *area, + char *postalcode, + char *street, + GError **error) +{ + GHashTable *address; + gboolean ret; + + address = geoclue_address_details_new (); + if (country_code && (strlen (country_code) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_COUNTRYCODE), + g_strdup (country_code)); + if (!country) { + geoclue_address_details_set_country_from_code (address); + } + } + if (country && (strlen (country) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_COUNTRY), + g_strdup (country)); + } + if (region && (strlen (region) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_REGION), + g_strdup (region)); + } + if (locality && (strlen (locality) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_LOCALITY), + g_strdup (locality)); + } + if (area && (strlen (area) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_AREA), + g_strdup (area)); + } + if (postalcode && (strlen (postalcode) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_POSTALCODE), + g_strdup (postalcode)); + } + if (street && (strlen (street) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_STREET), + g_strdup (street)); + } + + ret = geoclue_localnet_set_address (localnet, + address, + error); + g_hash_table_destroy (address); + return ret; +} + +static gboolean +get_address (GcIfaceAddress *gc, + int *timestamp, + GHashTable **address, + GeoclueAccuracy **accuracy, + GError **error) +{ + GeoclueLocalnet *localnet; + char *mac; + Gateway *gw; + + localnet = GEOCLUE_LOCALNET (gc); + + /* we may be trying to read /proc/net/arp right after network connection. + * It's sometimes not up yet, try a couple of times */ + mac = geoclue_connectivity_get_router_mac (localnet->conn); + + if (!mac) { + g_warning ("Couldn't get current gateway mac address"); + if (error) { + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, "Could not get current gateway mac address"); + } + return FALSE; + } + + gw = geoclue_localnet_find_gateway (localnet, mac); + g_free (mac); + + if (timestamp) { + *timestamp = time(NULL); + } + if (address) { + if (gw) { + *address = geoclue_address_details_copy (gw->address); + } else { + *address = geoclue_address_details_new (); + } + } + if (accuracy) { + if (gw) { + *accuracy = geoclue_accuracy_copy (gw->accuracy); + } else { + *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0, 0); + } + } + return TRUE; +} + +static void +geoclue_localnet_address_init (GcIfaceAddressClass *iface) +{ + iface->get_address = get_address; +} + +int +main (int argc, + char **argv) +{ + GeoclueLocalnet *localnet; + + g_type_init (); + + localnet = g_object_new (GEOCLUE_TYPE_LOCALNET, NULL); + localnet->loop = g_main_loop_new (NULL, TRUE); + + g_main_loop_run (localnet->loop); + + g_main_loop_unref (localnet->loop); + g_object_unref (localnet); + + return 0; +} diff --git a/.pc/tizen.patch/providers/manual/Makefile.am b/.pc/tizen.patch/providers/manual/Makefile.am new file mode 100755 index 0000000..231e042 --- /dev/null +++ b/.pc/tizen.patch/providers/manual/Makefile.am @@ -0,0 +1,54 @@ +libexec_PROGRAMS = geoclue-manual + +noinst_DATA = \ + geoclue-manual.xml + +nodist_geoclue_manual_SOURCES = \ + geoclue-manual-glue.h + +BUILT_SOURCES = \ + $(nodist_geoclue_manual_SOURCES) + +geoclue_manual_SOURCES = \ + geoclue-manual.c + +geoclue_manual_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) + +geoclue_manual_LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-manual.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Manual.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +CLEANFILES = \ + stamp-geoclue-manual-glue.h + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) \ + $(noinst_DATA) + +DISTCLEANFILES = \ + $(service_DATA) \ + $(nodist_geoclue_manual_SOURCES) + +%-glue.h: stamp-%-glue.h + @true + +stamp-geoclue-manual-glue.h: geoclue-manual.xml + $(AM_V_GEN) $(DBUS_BINDING_TOOL) --prefix=geoclue_manual --mode=glib-server $< > xgen-$(@F) \ + && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \ + && rm -f xgen-$(@F) \ + && echo timestamp > $(@F) diff --git a/.pc/tizen.patch/providers/manual/geoclue-manual.c b/.pc/tizen.patch/providers/manual/geoclue-manual.c new file mode 100755 index 0000000..2b6620a --- /dev/null +++ b/.pc/tizen.patch/providers/manual/geoclue-manual.c @@ -0,0 +1,365 @@ +/* + * Geoclue + * geoclue-manual.c - Manual address provider + * + * Author: Jussi Kukkonen <jku@o-hand.com> + * Copyright 2008 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/** Geoclue manual provider + * + * This is an address provider which gets its address data from user + * input. No UI is included, any application may query the address from + * the user and submit it to manual provider through the D-Bus API: + * org.freedesktop.Geoclue.Manual.SetAddress + * org.freedesktop.Geoclue.Manual.SetAddressFields + * + * SetAddress allows setting the current address as a GeoclueAddress, + * while SetAddressFields is a convenience version with separate + * address fields. Shell example using SetAddressFields: + * + * dbus-send --print-reply --type=method_call \ + * --dest=org.freedesktop.Geoclue.Providers.Manual \ + * /org/freedesktop/Geoclue/Providers/Manual \ + * org.freedesktop.Geoclue.Manual.SetAddressFields \ + * int32:7200 \ + * string: \ + * string:"Finland" \ + * string: \ + * string:"Helsinki" \ + * string: \ + * string: \ + * string:"Solnantie 24" + * + * This would make the provider emit a AddressChanged signal with + * accuracy level GEOCLUE_ACCURACY_STREET. Unless new SetAddress* calls + * are made, provider will emit another signal in two hours (7200 sec), + * with empty address and GEOCLUE_ACCURACY_NONE. + **/ + +#include <config.h> +#include <string.h> +#include <dbus/dbus-glib-bindings.h> +#include <dbus/dbus.h> + +#include <geoclue/gc-provider.h> +#include <geoclue/gc-iface-address.h> + +typedef struct { + GcProvider parent; + + GMainLoop *loop; + + guint event_id; + + int timestamp; + GHashTable *address; + GeoclueAccuracy *accuracy; +} GeoclueManual; + +typedef struct { + GcProviderClass parent_class; +} GeoclueManualClass; + +#define GEOCLUE_TYPE_MANUAL (geoclue_manual_get_type ()) +#define GEOCLUE_MANUAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_MANUAL, GeoclueManual)) + +static void geoclue_manual_address_init (GcIfaceAddressClass *iface); + +G_DEFINE_TYPE_WITH_CODE (GeoclueManual, geoclue_manual, GC_TYPE_PROVIDER, + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_ADDRESS, + geoclue_manual_address_init)) + +static gboolean +geoclue_manual_set_address (GeoclueManual *manual, + int valid_until, + GHashTable *address, + GError **error); + +static gboolean +geoclue_manual_set_address_fields (GeoclueManual *manual, + int valid_until, + char *country_code, + char *country, + char *region, + char *locality, + char *area, + char *postalcode, + char *street, + GError **error); + +#include "geoclue-manual-glue.h" + + +static GeoclueAccuracyLevel +get_accuracy_for_address (GHashTable *address) +{ + if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_STREET)) { + return GEOCLUE_ACCURACY_LEVEL_STREET; + } else if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_POSTALCODE)) { + return GEOCLUE_ACCURACY_LEVEL_POSTALCODE; + } else if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_LOCALITY)) { + return GEOCLUE_ACCURACY_LEVEL_LOCALITY; + } else if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_REGION)) { + return GEOCLUE_ACCURACY_LEVEL_REGION; + } else if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_COUNTRY) || + g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_COUNTRYCODE)) { + return GEOCLUE_ACCURACY_LEVEL_COUNTRY; + } + return GEOCLUE_ACCURACY_LEVEL_NONE; +} + +static gboolean +get_status (GcIfaceGeoclue *gc, + GeoclueStatus *status, + GError **error) +{ + GeoclueAccuracyLevel level; + + geoclue_accuracy_get_details (GEOCLUE_MANUAL (gc)->accuracy, + &level, NULL, NULL); + if (level == GEOCLUE_ACCURACY_LEVEL_NONE) { + *status = GEOCLUE_STATUS_UNAVAILABLE; + } else { + *status = GEOCLUE_STATUS_AVAILABLE; + } + return TRUE; +} + +static void +shutdown (GcProvider *provider) +{ + GeoclueManual *manual; + + manual = GEOCLUE_MANUAL (provider); + g_main_loop_quit (manual->loop); +} + +gboolean +validity_ended (GeoclueManual *manual) +{ + manual->event_id = 0; + g_hash_table_remove_all (manual->address); + geoclue_accuracy_set_details (manual->accuracy, + GEOCLUE_ACCURACY_LEVEL_NONE, 0, 0); + + gc_iface_address_emit_address_changed (GC_IFACE_ADDRESS (manual), + manual->timestamp, + manual->address, + manual->accuracy); + return FALSE; +} + + +static void +geoclue_manual_set_address_common (GeoclueManual *manual, + int valid_for, + GHashTable *address) +{ + if (manual->event_id > 0) { + g_source_remove (manual->event_id); + } + + manual->timestamp = time (NULL); + + g_hash_table_destroy (manual->address); + manual->address = address; + + geoclue_accuracy_set_details (manual->accuracy, + get_accuracy_for_address (address), + 0, 0); + + gc_iface_address_emit_address_changed (GC_IFACE_ADDRESS (manual), + manual->timestamp, + manual->address, + manual->accuracy); + + if (valid_for > 0) { + manual->event_id = g_timeout_add (valid_for * 1000, + (GSourceFunc)validity_ended, + manual); + } +} + +static gboolean +geoclue_manual_set_address (GeoclueManual *manual, + int valid_for, + GHashTable *address, + GError **error) +{ + geoclue_manual_set_address_common (manual, + valid_for, + geoclue_address_details_copy (address)); + return TRUE; +} + +static gboolean +geoclue_manual_set_address_fields (GeoclueManual *manual, + int valid_for, + char *country_code, + char *country, + char *region, + char *locality, + char *area, + char *postalcode, + char *street, + GError **error) +{ + GHashTable *address; + + address = geoclue_address_details_new (); + if (country_code && (strlen (country_code) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_COUNTRYCODE), + g_strdup (country_code)); + } + if (country && (strlen (country) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_COUNTRY), + g_strdup (country)); + } + if (region && (strlen (region) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_REGION), + g_strdup (region)); + } + if (locality && (strlen (locality) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_LOCALITY), + g_strdup (locality)); + } + if (area && (strlen (area) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_AREA), + g_strdup (area)); + } + if (postalcode && (strlen (postalcode) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_POSTALCODE), + g_strdup (postalcode)); + } + if (street && (strlen (street) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_STREET), + g_strdup (street)); + } + + geoclue_manual_set_address_common (manual, + valid_for, + address); + return TRUE; +} + + +static void +finalize (GObject *object) +{ + GeoclueManual *manual; + + manual = GEOCLUE_MANUAL (object); + + g_hash_table_destroy (manual->address); + geoclue_accuracy_free (manual->accuracy); + + ((GObjectClass *) geoclue_manual_parent_class)->finalize (object); +} + +static void +geoclue_manual_class_init (GeoclueManualClass *klass) +{ + GObjectClass *o_class = (GObjectClass *) klass; + GcProviderClass *p_class = (GcProviderClass *) klass; + + o_class->finalize = finalize; + + p_class->get_status = get_status; + p_class->shutdown = shutdown; + + dbus_g_object_type_install_info (geoclue_manual_get_type (), + &dbus_glib_geoclue_manual_object_info); +} + +static void +geoclue_manual_init (GeoclueManual *manual) +{ + gc_provider_set_details (GC_PROVIDER (manual), + "org.freedesktop.Geoclue.Providers.Manual", + "/org/freedesktop/Geoclue/Providers/Manual", + "Manual", "Manual provider"); + + manual->address = geoclue_address_details_new (); + manual->accuracy = + geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0, 0); +} + +static gboolean +get_address (GcIfaceAddress *gc, + int *timestamp, + GHashTable **address, + GeoclueAccuracy **accuracy, + GError **error) +{ + GeoclueManual *manual = GEOCLUE_MANUAL (gc); + GeoclueAccuracyLevel level; + + geoclue_accuracy_get_details (manual->accuracy, &level, NULL, NULL); + if (level == GEOCLUE_ACCURACY_LEVEL_NONE) { + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "No manual address set"); + return FALSE; + } + + if (timestamp) { + *timestamp = manual->timestamp; + } + if (address) { + *address = geoclue_address_details_copy (manual->address); + } + if (accuracy) { + *accuracy = geoclue_accuracy_copy (manual->accuracy); + } + + return TRUE; +} + +static void +geoclue_manual_address_init (GcIfaceAddressClass *iface) +{ + iface->get_address = get_address; +} + +int +main (int argc, + char **argv) +{ + GeoclueManual *manual; + + g_type_init (); + + manual = g_object_new (GEOCLUE_TYPE_MANUAL, NULL); + manual->loop = g_main_loop_new (NULL, TRUE); + + g_main_loop_run (manual->loop); + + g_main_loop_unref (manual->loop); + g_object_unref (manual); + + return 0; +} diff --git a/.pc/tizen.patch/providers/nominatim/Makefile.am b/.pc/tizen.patch/providers/nominatim/Makefile.am new file mode 100755 index 0000000..f723ac9 --- /dev/null +++ b/.pc/tizen.patch/providers/nominatim/Makefile.am @@ -0,0 +1,35 @@ +libexec_PROGRAMS = \ + geoclue-nominatim + +NOINST_H_FILES = \ + geoclue-nominatim.h + +geoclue_nominatim_SOURCES = \ + $(NOINST_H_FILES) \ + geoclue-nominatim.c + +geoclue_nominatim_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) + +geoclue_nominatim_LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-nominatim.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Nominatim.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/providers/plazes/Makefile.am b/.pc/tizen.patch/providers/plazes/Makefile.am new file mode 100755 index 0000000..dc9fb47 --- /dev/null +++ b/.pc/tizen.patch/providers/plazes/Makefile.am @@ -0,0 +1,33 @@ +libexec_PROGRAMS = \ + geoclue-plazes + +geoclue_plazes_SOURCES = \ + geoclue-plazes.c + +geoclue_plazes_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/src \ + $(GEOCLUE_CFLAGS) + +geoclue_plazes_LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/src/libconnectivity.la \ + $(top_builddir)/geoclue/libgeoclue.la + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-plazes.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Plazes.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/providers/plazes/geoclue-plazes.c b/.pc/tizen.patch/providers/plazes/geoclue-plazes.c new file mode 100755 index 0000000..be44d90 --- /dev/null +++ b/.pc/tizen.patch/providers/plazes/geoclue-plazes.c @@ -0,0 +1,377 @@ +/* + * Geoclue + * geoclue-plazes.c - A plazes.com-based Address/Position provider + * + * Author: Jussi Kukkonen <jku@o-hand.com> + * Copyright 2008 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <time.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include <glib-object.h> +#include <dbus/dbus-glib-bindings.h> + +#include <geoclue/gc-web-service.h> +#include <geoclue/gc-provider.h> +#include <geoclue/geoclue-error.h> +#include <geoclue/gc-iface-position.h> +#include <geoclue/gc-iface-address.h> + +#include "connectivity.h" + +#define GEOCLUE_DBUS_SERVICE_PLAZES "org.freedesktop.Geoclue.Providers.Plazes" +#define GEOCLUE_DBUS_PATH_PLAZES "/org/freedesktop/Geoclue/Providers/Plazes" +#define PLAZES_URL "http://plazes.com/suggestions.xml" +#define PLAZES_KEY_MAC "mac_address" +#define PLAZES_LAT_XPATH "//plaze/latitude" +#define PLAZES_LON_XPATH "//plaze/longitude" + +#define GEOCLUE_TYPE_PLAZES (geoclue_plazes_get_type ()) +#define GEOCLUE_PLAZES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_PLAZES, GeocluePlazes)) + +typedef struct _GeocluePlazes { + GcProvider parent; + GMainLoop *loop; + GeoclueConnectivity *conn; + GcWebService *web_service; + GeoclueStatus last_status; +} GeocluePlazes; + +typedef struct _GeocluePlazesClass { + GcProviderClass parent_class; +} GeocluePlazesClass; + + +static void geoclue_plazes_init (GeocluePlazes *plazes); +static void geoclue_plazes_position_init (GcIfacePositionClass *iface); +static void geoclue_plazes_address_init (GcIfaceAddressClass *iface); + +G_DEFINE_TYPE_WITH_CODE (GeocluePlazes, geoclue_plazes, GC_TYPE_PROVIDER, + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION, + geoclue_plazes_position_init) + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_ADDRESS, + geoclue_plazes_address_init)) + + +/* Geoclue interface implementation */ +static gboolean +geoclue_plazes_get_status (GcIfaceGeoclue *iface, + GeoclueStatus *status, + GError **error) +{ + GeocluePlazes *plazes = GEOCLUE_PLAZES (iface); + + *status = plazes->last_status; + return TRUE; +} + +static void +shutdown (GcProvider *provider) +{ + GeocluePlazes *plazes = GEOCLUE_PLAZES (provider); + g_main_loop_quit (plazes->loop); +} + +static void +geoclue_plazes_set_status (GeocluePlazes *self, GeoclueStatus status) +{ + if (status != self->last_status) { + self->last_status = status; + gc_iface_geoclue_emit_status_changed (GC_IFACE_GEOCLUE (self), status); + } +} + +static char * +mac_strdown (char *mac) +{ + guint i; + for (i = 0; mac[i] != '\0' ; i++) { + if (g_ascii_isalpha (mac[i])) + mac[i] = g_ascii_tolower (mac[i]); + } + return mac; +} +/* Position interface implementation */ + +static gboolean +geoclue_plazes_get_position (GcIfacePosition *iface, + GeocluePositionFields *fields, + int *timestamp, + double *latitude, + double *longitude, + double *altitude, + GeoclueAccuracy **accuracy, + GError **error) +{ + GeocluePlazes *plazes; + char *mac, *mac_lc; + + plazes = (GEOCLUE_PLAZES (iface)); + + *fields = GEOCLUE_POSITION_FIELDS_NONE; + if (timestamp) { + *timestamp = time (NULL); + } + + mac = geoclue_connectivity_get_router_mac (plazes->conn); + if (mac == NULL) { + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Router mac address query failed"); + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_ERROR); + return FALSE; + } + + mac = mac_strdown (mac); + + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_ACQUIRING); + + mac_lc = g_ascii_strdown (mac, -1); + g_free (mac); + if (!gc_web_service_query (plazes->web_service, error, + PLAZES_KEY_MAC, mac, + (char *)0)) { + g_free (mac_lc); + // did not get a reply; we can try again later + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_AVAILABLE); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Did not get reply from server"); + return FALSE; + } + + g_free (mac); + + if (latitude && gc_web_service_get_double (plazes->web_service, + latitude, PLAZES_LAT_XPATH)) { + *fields |= GEOCLUE_POSITION_FIELDS_LATITUDE; + } + if (longitude && gc_web_service_get_double (plazes->web_service, + longitude, PLAZES_LON_XPATH)) { + *fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE; + } + + if (accuracy) { + /* Educated guess. Plazes are typically hand pointed on + * a map, or geocoded from address, so should be fairly + * accurate */ + *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_STREET, 0, 0); + } + + if (!(*fields & GEOCLUE_POSITION_FIELDS_LATITUDE && + *fields & GEOCLUE_POSITION_FIELDS_LONGITUDE)) { + + // we got a reply, but could not exploit it. It would probably be the + // same next time. + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_ERROR); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Could not understand reply from server"); + return FALSE; + } + + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_AVAILABLE); + + return TRUE; +} + +/* Address interface implementation */ + +static gboolean +geoclue_plazes_get_address (GcIfaceAddress *iface, + int *timestamp, + GHashTable **address, + GeoclueAccuracy **accuracy, + GError **error) +{ + + GeocluePlazes *plazes = GEOCLUE_PLAZES (iface); + char *mac, *mac_lc; + + GeoclueAccuracyLevel level = GEOCLUE_ACCURACY_LEVEL_NONE; + + if (timestamp) { + *timestamp = time (NULL); + } + + mac = geoclue_connectivity_get_router_mac (plazes->conn); + + if (mac == NULL) { + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Router mac address query failed"); + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_ERROR); + return FALSE; + } + + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_ACQUIRING); + + mac_lc = g_ascii_strdown (mac, -1); + g_free (mac); + if (!gc_web_service_query (plazes->web_service, error, + PLAZES_KEY_MAC, mac_lc, + (char *)0)) { + g_free (mac_lc); + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_AVAILABLE); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Did not get reply from server"); + return FALSE; + } + g_free (mac_lc); + + if (address) { + char *str; + + *address = geoclue_address_details_new (); + + if (gc_web_service_get_string (plazes->web_service, + &str, "//plaze/country")) { + geoclue_address_details_insert (*address, + GEOCLUE_ADDRESS_KEY_COUNTRY, + str); + g_free (str); + level = GEOCLUE_ACCURACY_LEVEL_COUNTRY; + } + if (gc_web_service_get_string (plazes->web_service, + &str, "//plaze/country_code")) { + geoclue_address_details_insert (*address, + GEOCLUE_ADDRESS_KEY_COUNTRYCODE, + str); + g_free (str); + level = GEOCLUE_ACCURACY_LEVEL_COUNTRY; + } + if (gc_web_service_get_string (plazes->web_service, + &str, "//plaze/city")) { + geoclue_address_details_insert (*address, + GEOCLUE_ADDRESS_KEY_LOCALITY, + str); + g_free (str); + level = GEOCLUE_ACCURACY_LEVEL_LOCALITY; + } + if (gc_web_service_get_string (plazes->web_service, + &str, "//plaze/zip_code")) { + geoclue_address_details_insert (*address, + GEOCLUE_ADDRESS_KEY_POSTALCODE, + str); + g_free (str); + level = GEOCLUE_ACCURACY_LEVEL_POSTALCODE; + } + if (gc_web_service_get_string (plazes->web_service, + &str, "//plaze/address")) { + geoclue_address_details_insert (*address, + GEOCLUE_ADDRESS_KEY_STREET, + str); + g_free (str); + level = GEOCLUE_ACCURACY_LEVEL_STREET; + } + } + + if (level == GEOCLUE_ACCURACY_LEVEL_NONE) { + // we got a reply, but could not exploit it. It would probably be the + // same next time. + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_ERROR); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Could not understand reply from server"); + return FALSE; + } + + if (accuracy) { + *accuracy = geoclue_accuracy_new (level, 0, 0); + } + + return TRUE; +} + +static void +geoclue_plazes_finalize (GObject *obj) +{ + GeocluePlazes *plazes = GEOCLUE_PLAZES (obj); + + if (plazes->conn != NULL) { + g_object_unref (plazes->conn); + plazes->conn = NULL; + } + g_object_unref (plazes->web_service); + + ((GObjectClass *) geoclue_plazes_parent_class)->finalize (obj); +} + + +/* Initialization */ + +static void +geoclue_plazes_class_init (GeocluePlazesClass *klass) +{ + GcProviderClass *p_class = (GcProviderClass *)klass; + GObjectClass *o_class = (GObjectClass *)klass; + + p_class->shutdown = shutdown; + p_class->get_status = geoclue_plazes_get_status; + + o_class->finalize = geoclue_plazes_finalize; +} + +static void +geoclue_plazes_init (GeocluePlazes *plazes) +{ + gc_provider_set_details (GC_PROVIDER (plazes), + GEOCLUE_DBUS_SERVICE_PLAZES, + GEOCLUE_DBUS_PATH_PLAZES, + "Plazes", "Plazes.com based provider, uses gateway mac address to locate"); + + plazes->conn = geoclue_connectivity_new (); + plazes->web_service = g_object_new (GC_TYPE_WEB_SERVICE, NULL); + gc_web_service_set_base_url (plazes->web_service, PLAZES_URL); + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_AVAILABLE); +} + +static void +geoclue_plazes_position_init (GcIfacePositionClass *iface) +{ + iface->get_position = geoclue_plazes_get_position; +} + +static void +geoclue_plazes_address_init (GcIfaceAddressClass *iface) +{ + iface->get_address = geoclue_plazes_get_address; +} + +int +main() +{ + g_type_init(); + + GeocluePlazes *o = g_object_new (GEOCLUE_TYPE_PLAZES, NULL); + o->loop = g_main_loop_new (NULL, TRUE); + + g_main_loop_run (o->loop); + + g_main_loop_unref (o->loop); + g_object_unref (o); + + return 0; +} diff --git a/.pc/tizen.patch/providers/skyhook/Makefile.am b/.pc/tizen.patch/providers/skyhook/Makefile.am new file mode 100755 index 0000000..a6e2107 --- /dev/null +++ b/.pc/tizen.patch/providers/skyhook/Makefile.am @@ -0,0 +1,35 @@ +libexec_PROGRAMS = \ + geoclue-skyhook + +geoclue_skyhook_SOURCES = \ + geoclue-skyhook.c + +geoclue_skyhook_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/src \ + $(GEOCLUE_CFLAGS) \ + $(SKYHOOK_CFLAGS) + +geoclue_skyhook_LDADD = \ + $(GEOCLUE_LIBS) \ + $(SKYHOOK_LIBS) \ + $(top_builddir)/src/libconnectivity.la \ + $(top_builddir)/geoclue/libgeoclue.la + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-skyhook.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Skyhook.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/providers/skyhook/geoclue-skyhook.c b/.pc/tizen.patch/providers/skyhook/geoclue-skyhook.c new file mode 100755 index 0000000..5af7b45 --- /dev/null +++ b/.pc/tizen.patch/providers/skyhook/geoclue-skyhook.c @@ -0,0 +1,303 @@ +/* + * Geoclue + * geoclue-skyhook.c - A skyhook.com-based Address/Position provider + * + * Author: Bastien Nocera <hadess@hadess.net> + * Copyright 2009 Bastien Nocera + */ + +#include <config.h> + +#include <time.h> +#include <string.h> +#include <errno.h> + +#include <glib-object.h> +#include <dbus/dbus-glib-bindings.h> +#include <libsoup/soup.h> +#include <libxml/xpathInternals.h> + +#include <geoclue/gc-web-service.h> +#include <geoclue/gc-provider.h> +#include <geoclue/geoclue-error.h> +#include <geoclue/gc-iface-position.h> + +#include "connectivity.h" + +#define GEOCLUE_DBUS_SERVICE_SKYHOOK "org.freedesktop.Geoclue.Providers.Skyhook" +#define GEOCLUE_DBUS_PATH_SKYHOOK "/org/freedesktop/Geoclue/Providers/Skyhook" +#define SKYHOOK_URL "https://api.skyhookwireless.com/wps2/location" +#define SKYHOOK_LAT_XPATH "//prefix:latitude" +#define SKYHOOK_LON_XPATH "//prefix:longitude" +#define USER_AGENT "Geoclue "VERSION + +#define GEOCLUE_TYPE_SKYHOOK (geoclue_skyhook_get_type ()) +#define GEOCLUE_SKYHOOK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_SKYHOOK, GeoclueSkyhook)) + +#define QUERY_START "<?xml version=\'1.0\'?><LocationRQ xmlns=\'http://skyhookwireless.com/wps/2005\' version=\'2.6\' street-address-lookup=\'full\'><authentication version=\'2.0\'><simple><username>beta</username><realm>js.loki.com</realm></simple></authentication>" +#define QUERY_AP "<access-point><mac>%s</mac><signal-strength>%d</signal-strength></access-point>" +#define QUERY_END "</LocationRQ>" + +typedef struct _GeoclueSkyhook { + GcProvider parent; + GMainLoop *loop; + SoupSession *session; + GeoclueConnectivity *conn; +} GeoclueSkyhook; + +typedef struct _GeoclueSkyhookClass { + GcProviderClass parent_class; +} GeoclueSkyhookClass; + + +static void geoclue_skyhook_init (GeoclueSkyhook *skyhook); +static void geoclue_skyhook_position_init (GcIfacePositionClass *iface); + +G_DEFINE_TYPE_WITH_CODE (GeoclueSkyhook, geoclue_skyhook, GC_TYPE_PROVIDER, + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION, + geoclue_skyhook_position_init)) + + +/* Geoclue interface implementation */ +static gboolean +geoclue_skyhook_get_status (GcIfaceGeoclue *iface, + GeoclueStatus *status, + GError **error) +{ + /* Assume available so long as all the requirements are satisfied + ie: Network is available */ + *status = GEOCLUE_STATUS_AVAILABLE; + return TRUE; +} + +static void +_shutdown (GcProvider *provider) +{ + GeoclueSkyhook *skyhook = GEOCLUE_SKYHOOK (provider); + g_main_loop_quit (skyhook->loop); +} + +static void +add_ap (gpointer key, + gpointer value, + gpointer data) +{ + char *mac; + char **split; + + /* Remove the ":" */ + split = g_strsplit (key, ":", -1); + mac = g_strjoinv ("", split); + g_strfreev (split); + + g_string_append_printf (data, QUERY_AP, mac, GPOINTER_TO_INT (value)); + g_free (mac); +} + +static char * +create_post_query (GeoclueConnectivity *conn) +{ + GHashTable *ht; + GString *str; + + ht = geoclue_connectivity_get_aps (conn); + if (ht == NULL) + return NULL; + str = g_string_new (QUERY_START); + g_hash_table_foreach (ht, add_ap, str); + g_string_append (str, QUERY_END); + g_hash_table_destroy (ht); + + return g_string_free (str, FALSE); +} + +static gboolean +get_double (xmlXPathContext *xpath_ctx, char *xpath, gdouble *value) +{ + xmlXPathObject *obj = NULL; + + obj = xmlXPathEvalExpression (BAD_CAST (xpath), xpath_ctx); + if (obj && + (!obj->nodesetval || xmlXPathNodeSetIsEmpty (obj->nodesetval))) { + xmlXPathFreeObject (obj); + return FALSE; + } + *value = xmlXPathCastNodeSetToNumber (obj->nodesetval); + xmlXPathFreeObject (obj); + return TRUE; +} + +static gboolean +parse_response (const char *body, gdouble *latitude, gdouble *longitude) +{ + xmlDocPtr doc; + xmlXPathContext *xpath_ctx; + gboolean ret = TRUE; + + doc = xmlParseDoc (BAD_CAST (body)); + if (!doc) + return FALSE; + + xpath_ctx = xmlXPathNewContext(doc); + if (!xpath_ctx) { + xmlFreeDoc (doc); + return FALSE; + } + xmlXPathRegisterNs (xpath_ctx, BAD_CAST ("prefix"), BAD_CAST("http://skyhookwireless.com/wps/2005")); + if (get_double (xpath_ctx, SKYHOOK_LAT_XPATH, latitude) == FALSE) { + ret = FALSE; + } else if (get_double (xpath_ctx, SKYHOOK_LON_XPATH, longitude) == FALSE) { + ret = FALSE; + } + xmlXPathFreeContext (xpath_ctx); + xmlFreeDoc (doc); + + return ret; +} + +/* Position interface implementation */ + +static gboolean +geoclue_skyhook_get_position (GcIfacePosition *iface, + GeocluePositionFields *fields, + int *timestamp, + double *latitude, + double *longitude, + double *altitude, + GeoclueAccuracy **accuracy, + GError **error) +{ + GeoclueSkyhook *skyhook; + char *query; + SoupMessage *msg; + + skyhook = (GEOCLUE_SKYHOOK (iface)); + + *fields = GEOCLUE_POSITION_FIELDS_NONE; + if (timestamp) + *timestamp = time (NULL); + + query = create_post_query (skyhook->conn); + if (query == NULL) { + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Router mac address query failed"); + /* TODO: set status == error ? */ + return FALSE; + } + + msg = soup_message_new ("POST", SKYHOOK_URL); + soup_message_headers_append (msg->request_headers, "User-Agent", USER_AGENT); + soup_message_set_request (msg, + "text/xml", + SOUP_MEMORY_TAKE, + query, + strlen (query)); + soup_session_send_message (skyhook->session, msg); + if (msg->response_body == NULL || msg->response_body->data == NULL) { + g_object_unref (msg); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Failed to query web service"); + return FALSE; + } + + if (strstr (msg->response_body->data, "<error>") != NULL) { + g_object_unref (msg); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Web service returned an error"); + return FALSE; + } + + if (parse_response (msg->response_body->data, latitude, longitude) == FALSE) { + g_object_unref (msg); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Couldn't parse response from web service"); + return FALSE; + } + + if (latitude) + *fields |= GEOCLUE_POSITION_FIELDS_LATITUDE; + if (longitude) + *fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE; + + if (accuracy) { + if (*fields == GEOCLUE_POSITION_FIELDS_NONE) { + *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, + 0, 0); + } else { + /* Educated guess. Skyhook are typically hand pointed on + * a map, or geocoded from address, so should be fairly + * accurate */ + *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_STREET, + 0, 0); + } + } + + return TRUE; +} + +static void +geoclue_skyhook_finalize (GObject *obj) +{ + GeoclueSkyhook *skyhook = GEOCLUE_SKYHOOK (obj); + + if (skyhook->conn != NULL) { + g_object_unref (skyhook->conn); + skyhook->conn = NULL; + } + g_object_unref (skyhook->session); + + ((GObjectClass *) geoclue_skyhook_parent_class)->finalize (obj); +} + + +/* Initialization */ + +static void +geoclue_skyhook_class_init (GeoclueSkyhookClass *klass) +{ + GcProviderClass *p_class = (GcProviderClass *)klass; + GObjectClass *o_class = (GObjectClass *)klass; + + p_class->shutdown = _shutdown; + p_class->get_status = geoclue_skyhook_get_status; + + o_class->finalize = geoclue_skyhook_finalize; +} + +static void +geoclue_skyhook_init (GeoclueSkyhook *skyhook) +{ + gc_provider_set_details (GC_PROVIDER (skyhook), + GEOCLUE_DBUS_SERVICE_SKYHOOK, + GEOCLUE_DBUS_PATH_SKYHOOK, + "Skyhook", "Skyhook.com based provider, uses gateway mac address to locate"); + skyhook->session = soup_session_sync_new (); + skyhook->conn = geoclue_connectivity_new (); +} + +static void +geoclue_skyhook_position_init (GcIfacePositionClass *iface) +{ + iface->get_position = geoclue_skyhook_get_position; +} + +int +main() +{ + g_type_init(); + g_thread_init (NULL); + + GeoclueSkyhook *o = g_object_new (GEOCLUE_TYPE_SKYHOOK, NULL); + o->loop = g_main_loop_new (NULL, TRUE); + + g_main_loop_run (o->loop); + + g_main_loop_unref (o->loop); + g_object_unref (o); + + return 0; +} diff --git a/.pc/tizen.patch/providers/skyhook/geoclue-skyhook.provider b/.pc/tizen.patch/providers/skyhook/geoclue-skyhook.provider new file mode 100755 index 0000000..1e0fcde --- /dev/null +++ b/.pc/tizen.patch/providers/skyhook/geoclue-skyhook.provider @@ -0,0 +1,8 @@ +[Geoclue Provider] +Name=Skyhook +Service=org.freedesktop.Geoclue.Providers.Skyhook +Path=/org/freedesktop/Geoclue/Providers/Skyhook +Accuracy=Street +Requires=RequiresNetwork +Provides=ProvidesCacheableOnConnection +Interfaces=org.freedesktop.Geoclue.Position diff --git a/.pc/tizen.patch/providers/yahoo/Makefile.am b/.pc/tizen.patch/providers/yahoo/Makefile.am new file mode 100755 index 0000000..fee408b --- /dev/null +++ b/.pc/tizen.patch/providers/yahoo/Makefile.am @@ -0,0 +1,31 @@ +libexec_PROGRAMS = \ + geoclue-yahoo + +geoclue_yahoo_SOURCES = \ + geoclue-yahoo.c + +geoclue_yahoo_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) + +geoclue_yahoo_LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-yahoo.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Yahoo.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) |