Open Source Telephony
 help / color / mirror / Atom feed
From: Giacinto Cifelli <gciofono@gmail.com>
To: ofono@ofono.org
Subject: [PATCH] gemalto/location-reporting: add driver properties
Date: Sun, 23 Sep 2018 08:19:22 +0200	[thread overview]
Message-ID: <20180923061922.23288-3-gciofono@gmail.com> (raw)
In-Reply-To: <20180923061922.23288-1-gciofono@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 13296 bytes --]

---
 drivers/gemaltomodem/location-reporting.c | 317 ++++++++++++++++++++--
 1 file changed, 291 insertions(+), 26 deletions(-)

diff --git a/drivers/gemaltomodem/location-reporting.c b/drivers/gemaltomodem/location-reporting.c
index bcfe00e5..375b7bfa 100644
--- a/drivers/gemaltomodem/location-reporting.c
+++ b/drivers/gemaltomodem/location-reporting.c
@@ -3,6 +3,7 @@
  *  oFono - Open Source Telephony
  *
  *  Copyright (C) 2017 Vincent Cesson. All rights reserved.
+ *  Copyright (C) 2018 Gemalto M2M
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
@@ -31,38 +32,62 @@
 #include <unistd.h>
 
 #include <glib.h>
+#include <gdbus.h>
 
 #include <ofono/log.h>
 #include <ofono/modem.h>
 #include <ofono/location-reporting.h>
 
+#include <src/storage.h>
+
 #include "gatchat.h"
 #include "gatresult.h"
 #include "gattty.h"
 
+#include "ofono.h"
+#include "common.h"
+
 #include "gemaltomodem.h"
 
+struct ofono_location_reporting {
+	DBusMessage *pending;
+	const struct ofono_location_reporting_driver *driver;
+	void *driver_data;
+	struct ofono_atom *atom;
+	ofono_bool_t enabled;
+	char *client_owner;
+	guint disconnect_watch;
+};
+
 static const char *sgpsc_prefix[] = { "^SGPSC:", NULL };
 
+#define MAX_GNSS_PROPERTIES		(64)
+#define MAX_GNSS_STRLEN			(32)
+
+typedef struct _gnss_property {
+	uint type; // dynamic or stored, exclude, value_s or value_i
+	char name[MAX_GNSS_STRLEN];
+	union {
+		char value_s[32];
+		int value_i;
+	};
+} gnss_property;
+
 struct gps_data {
 	GAtChat *chat;
+	gnss_property properties[MAX_GNSS_PROPERTIES];
 };
 
 static void gemalto_gps_disable_cb(gboolean ok, GAtResult *result,
 							gpointer user_data)
 {
 	struct cb_data *cbd = user_data;
-	struct ofono_location_reporting *lr = cbd->user;
 	ofono_location_reporting_disable_cb_t cb = cbd->cb;
 
-	DBG("lr=%p, ok=%d", lr, ok);
-
 	if (!ok) {
 		struct ofono_error error;
-
 		decode_at_error(&error, g_at_result_final_response(result));
 		cb(&error, cbd->data);
-
 		return;
 	}
 
@@ -77,8 +102,6 @@ static void gemalto_location_reporting_disable(
 	struct gps_data *gd = ofono_location_reporting_get_data(lr);
 	struct cb_data *cbd = cb_data_new(cb, data);
 
-	DBG("lr=%p", lr);
-
 	cbd->user = lr;
 
 	if (g_at_chat_send(gd->chat, "AT^SGPSC=\"Engine\",0", sgpsc_prefix,
@@ -86,36 +109,32 @@ static void gemalto_location_reporting_disable(
 		return;
 
 	CALLBACK_WITH_FAILURE(cb, data);
-
 	g_free(cbd);
 }
 
 static int enable_data_stream(struct ofono_location_reporting *lr)
 {
 	struct ofono_modem *modem;
-	const char *gps_dev;
+	const char *gnss_dev;
 	GHashTable *options;
 	GIOChannel *channel;
 	int fd;
 
 	modem = ofono_location_reporting_get_modem(lr);
-	gps_dev = ofono_modem_get_string(modem, "GPS");
-
+	gnss_dev = ofono_modem_get_string(modem, "GNSS");
 	options = g_hash_table_new(g_str_hash, g_str_equal);
-	if (options == NULL)
+
+	if (!gnss_dev || !*gnss_dev || !options)
 		return -1;
 
 	g_hash_table_insert(options, "Baud", "115200");
-
-	channel = g_at_tty_open(gps_dev, options);
-
+	channel = g_at_tty_open(gnss_dev, options);
 	g_hash_table_destroy(options);
 
-	if (channel == NULL)
+	if (!channel)
 		return -1;
 
 	fd = g_io_channel_unix_get_fd(channel);
-
 	g_io_channel_set_close_on_unref(channel, FALSE);
 	g_io_channel_unref(channel);
 
@@ -131,8 +150,6 @@ static void gemalto_sgpsc_cb(gboolean ok, GAtResult *result,
 	struct ofono_error error;
 	int fd;
 
-	DBG("lr=%p ok=%d", lr, ok);
-
 	decode_at_error(&error, g_at_result_final_response(result));
 
 	if (!ok) {
@@ -153,15 +170,14 @@ static void gemalto_sgpsc_cb(gboolean ok, GAtResult *result,
 	close(fd);
 }
 
-static void gemalto_location_reporting_enable(struct ofono_location_reporting *lr,
+static void gemalto_location_reporting_enable(
+					struct ofono_location_reporting *lr,
 					ofono_location_reporting_enable_cb_t cb,
 					void *data)
 {
 	struct gps_data *gd = ofono_location_reporting_get_data(lr);
 	struct cb_data *cbd = cb_data_new(cb, data);
 
-	DBG("lr=%p", lr);
-
 	cbd->user = lr;
 
 	if (g_at_chat_send(gd->chat, "AT^SGPSC=\"Engine\",2", sgpsc_prefix,
@@ -172,6 +188,205 @@ static void gemalto_location_reporting_enable(struct ofono_location_reporting *l
 	g_free(cbd);
 }
 
+static void gemalto_location_reporting_get_properties(
+			struct ofono_location_reporting *lr, void *_dict)
+{
+	DBusMessageIter *dict = _dict;
+	struct gps_data *gd = ofono_location_reporting_get_data(lr);
+	int property_pos = 0;
+	struct ofono_modem *modem = ofono_location_reporting_get_modem(lr);
+	const char *port = ofono_modem_get_string(modem, "GNSS");
+	const char *prop_port = "Port";
+
+	while(property_pos < MAX_GNSS_PROPERTIES &&
+					*gd->properties[property_pos].name) {
+		char *propval = gd->properties[property_pos].value_s;
+		ofono_dbus_dict_append(dict, gd->properties[property_pos].name,
+						DBUS_TYPE_STRING, &propval);
+		property_pos++;
+	}
+
+	/* add port outside of the modem property list */
+	DBG("%s=%s", prop_port, port);
+	if (port)
+		ofono_dbus_dict_append(dict, prop_port, DBUS_TYPE_STRING, &port);
+}
+
+static void change_property_list(GAtResult *result, gpointer user_data) {
+	struct ofono_location_reporting *lr = user_data;
+	struct gps_data *gd = ofono_location_reporting_get_data(lr);
+	GAtResultIter iter;
+	int property_pos;
+	DBusConnection *conn = ofono_dbus_get_connection();
+	const char *path = __ofono_atom_get_path(lr->atom);
+
+	g_at_result_iter_init(&iter, result);
+
+	/* supported format: ^SGPSC: "Nmea/Output","off" */
+	while (g_at_result_iter_next(&iter, "^SGPSC:")) {
+		const char *name = "";
+		const char *val = "";
+
+		if (!g_at_result_iter_next_string(&iter, &name))
+			continue;
+
+		/*
+		 * skip the "Info" property:
+		 * different line format and different usage
+		 */
+		if (g_str_equal(name,"Info"))
+			continue;
+
+		if (!g_at_result_iter_next_string(&iter, &val))
+			continue;
+
+		for(property_pos = 0; property_pos < MAX_GNSS_PROPERTIES &&
+			   *gd->properties[property_pos].name; property_pos++) {
+
+			if (!g_str_equal(gd->properties[property_pos].name,
+									name))
+				continue;
+
+			strncpy(gd->properties[property_pos].value_s,val,
+					MAX_GNSS_STRLEN);
+			ofono_dbus_signal_property_changed(conn, path,
+					OFONO_LOCATION_REPORTING_INTERFACE,
+					name, DBUS_TYPE_STRING, &val);
+		}
+	}
+}
+
+static void gemalto_location_reporting_set_property_cb(gboolean ok,
+					GAtResult *result, gpointer user_data)
+{
+	struct ofono_location_reporting *lr = user_data;
+
+	if (!ok || !lr)
+		return;
+
+	change_property_list(result, lr);
+}
+
+static void *gemalto_location_reporting_set_property(
+				struct ofono_location_reporting *lr, void *_msg)
+{
+	DBusMessage *msg = _msg;
+	struct gps_data *gd;
+	DBusMessageIter iter, var;
+	const char *name;
+	int property_pos;
+
+	DBG("");
+	if (!lr)
+		return __ofono_error_not_available(msg);
+
+	gd = ofono_location_reporting_get_data(lr);
+
+	if (!gd)
+		return __ofono_error_not_available(msg);
+
+	if (dbus_message_iter_init(msg, &iter) == FALSE)
+		return __ofono_error_invalid_args(msg);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+		return __ofono_error_invalid_args(msg);
+
+	dbus_message_iter_get_basic(&iter, &name);
+	dbus_message_iter_next(&iter);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+		return __ofono_error_invalid_args(msg);
+
+	dbus_message_iter_recurse(&iter, &var);
+
+	property_pos = 0;
+
+	while(property_pos < MAX_GNSS_PROPERTIES &&
+					*gd->properties[property_pos].name) {
+
+		if (g_str_equal(name, gd->properties[property_pos].name))
+		{
+			char s[128];
+			char *value;
+
+			if (dbus_message_iter_get_arg_type(&var) !=
+							DBUS_TYPE_STRING)
+				return __ofono_error_invalid_args(msg);
+
+			dbus_message_iter_get_basic(&var, &value);
+
+			/* do not set the same value and do not notify change */
+			if (g_str_equal(value,
+					gd->properties[property_pos].value_s))
+				return __ofono_error_not_available(msg);
+
+			sprintf(s, "AT^SGPSC=\"%s\",\"%s\"",name, value);
+			DBG("setting %s", s);
+
+			/* TODO: report value changed */
+
+			if (g_at_chat_send(gd->chat, s, sgpsc_prefix,
+				    gemalto_location_reporting_set_property_cb,
+								lr, NULL) > 0)
+
+				return dbus_message_new_method_return(msg);
+
+			return __ofono_error_not_available(msg);
+		}
+		property_pos++;
+
+	}
+
+	return __ofono_error_invalid_args(msg);
+}
+
+static void build_property_list(GAtResult *result, gpointer user_data) {
+	struct ofono_location_reporting *lr = user_data;
+	struct gps_data *gd = ofono_location_reporting_get_data(lr);
+	GAtResultIter iter;
+	int property_pos = 0;
+
+	/* skip pre-set */
+	while (property_pos < MAX_GNSS_PROPERTIES &&
+					*gd->properties[property_pos].name)
+		property_pos++;
+
+	g_at_result_iter_init(&iter, result);
+
+	/* supported format: ^SGPSC: "Nmea/Output","off" */
+	while ((property_pos < MAX_GNSS_PROPERTIES) &&
+				g_at_result_iter_next(&iter, "^SGPSC:")) {
+		const char *name = "";
+		const char *val = "";
+
+		if (!g_at_result_iter_next_string(&iter, &name))
+			continue;
+
+		/*
+		 * skip the "Info" property:
+		 * different line format and different usage
+		 */
+		if (g_str_equal(name,"Info"))
+			continue;
+
+		if (!g_at_result_iter_next_string(&iter, &val))
+			continue;
+
+		strncpy(gd->properties[property_pos].name, name,
+							MAX_GNSS_STRLEN);
+		strncpy(gd->properties[property_pos].value_s, val,
+							MAX_GNSS_STRLEN);
+		property_pos++;
+	}
+
+	property_pos = 0;
+
+	while ((property_pos < MAX_GNSS_PROPERTIES) &&
+					*gd->properties[property_pos].name) {
+		property_pos++;
+	}
+}
+
 static void gemalto_location_reporting_support_cb(gboolean ok, GAtResult *result,
 							gpointer user_data)
 {
@@ -179,13 +394,50 @@ static void gemalto_location_reporting_support_cb(gboolean ok, GAtResult *result
 
 	if (!ok) {
 		ofono_location_reporting_remove(lr);
-
 		return;
 	}
 
+	build_property_list(result, user_data);
 	ofono_location_reporting_register(lr);
 }
 
+static void gemalto_locrep_stored(struct ofono_location_reporting *lr) {
+	struct ofono_modem *modem = ofono_location_reporting_get_modem(lr);
+	struct gps_data *gd = ofono_location_reporting_get_data(lr);
+	const char *vid = ofono_modem_get_string(modem, "Vendor");
+	const char *pid = ofono_modem_get_string(modem, "Model");
+	char store[32];
+	int index;
+	char *property, *value;
+	char key[32];
+	GKeyFile *f;
+	char *command;
+
+	sprintf(store,"%s-%s/location-reporting", vid, pid);
+	f = storage_open(NULL, store);
+
+	if (!f)
+		return;
+
+	for (index = 0; ; index++) {
+		sprintf(key, "property_%d", index);
+		property = g_key_file_get_string(f, "Properties", key, NULL);
+
+		sprintf(key, "value_%d", index);
+		value = g_key_file_get_string(f, "Properties", key, NULL);
+
+		if (!property || !value)
+			break;
+
+		command = g_strdup_printf("AT^SGPSC=%s,%s", property, value);
+		DBG("setting GNSS property: %s", command);
+		g_at_chat_send(gd->chat, command, NULL, NULL, NULL, NULL);
+		free(command);
+	}
+
+	storage_close(NULL, store, f, FALSE);
+}
+
 static int gemalto_location_reporting_probe(struct ofono_location_reporting *lr,
 						unsigned int vendor, void *data)
 {
@@ -193,24 +445,35 @@ static int gemalto_location_reporting_probe(struct ofono_location_reporting *lr,
 	struct gps_data *gd;
 
 	gd = g_try_new0(struct gps_data, 1);
+
 	if (gd == NULL)
 		return -ENOMEM;
 
 	gd->chat = g_at_chat_clone(chat);
-
 	ofono_location_reporting_set_data(lr, gd);
 
-	g_at_chat_send(gd->chat, "AT^SGPSC=?", sgpsc_prefix,
+	/*
+	 * Storage of parameters is read-only.
+	 * It is intended for preconfiguring the devide by tbe manufacturer.
+	 * The parameters are stored by USB VID-PID, because
+	 * they are not standardized, and each model can have its own set.
+	 */
+	gemalto_locrep_stored(lr);
+
+	g_at_chat_send(gd->chat, "AT^SGPSC?", sgpsc_prefix,
 					gemalto_location_reporting_support_cb,
 					lr, NULL);
 
 	return 0;
 }
 
-static void gemalto_location_reporting_remove(struct ofono_location_reporting *lr)
+static void gemalto_location_reporting_remove(struct ofono_location_reporting
+									*lr)
 {
 	struct gps_data *gd = ofono_location_reporting_get_data(lr);
 
+	/* TODO: store modified params if [Settings] sync==yes */
+
 	ofono_location_reporting_set_data(lr, NULL);
 
 	g_at_chat_unref(gd->chat);
@@ -224,6 +487,8 @@ static struct ofono_location_reporting_driver driver = {
 	.remove			= gemalto_location_reporting_remove,
 	.enable			= gemalto_location_reporting_enable,
 	.disable		= gemalto_location_reporting_disable,
+	.get_properties		= gemalto_location_reporting_get_properties,
+	.set_property		= gemalto_location_reporting_set_property
 };
 
 void gemalto_location_reporting_init()
-- 
2.17.1


  parent reply	other threads:[~2018-09-23  6:19 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-23  6:19 [PATCH] location-reporting.h: driver properties handling Giacinto Cifelli
2018-09-23  6:19 ` [PATCH] src/location-reporting: " Giacinto Cifelli
2018-09-23  6:19 ` Giacinto Cifelli [this message]
2018-09-24 21:07 ` [PATCH] location-reporting.h: " Denis Kenzior
2018-09-25  3:49   ` Giacinto Cifelli

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180923061922.23288-3-gciofono@gmail.com \
    --to=gciofono@gmail.com \
    --cc=ofono@ofono.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox