All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/1] Create network registration driver for hfpmodem
  2009-10-23 21:36 [PATCH 0/1] netreg driver for HFP Gustavo F. Padovan
@ 2009-10-23 21:36 ` Gustavo F. Padovan
  2009-10-26  9:01   ` Naveen Verma
  0 siblings, 1 reply; 9+ messages in thread
From: Gustavo F. Padovan @ 2009-10-23 21:36 UTC (permalink / raw)
  To: ofono

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

This driver handles phone informations about registration status, signal
strength and roaming status listening +CIEV commands.
It also gets the Network Operator name with +COPS commands.
---
 Makefile.am                             |    3 +-
 drivers/hfpmodem/hfpmodem.c             |    2 +
 drivers/hfpmodem/hfpmodem.h             |    3 +
 drivers/hfpmodem/network-registration.c |  172 +++++++++++++++++++++++++++++++
 plugins/hfp.c                           |    1 +
 5 files changed, 180 insertions(+), 1 deletions(-)
 create mode 100644 drivers/hfpmodem/network-registration.c

diff --git a/Makefile.am b/Makefile.am
index 561eeb0..332e10b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -123,7 +123,8 @@ builtin_modules += hfpmodem
 builtin_sources += drivers/atmodem/atutil.h \
 			drivers/hfpmodem/hfpmodem.h \
 			drivers/hfpmodem/hfpmodem.c \
-			drivers/hfpmodem/voicecall.c
+			drivers/hfpmodem/voicecall.c \
+			drivers/hfpmodem/network-registration.c
 
 builtin_modules += modemconf
 builtin_sources += plugins/modemconf.c
diff --git a/drivers/hfpmodem/hfpmodem.c b/drivers/hfpmodem/hfpmodem.c
index 03b5ea0..58ae03d 100644
--- a/drivers/hfpmodem/hfpmodem.c
+++ b/drivers/hfpmodem/hfpmodem.c
@@ -42,6 +42,7 @@
 static int hfpmodem_init(void)
 {
 	hfp_voicecall_init();
+	hfp_netreg_init();
 
 	return 0;
 }
@@ -49,6 +50,7 @@ static int hfpmodem_init(void)
 static void hfpmodem_exit(void)
 {
 	hfp_voicecall_exit();
+	hfp_netreg_exit();
 }
 
 OFONO_PLUGIN_DEFINE(hfpmodem, "Hands-Free Profile Driver", VERSION,
diff --git a/drivers/hfpmodem/hfpmodem.h b/drivers/hfpmodem/hfpmodem.h
index 6c6ab6f..3b30d83 100644
--- a/drivers/hfpmodem/hfpmodem.h
+++ b/drivers/hfpmodem/hfpmodem.h
@@ -61,6 +61,9 @@ struct hfp_data {
 	gint cind_val[HFP_INDICATOR_LAST];
 };
 
+extern void hfp_netreg_init();
+extern void hfp_netreg_exit();
+
 extern void hfp_voicecall_init();
 extern void hfp_voicecall_exit();
 
diff --git a/drivers/hfpmodem/network-registration.c b/drivers/hfpmodem/network-registration.c
new file mode 100644
index 0000000..c23d07e
--- /dev/null
+++ b/drivers/hfpmodem/network-registration.c
@@ -0,0 +1,172 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2009  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2009 ProFUSION embedded systems. All rights reserved.
+ *
+ *  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
+ *  published by the Free Software Foundation.
+ *
+ *  This program 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 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <glib.h>
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/netreg.h>
+
+#include "gatchat.h"
+#include "gatresult.h"
+
+#include "hfpmodem.h"
+
+#define OFONO_MAX_HFP_OPERATOR_NAME_LENGTH 16
+
+static const char *cops_prefix[] = { "+COPS:", NULL };
+
+struct netreg_data {
+	GAtChat *chat;
+	unsigned char cind_pos[HFP_INDICATOR_LAST];
+	int cind_val[HFP_INDICATOR_LAST];
+	char operator[16];
+};
+
+static void cops_name_notify(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct ofono_netreg *netreg = user_data;
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+	GAtResultIter iter;
+	int format;
+	const char *name;
+
+	if (!ok) {
+		ofono_error("Unable to get name of the registered Network");
+		ofono_netreg_remove(netreg);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+COPS:"))
+		return;
+
+	g_at_result_iter_skip_next(&iter);
+
+	ok = g_at_result_iter_next_number(&iter, &format);
+
+	if (ok == FALSE || format != 0)
+		return;
+
+	if (g_at_result_iter_next_string(&iter, &name) == FALSE)
+		return;
+
+	strncpy(nd->operator, name, OFONO_MAX_HFP_OPERATOR_NAME_LENGTH);
+	nd->operator[OFONO_MAX_HFP_OPERATOR_NAME_LENGTH] = '\0';
+}
+
+static void cops_notify(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct ofono_netreg *netreg = user_data;
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+
+	if (!ok) {
+		ofono_error("Unable to get name of the registered Network");
+		ofono_netreg_remove(netreg);
+		return;
+	}
+
+	g_at_chat_send(nd->chat, "AT+COPS?", cops_prefix,
+				cops_name_notify, netreg, NULL);
+}
+
+static void ciev_notify(GAtResult *result, gpointer user_data)
+{
+	struct ofono_netreg *netreg = user_data;
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+	GAtResultIter iter;
+	int index, value;
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CIEV:"))
+		return;
+
+	if (!g_at_result_iter_next_number(&iter, &index))
+		return;
+
+	if (!g_at_result_iter_next_number(&iter, &value))
+		return;
+
+	if (index == nd->cind_pos[HFP_INDICATOR_SERVICE])
+		nd->cind_val[HFP_INDICATOR_SERVICE] = value;
+	else if (index == nd->cind_pos[HFP_INDICATOR_ROAM])
+		nd->cind_val[HFP_INDICATOR_ROAM] = value;
+	else if (index == nd->cind_pos[HFP_INDICATOR_SIGNAL])
+		nd->cind_val[HFP_INDICATOR_SIGNAL] = value;
+
+	return;
+}
+
+static int hfp_netreg_probe(struct ofono_netreg *netreg, unsigned int vendor,
+				void *user_data)
+{
+	struct hfp_data *data = user_data;
+	struct netreg_data *nd;
+
+	nd = g_new0(struct netreg_data, 1);
+	nd->chat = data->chat;
+	memcpy(nd->cind_pos, data->cind_pos, HFP_INDICATOR_LAST);
+	memcpy(nd->cind_val, data->cind_val, HFP_INDICATOR_LAST);
+
+	ofono_netreg_set_data(netreg, nd);
+
+	g_at_chat_send(nd->chat, "AT+COPS=3,0", NULL,
+				cops_notify, netreg, NULL);
+	g_at_chat_register(nd->chat, "+CIEV:", ciev_notify, FALSE,
+			netreg, NULL);
+
+	return 0;
+}
+
+static void hfp_netreg_remove(struct ofono_netreg *netreg)
+{
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+
+	g_free(nd);
+}
+
+static struct ofono_netreg_driver driver = {
+	.name				= "hfpmodem",
+	.probe				= hfp_netreg_probe,
+	.remove				= hfp_netreg_remove,
+};
+
+void hfp_netreg_init()
+{
+	ofono_netreg_driver_register(&driver);
+}
+
+void hfp_netreg_exit()
+{
+	ofono_netreg_driver_unregister(&driver);
+}
diff --git a/plugins/hfp.c b/plugins/hfp.c
index 5e94a05..be812cd 100644
--- a/plugins/hfp.c
+++ b/plugins/hfp.c
@@ -311,6 +311,7 @@ static void hfp_pre_sim(struct ofono_modem *modem)
 
 	DBG("%p", modem);
 	ofono_voicecall_create(modem, 0, "hfpmodem", data);
+	ofono_netreg_create(modem, 0, "hfpmodem", data);
 }
 
 static void hfp_post_sim(struct ofono_modem *modem)
-- 
1.6.4.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] Create network registration driver for hfpmodem
  2009-10-23 21:36 ` [PATCH 1/1] Create network registration driver for hfpmodem Gustavo F. Padovan
@ 2009-10-26  9:01   ` Naveen Verma
  2009-10-26 14:27     ` Gustavo F. Padovan
  0 siblings, 1 reply; 9+ messages in thread
From: Naveen Verma @ 2009-10-26  9:01 UTC (permalink / raw)
  To: ofono

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

> @@ -0,0 +1,172 @@
> +/*
> + *
> + *  oFono - Open Source Telephony
> + *
> + *  Copyright (C) 2008-2009  Intel Corporation. All rights reserved.
> + *  Copyright (C) 2009 ProFUSION embedded systems. All rights reserved.
> + *
> + *  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
> + *  published by the Free Software Foundation.
> + *
> + *  This program 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 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 St, Fifth Floor, Boston, MA  02110-1301
>  USA
> + *
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +#include <config.h>
> +#endif
> +
> +#define _GNU_SOURCE
> +#include <string.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +
> +#include <glib.h>
> +
> +#include <ofono/log.h>
> +#include <ofono/modem.h>
> +#include <ofono/netreg.h>
> +
> +#include "gatchat.h"
> +#include "gatresult.h"
> +
> +#include "hfpmodem.h"
> +
> +#define OFONO_MAX_HFP_OPERATOR_NAME_LENGTH 16
> +
> +static const char *cops_prefix[] = { "+COPS:", NULL };
> +
> +struct netreg_data {
> +       GAtChat *chat;
> +       unsigned char cind_pos[HFP_INDICATOR_LAST];
> +       int cind_val[HFP_INDICATOR_LAST];
> +       char operator[16];
>

-- Should we use above #define for operator name length?
 -Br
Naveen

[-- Attachment #2: attachment.html --]
[-- Type: text/html, Size: 2061 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] Create network registration driver for hfpmodem
  2009-10-26  9:01   ` Naveen Verma
@ 2009-10-26 14:27     ` Gustavo F. Padovan
  0 siblings, 0 replies; 9+ messages in thread
From: Gustavo F. Padovan @ 2009-10-26 14:27 UTC (permalink / raw)
  To: ofono

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

On Mon, Oct 26, 2009 at 7:01 AM, Naveen Verma <ernaveenverma@gmail.com> wrote:
>
>
>>
>> @@ -0,0 +1,172 @@
>> +/*
>> + *
>> + *  oFono - Open Source Telephony
>> + *
>> + *  Copyright (C) 2008-2009  Intel Corporation. All rights reserved.
>> + *  Copyright (C) 2009 ProFUSION embedded systems. All rights reserved.
>> + *
>> + *  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
>> + *  published by the Free Software Foundation.
>> + *
>> + *  This program 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 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 St, Fifth Floor, Boston, MA  02110-1301
>>  USA
>> + *
>> + */
>> +
>> +#ifdef HAVE_CONFIG_H
>> +#include <config.h>
>> +#endif
>> +
>> +#define _GNU_SOURCE
>> +#include <string.h>
>> +#include <stdlib.h>
>> +#include <stdio.h>
>> +
>> +#include <glib.h>
>> +
>> +#include <ofono/log.h>
>> +#include <ofono/modem.h>
>> +#include <ofono/netreg.h>
>> +
>> +#include "gatchat.h"
>> +#include "gatresult.h"
>> +
>> +#include "hfpmodem.h"
>> +
>> +#define OFONO_MAX_HFP_OPERATOR_NAME_LENGTH 16
>> +
>> +static const char *cops_prefix[] = { "+COPS:", NULL };
>> +
>> +struct netreg_data {
>> +       GAtChat *chat;
>> +       unsigned char cind_pos[HFP_INDICATOR_LAST];
>> +       int cind_val[HFP_INDICATOR_LAST];
>> +       char operator[16];
>
> -- Should we use above #define for operator name length?

Yes, I missed that. Thanks.

>  -Br
> Naveen
>
>
>
> _______________________________________________
> ofono mailing list
> ofono(a)ofono.org
> http://lists.ofono.org/listinfo/ofono
>
>



-- 
Gustavo F. Padovan
http://padovan.org

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/1] Create network registration driver for hfpmodem
@ 2009-10-30 22:55 Gustavo F. Padovan
  0 siblings, 0 replies; 9+ messages in thread
From: Gustavo F. Padovan @ 2009-10-30 22:55 UTC (permalink / raw)
  To: ofono

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

This driver handles phone informations about registration status, signal
strength and roaming status listening +CIEV commands.  It also gets the
Network Operator name with +COPS commands.
---
 Makefile.am                             |    3 +-
 drivers/hfpmodem/hfpmodem.c             |    2 +
 drivers/hfpmodem/hfpmodem.h             |    3 +
 drivers/hfpmodem/network-registration.c |  365 +++++++++++++++++++++++++++++++
 plugins/hfp.c                           |    1 +
 5 files changed, 373 insertions(+), 1 deletions(-)
 create mode 100644 drivers/hfpmodem/network-registration.c

diff --git a/Makefile.am b/Makefile.am
index 8e56568..c3e06b4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -126,7 +126,8 @@ builtin_modules += hfpmodem
 builtin_sources += drivers/atmodem/atutil.h \
 			drivers/hfpmodem/hfpmodem.h \
 			drivers/hfpmodem/hfpmodem.c \
-			drivers/hfpmodem/voicecall.c
+			drivers/hfpmodem/voicecall.c \
+			drivers/hfpmodem/network-registration.c
 
 builtin_modules += mbmmodem
 builtin_sources += drivers/atmodem/atutil.h \
diff --git a/drivers/hfpmodem/hfpmodem.c b/drivers/hfpmodem/hfpmodem.c
index 03b5ea0..58ae03d 100644
--- a/drivers/hfpmodem/hfpmodem.c
+++ b/drivers/hfpmodem/hfpmodem.c
@@ -42,6 +42,7 @@
 static int hfpmodem_init(void)
 {
 	hfp_voicecall_init();
+	hfp_netreg_init();
 
 	return 0;
 }
@@ -49,6 +50,7 @@ static int hfpmodem_init(void)
 static void hfpmodem_exit(void)
 {
 	hfp_voicecall_exit();
+	hfp_netreg_exit();
 }
 
 OFONO_PLUGIN_DEFINE(hfpmodem, "Hands-Free Profile Driver", VERSION,
diff --git a/drivers/hfpmodem/hfpmodem.h b/drivers/hfpmodem/hfpmodem.h
index c4e2a34..02f5a4b 100644
--- a/drivers/hfpmodem/hfpmodem.h
+++ b/drivers/hfpmodem/hfpmodem.h
@@ -61,6 +61,9 @@ struct hfp_data {
 	unsigned int cind_val[HFP_INDICATOR_LAST];
 };
 
+extern void hfp_netreg_init();
+extern void hfp_netreg_exit();
+
 extern void hfp_voicecall_init();
 extern void hfp_voicecall_exit();
 
diff --git a/drivers/hfpmodem/network-registration.c b/drivers/hfpmodem/network-registration.c
new file mode 100644
index 0000000..6cfaf57
--- /dev/null
+++ b/drivers/hfpmodem/network-registration.c
@@ -0,0 +1,365 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2009  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2009 ProFUSION embedded systems. All rights reserved.
+ *
+ *  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
+ *  published by the Free Software Foundation.
+ *
+ *  This program 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 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <glib.h>
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/netreg.h>
+
+#include "gatchat.h"
+#include "gatresult.h"
+#include "common.h"
+
+#include "hfpmodem.h"
+
+#define HFP_MAX_OPERATOR_NAME_LENGTH 16
+
+static const char *cops_prefix[] = { "+COPS:", NULL };
+static const char *cind_prefix[] = { "+CIND:", NULL };
+
+struct netreg_data {
+	GAtChat *chat;
+	unsigned char cind_pos[HFP_INDICATOR_LAST];
+	int cind_val[HFP_INDICATOR_LAST];
+};
+
+static void cops_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	struct netreg_data *nd = ofono_netreg_get_data(cbd->user);
+	ofono_netreg_operator_cb_t cb = cbd->cb;
+	struct ofono_network_operator op;
+	GAtResultIter iter;
+	int format;
+	const char *name;
+	struct ofono_error error;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, NULL, cbd->data);
+		goto out;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+COPS:"))
+		return;
+
+	g_at_result_iter_skip_next(&iter);
+
+	ok = g_at_result_iter_next_number(&iter, &format);
+
+	if (ok == FALSE || format != 0)
+		return;
+
+	if (g_at_result_iter_next_string(&iter, &name) == FALSE)
+		return;
+
+	strncpy(op.name, name, HFP_MAX_OPERATOR_NAME_LENGTH);
+	op.name[HFP_MAX_OPERATOR_NAME_LENGTH] = '\0';
+
+	op.mcc[0] = '\0';
+	op.mnc[0] = '\0';
+
+	cb(&error, &op, cbd->data);
+
+out:
+	g_free(cbd);
+
+	return;
+
+error:
+	CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+
+	g_free(cbd);
+}
+
+static void ciev_notify(GAtResult *result, gpointer user_data)
+{
+	struct ofono_netreg *netreg = user_data;
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+	GAtResultIter iter;
+	int index, value, status;
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CIEV:"))
+		return;
+
+	if (!g_at_result_iter_next_number(&iter, &index))
+		return;
+
+	if (!g_at_result_iter_next_number(&iter, &value))
+		return;
+
+	if (index == nd->cind_pos[HFP_INDICATOR_SERVICE]) {
+		nd->cind_val[HFP_INDICATOR_SERVICE] = value;
+		if (value)
+			status = NETWORK_REGISTRATION_STATUS_REGISTERED;
+		else
+			status = NETWORK_REGISTRATION_STATUS_NOT_REGISTERED;
+
+		ofono_netreg_status_notify(netreg, status, -1, -1, -1);
+	} else if (index == nd->cind_pos[HFP_INDICATOR_ROAM]) {
+		nd->cind_val[HFP_INDICATOR_ROAM] = value;
+		if (value)
+			status = NETWORK_REGISTRATION_STATUS_ROAMING;
+
+		ofono_netreg_status_notify(netreg, status, -1, -1, -1);
+	} else if (index == nd->cind_pos[HFP_INDICATOR_SIGNAL]) {
+		nd->cind_val[HFP_INDICATOR_SIGNAL] = value;
+		ofono_netreg_strength_notify(netreg, value * 20);
+	}
+
+	return;
+}
+
+static void signal_strength_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_netreg_strength_cb_t cb = cbd->cb;
+	struct netreg_data *nd = ofono_netreg_get_data(cbd->user);
+	GAtResultIter iter;
+	int index, strength;
+	struct ofono_error error;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, -1, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CIND:")) {
+		CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+		return;
+	}
+
+	index = 1;
+
+	while (g_at_result_iter_next_number(&iter, &strength)) {
+		if (index == nd->cind_pos[HFP_INDICATOR_SIGNAL]) {
+			nd->cind_val[HFP_INDICATOR_SIGNAL] = strength;
+			break;
+		}
+
+		index++;
+	}
+
+	ofono_debug("signal_strength_cb: %d", strength);
+
+	cb(&error, strength * 20, cbd->data);
+}
+
+static void registration_status_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_netreg_status_cb_t cb = cbd->cb;
+	struct netreg_data *nd = ofono_netreg_get_data(cbd->user);
+	GAtResultIter iter;
+	int index, value, status;
+	struct ofono_error error;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, -1, -1, -1, -1, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CIND:")) {
+		CALLBACK_WITH_FAILURE(cb, -1, -1, -1, -1, cbd->data);
+		return;
+	}
+
+	index = 1;
+
+	while (g_at_result_iter_next_number(&iter, &value)) {
+
+		if (index == nd->cind_pos[HFP_INDICATOR_SERVICE])
+			nd->cind_val[HFP_INDICATOR_SERVICE] = value;
+
+		if (index == nd->cind_pos[HFP_INDICATOR_ROAM])
+			nd->cind_val[HFP_INDICATOR_ROAM] = value;
+
+		index++;
+	}
+
+	if (nd->cind_val[HFP_INDICATOR_SERVICE])
+		status = NETWORK_REGISTRATION_STATUS_REGISTERED;
+	else
+		status = NETWORK_REGISTRATION_STATUS_NOT_REGISTERED;
+
+	if (nd->cind_val[HFP_INDICATOR_ROAM])
+		status = NETWORK_REGISTRATION_STATUS_ROAMING;
+
+	cb(&error, status, -1, -1, -1, cbd->data);
+}
+
+static void hfp_registration_status(struct ofono_netreg *netreg,
+					ofono_netreg_status_cb_t cb,
+					void *data)
+{
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	gboolean ok;
+
+	if (!cbd)
+		goto error;
+
+	cbd->user = netreg;
+
+	ok = g_at_chat_send(nd->chat, "AT+CIND?", cind_prefix,
+				registration_status_cb, cbd, g_free);
+	if (ok)
+		return;
+
+error:
+	if (cbd)
+		g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, -1, -1, -1, -1, data);
+}
+
+static void hfp_current_operator(struct ofono_netreg *netreg,
+				ofono_netreg_operator_cb_t cb, void *data)
+{
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	gboolean ok;
+
+	if (!cbd)
+		goto error;
+
+	cbd->user = netreg;
+
+	ok = g_at_chat_send(nd->chat, "AT+COPS=3,0", NULL,
+			NULL, cbd, NULL);
+
+	if (ok)
+		ok = g_at_chat_send(nd->chat, "AT+COPS?", cops_prefix,
+				cops_cb, cbd, NULL);
+
+	if (ok)
+		return;
+
+error:
+	if (cbd)
+		g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, NULL, data);
+}
+
+static void hfp_signal_strength(struct ofono_netreg *netreg,
+				ofono_netreg_strength_cb_t cb, void *data)
+{
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+	struct cb_data *cbd = cb_data_new(cb, data);
+
+	if (!cbd)
+		goto error;
+
+	cbd->user = netreg;
+
+	if (g_at_chat_send(nd->chat, "AT+CIND?", cind_prefix,
+			signal_strength_cb, cbd, g_free) > 0)
+		return;
+
+error:
+	if (cbd)
+		g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, -1, data);
+}
+
+static gboolean hfp_netreg_register(gpointer user_data)
+{
+	struct ofono_netreg *netreg = user_data;
+
+	ofono_netreg_register(netreg);
+
+	return FALSE;
+}
+
+static int hfp_netreg_probe(struct ofono_netreg *netreg, unsigned int vendor,
+				void *user_data)
+{
+	struct hfp_data *data = user_data;
+	struct netreg_data *nd;
+
+	nd = g_new0(struct netreg_data, 1);
+	nd->chat = data->chat;
+	memcpy(nd->cind_pos, data->cind_pos, HFP_INDICATOR_LAST);
+	memcpy(nd->cind_val, data->cind_val, HFP_INDICATOR_LAST);
+
+	ofono_netreg_set_data(netreg, nd);
+
+	g_at_chat_register(nd->chat, "+CIEV:", ciev_notify, FALSE,
+			netreg, NULL);
+
+	g_idle_add(hfp_netreg_register, netreg);
+
+	return 0;
+}
+
+static void hfp_netreg_remove(struct ofono_netreg *netreg)
+{
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+
+	g_free(nd);
+}
+
+static struct ofono_netreg_driver driver = {
+	.name				= "hfpmodem",
+	.probe				= hfp_netreg_probe,
+	.remove				= hfp_netreg_remove,
+	.registration_status		= hfp_registration_status,
+	.current_operator		= hfp_current_operator,
+	.strength			= hfp_signal_strength,
+};
+
+void hfp_netreg_init()
+{
+	ofono_netreg_driver_register(&driver);
+}
+
+void hfp_netreg_exit()
+{
+	ofono_netreg_driver_unregister(&driver);
+}
diff --git a/plugins/hfp.c b/plugins/hfp.c
index 5e94a05..be812cd 100644
--- a/plugins/hfp.c
+++ b/plugins/hfp.c
@@ -311,6 +311,7 @@ static void hfp_pre_sim(struct ofono_modem *modem)
 
 	DBG("%p", modem);
 	ofono_voicecall_create(modem, 0, "hfpmodem", data);
+	ofono_netreg_create(modem, 0, "hfpmodem", data);
 }
 
 static void hfp_post_sim(struct ofono_modem *modem)
-- 
1.6.4.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] Create network registration driver for hfpmodem
  2009-11-03 17:46 ` Zhenhua Zhang
@ 2009-11-03 16:53   ` Gustavo F. Padovan
  0 siblings, 0 replies; 9+ messages in thread
From: Gustavo F. Padovan @ 2009-11-03 16:53 UTC (permalink / raw)
  To: ofono

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

Hi Zhenhua,

On Tue, Nov 3, 2009 at 3:46 PM, Zhenhua Zhang <zhenhua.zhang@intel.com> wrote:
> Hi Padovan,
>
> Gustavo F. Padovan wrote:
>> This driver handles phone informations about registration status, signal
>> strength and roaming status listening +CIEV commands.  It also gets the
>> Network Operator name with +COPS commands.
>> ---
>>  Makefile.am                             |    3 +-
>>  drivers/hfpmodem/hfpmodem.c             |    2 +
>>  drivers/hfpmodem/hfpmodem.h             |    3 +
>>  drivers/hfpmodem/network-registration.c |  365 +++++++++++++++++++++++++++++++
>>  plugins/hfp.c                           |    1 +
>>  5 files changed, 373 insertions(+), 1 deletions(-)
>>  create mode 100644 drivers/hfpmodem/network-registration.c
>
> On compiling your code I got:
>
>  CC     drivers/hfpmodem/network-registration.o
> cc1: warnings being treated as errors
> drivers/hfpmodem/network-registration.c: In function ‘cops_cb’:
> drivers/hfpmodem/network-registration.c:101: error: label ‘error’
> defined but not used
> drivers/hfpmodem/network-registration.c:58: error: unused variable ‘nd’
> make[1]: *** [drivers/hfpmodem/network-registration.o] Error 1
> make: *** [all] Error 2

Sorry, I forgot the --enable-maintainer-mode. :(

>
> So I have below patch to remove 'nd' and refine labels in cops_cb.
> Please review it.
>
> I would suggest to replace 'out' label by return. We really don't need
> two labels that is confusing. Atmodem netreg has the same problem.

I agree with you, thanks for the patch and the review.


-- 
Gustavo F. Padovan
ProFUSION embedded systems - http://profusion.mobi

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/1] Create network registration driver for hfpmodem
@ 2009-11-03 17:04 Gustavo F. Padovan
  2009-11-04 17:54 ` Denis Kenzior
  0 siblings, 1 reply; 9+ messages in thread
From: Gustavo F. Padovan @ 2009-11-03 17:04 UTC (permalink / raw)
  To: ofono

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

This driver handles phone informations about registration status, signal
strength and roaming status listening +CIEV commands.  It also gets the
Network Operator name with +COPS commands.
---
 Makefile.am                             |    3 +-
 drivers/hfpmodem/hfpmodem.c             |    2 +
 drivers/hfpmodem/hfpmodem.h             |    3 +
 drivers/hfpmodem/network-registration.c |  365 +++++++++++++++++++++++++++++++
 plugins/hfp.c                           |    1 +
 5 files changed, 373 insertions(+), 1 deletions(-)
 create mode 100644 drivers/hfpmodem/network-registration.c

diff --git a/Makefile.am b/Makefile.am
index 8e56568..c3e06b4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -126,7 +126,8 @@ builtin_modules += hfpmodem
 builtin_sources += drivers/atmodem/atutil.h \
 			drivers/hfpmodem/hfpmodem.h \
 			drivers/hfpmodem/hfpmodem.c \
-			drivers/hfpmodem/voicecall.c
+			drivers/hfpmodem/voicecall.c \
+			drivers/hfpmodem/network-registration.c
 
 builtin_modules += mbmmodem
 builtin_sources += drivers/atmodem/atutil.h \
diff --git a/drivers/hfpmodem/hfpmodem.c b/drivers/hfpmodem/hfpmodem.c
index 03b5ea0..58ae03d 100644
--- a/drivers/hfpmodem/hfpmodem.c
+++ b/drivers/hfpmodem/hfpmodem.c
@@ -42,6 +42,7 @@
 static int hfpmodem_init(void)
 {
 	hfp_voicecall_init();
+	hfp_netreg_init();
 
 	return 0;
 }
@@ -49,6 +50,7 @@ static int hfpmodem_init(void)
 static void hfpmodem_exit(void)
 {
 	hfp_voicecall_exit();
+	hfp_netreg_exit();
 }
 
 OFONO_PLUGIN_DEFINE(hfpmodem, "Hands-Free Profile Driver", VERSION,
diff --git a/drivers/hfpmodem/hfpmodem.h b/drivers/hfpmodem/hfpmodem.h
index c4e2a34..02f5a4b 100644
--- a/drivers/hfpmodem/hfpmodem.h
+++ b/drivers/hfpmodem/hfpmodem.h
@@ -61,6 +61,9 @@ struct hfp_data {
 	unsigned int cind_val[HFP_INDICATOR_LAST];
 };
 
+extern void hfp_netreg_init();
+extern void hfp_netreg_exit();
+
 extern void hfp_voicecall_init();
 extern void hfp_voicecall_exit();
 
diff --git a/drivers/hfpmodem/network-registration.c b/drivers/hfpmodem/network-registration.c
new file mode 100644
index 0000000..6cfaf57
--- /dev/null
+++ b/drivers/hfpmodem/network-registration.c
@@ -0,0 +1,365 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2009  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2009 ProFUSION embedded systems. All rights reserved.
+ *
+ *  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
+ *  published by the Free Software Foundation.
+ *
+ *  This program 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 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <glib.h>
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/netreg.h>
+
+#include "gatchat.h"
+#include "gatresult.h"
+#include "common.h"
+
+#include "hfpmodem.h"
+
+#define HFP_MAX_OPERATOR_NAME_LENGTH 16
+
+static const char *cops_prefix[] = { "+COPS:", NULL };
+static const char *cind_prefix[] = { "+CIND:", NULL };
+
+struct netreg_data {
+	GAtChat *chat;
+	unsigned char cind_pos[HFP_INDICATOR_LAST];
+	int cind_val[HFP_INDICATOR_LAST];
+};
+
+static void cops_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	struct netreg_data *nd = ofono_netreg_get_data(cbd->user);
+	ofono_netreg_operator_cb_t cb = cbd->cb;
+	struct ofono_network_operator op;
+	GAtResultIter iter;
+	int format;
+	const char *name;
+	struct ofono_error error;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, NULL, cbd->data);
+		goto out;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+COPS:"))
+		return;
+
+	g_at_result_iter_skip_next(&iter);
+
+	ok = g_at_result_iter_next_number(&iter, &format);
+
+	if (ok == FALSE || format != 0)
+		return;
+
+	if (g_at_result_iter_next_string(&iter, &name) == FALSE)
+		return;
+
+	strncpy(op.name, name, HFP_MAX_OPERATOR_NAME_LENGTH);
+	op.name[HFP_MAX_OPERATOR_NAME_LENGTH] = '\0';
+
+	op.mcc[0] = '\0';
+	op.mnc[0] = '\0';
+
+	cb(&error, &op, cbd->data);
+
+out:
+	g_free(cbd);
+
+	return;
+
+error:
+	CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+
+	g_free(cbd);
+}
+
+static void ciev_notify(GAtResult *result, gpointer user_data)
+{
+	struct ofono_netreg *netreg = user_data;
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+	GAtResultIter iter;
+	int index, value, status;
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CIEV:"))
+		return;
+
+	if (!g_at_result_iter_next_number(&iter, &index))
+		return;
+
+	if (!g_at_result_iter_next_number(&iter, &value))
+		return;
+
+	if (index == nd->cind_pos[HFP_INDICATOR_SERVICE]) {
+		nd->cind_val[HFP_INDICATOR_SERVICE] = value;
+		if (value)
+			status = NETWORK_REGISTRATION_STATUS_REGISTERED;
+		else
+			status = NETWORK_REGISTRATION_STATUS_NOT_REGISTERED;
+
+		ofono_netreg_status_notify(netreg, status, -1, -1, -1);
+	} else if (index == nd->cind_pos[HFP_INDICATOR_ROAM]) {
+		nd->cind_val[HFP_INDICATOR_ROAM] = value;
+		if (value)
+			status = NETWORK_REGISTRATION_STATUS_ROAMING;
+
+		ofono_netreg_status_notify(netreg, status, -1, -1, -1);
+	} else if (index == nd->cind_pos[HFP_INDICATOR_SIGNAL]) {
+		nd->cind_val[HFP_INDICATOR_SIGNAL] = value;
+		ofono_netreg_strength_notify(netreg, value * 20);
+	}
+
+	return;
+}
+
+static void signal_strength_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_netreg_strength_cb_t cb = cbd->cb;
+	struct netreg_data *nd = ofono_netreg_get_data(cbd->user);
+	GAtResultIter iter;
+	int index, strength;
+	struct ofono_error error;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, -1, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CIND:")) {
+		CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+		return;
+	}
+
+	index = 1;
+
+	while (g_at_result_iter_next_number(&iter, &strength)) {
+		if (index == nd->cind_pos[HFP_INDICATOR_SIGNAL]) {
+			nd->cind_val[HFP_INDICATOR_SIGNAL] = strength;
+			break;
+		}
+
+		index++;
+	}
+
+	ofono_debug("signal_strength_cb: %d", strength);
+
+	cb(&error, strength * 20, cbd->data);
+}
+
+static void registration_status_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_netreg_status_cb_t cb = cbd->cb;
+	struct netreg_data *nd = ofono_netreg_get_data(cbd->user);
+	GAtResultIter iter;
+	int index, value, status;
+	struct ofono_error error;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, -1, -1, -1, -1, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CIND:")) {
+		CALLBACK_WITH_FAILURE(cb, -1, -1, -1, -1, cbd->data);
+		return;
+	}
+
+	index = 1;
+
+	while (g_at_result_iter_next_number(&iter, &value)) {
+
+		if (index == nd->cind_pos[HFP_INDICATOR_SERVICE])
+			nd->cind_val[HFP_INDICATOR_SERVICE] = value;
+
+		if (index == nd->cind_pos[HFP_INDICATOR_ROAM])
+			nd->cind_val[HFP_INDICATOR_ROAM] = value;
+
+		index++;
+	}
+
+	if (nd->cind_val[HFP_INDICATOR_SERVICE])
+		status = NETWORK_REGISTRATION_STATUS_REGISTERED;
+	else
+		status = NETWORK_REGISTRATION_STATUS_NOT_REGISTERED;
+
+	if (nd->cind_val[HFP_INDICATOR_ROAM])
+		status = NETWORK_REGISTRATION_STATUS_ROAMING;
+
+	cb(&error, status, -1, -1, -1, cbd->data);
+}
+
+static void hfp_registration_status(struct ofono_netreg *netreg,
+					ofono_netreg_status_cb_t cb,
+					void *data)
+{
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	gboolean ok;
+
+	if (!cbd)
+		goto error;
+
+	cbd->user = netreg;
+
+	ok = g_at_chat_send(nd->chat, "AT+CIND?", cind_prefix,
+				registration_status_cb, cbd, g_free);
+	if (ok)
+		return;
+
+error:
+	if (cbd)
+		g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, -1, -1, -1, -1, data);
+}
+
+static void hfp_current_operator(struct ofono_netreg *netreg,
+				ofono_netreg_operator_cb_t cb, void *data)
+{
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	gboolean ok;
+
+	if (!cbd)
+		goto error;
+
+	cbd->user = netreg;
+
+	ok = g_at_chat_send(nd->chat, "AT+COPS=3,0", NULL,
+			NULL, cbd, NULL);
+
+	if (ok)
+		ok = g_at_chat_send(nd->chat, "AT+COPS?", cops_prefix,
+				cops_cb, cbd, NULL);
+
+	if (ok)
+		return;
+
+error:
+	if (cbd)
+		g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, NULL, data);
+}
+
+static void hfp_signal_strength(struct ofono_netreg *netreg,
+				ofono_netreg_strength_cb_t cb, void *data)
+{
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+	struct cb_data *cbd = cb_data_new(cb, data);
+
+	if (!cbd)
+		goto error;
+
+	cbd->user = netreg;
+
+	if (g_at_chat_send(nd->chat, "AT+CIND?", cind_prefix,
+			signal_strength_cb, cbd, g_free) > 0)
+		return;
+
+error:
+	if (cbd)
+		g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, -1, data);
+}
+
+static gboolean hfp_netreg_register(gpointer user_data)
+{
+	struct ofono_netreg *netreg = user_data;
+
+	ofono_netreg_register(netreg);
+
+	return FALSE;
+}
+
+static int hfp_netreg_probe(struct ofono_netreg *netreg, unsigned int vendor,
+				void *user_data)
+{
+	struct hfp_data *data = user_data;
+	struct netreg_data *nd;
+
+	nd = g_new0(struct netreg_data, 1);
+	nd->chat = data->chat;
+	memcpy(nd->cind_pos, data->cind_pos, HFP_INDICATOR_LAST);
+	memcpy(nd->cind_val, data->cind_val, HFP_INDICATOR_LAST);
+
+	ofono_netreg_set_data(netreg, nd);
+
+	g_at_chat_register(nd->chat, "+CIEV:", ciev_notify, FALSE,
+			netreg, NULL);
+
+	g_idle_add(hfp_netreg_register, netreg);
+
+	return 0;
+}
+
+static void hfp_netreg_remove(struct ofono_netreg *netreg)
+{
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+
+	g_free(nd);
+}
+
+static struct ofono_netreg_driver driver = {
+	.name				= "hfpmodem",
+	.probe				= hfp_netreg_probe,
+	.remove				= hfp_netreg_remove,
+	.registration_status		= hfp_registration_status,
+	.current_operator		= hfp_current_operator,
+	.strength			= hfp_signal_strength,
+};
+
+void hfp_netreg_init()
+{
+	ofono_netreg_driver_register(&driver);
+}
+
+void hfp_netreg_exit()
+{
+	ofono_netreg_driver_unregister(&driver);
+}
diff --git a/plugins/hfp.c b/plugins/hfp.c
index 5e94a05..be812cd 100644
--- a/plugins/hfp.c
+++ b/plugins/hfp.c
@@ -311,6 +311,7 @@ static void hfp_pre_sim(struct ofono_modem *modem)
 
 	DBG("%p", modem);
 	ofono_voicecall_create(modem, 0, "hfpmodem", data);
+	ofono_netreg_create(modem, 0, "hfpmodem", data);
 }
 
 static void hfp_post_sim(struct ofono_modem *modem)
-- 
1.6.4.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 1/1] Create network registration driver for hfpmodem
@ 2009-11-03 17:44 Gustavo F. Padovan
  0 siblings, 0 replies; 9+ messages in thread
From: Gustavo F. Padovan @ 2009-11-03 17:44 UTC (permalink / raw)
  To: ofono

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

This driver handles phone informations about registration status, signal
strength and roaming status listening +CIEV commands.  It also gets the
Network Operator name with +COPS commands.
---
 Makefile.am                             |    3 +-
 drivers/hfpmodem/hfpmodem.c             |    2 +
 drivers/hfpmodem/hfpmodem.h             |    3 +
 drivers/hfpmodem/network-registration.c |  356 +++++++++++++++++++++++++++++++
 plugins/hfp.c                           |    1 +
 5 files changed, 364 insertions(+), 1 deletions(-)
 create mode 100644 drivers/hfpmodem/network-registration.c

diff --git a/Makefile.am b/Makefile.am
index 8e56568..c3e06b4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -126,7 +126,8 @@ builtin_modules += hfpmodem
 builtin_sources += drivers/atmodem/atutil.h \
 			drivers/hfpmodem/hfpmodem.h \
 			drivers/hfpmodem/hfpmodem.c \
-			drivers/hfpmodem/voicecall.c
+			drivers/hfpmodem/voicecall.c \
+			drivers/hfpmodem/network-registration.c
 
 builtin_modules += mbmmodem
 builtin_sources += drivers/atmodem/atutil.h \
diff --git a/drivers/hfpmodem/hfpmodem.c b/drivers/hfpmodem/hfpmodem.c
index 03b5ea0..58ae03d 100644
--- a/drivers/hfpmodem/hfpmodem.c
+++ b/drivers/hfpmodem/hfpmodem.c
@@ -42,6 +42,7 @@
 static int hfpmodem_init(void)
 {
 	hfp_voicecall_init();
+	hfp_netreg_init();
 
 	return 0;
 }
@@ -49,6 +50,7 @@ static int hfpmodem_init(void)
 static void hfpmodem_exit(void)
 {
 	hfp_voicecall_exit();
+	hfp_netreg_exit();
 }
 
 OFONO_PLUGIN_DEFINE(hfpmodem, "Hands-Free Profile Driver", VERSION,
diff --git a/drivers/hfpmodem/hfpmodem.h b/drivers/hfpmodem/hfpmodem.h
index c4e2a34..02f5a4b 100644
--- a/drivers/hfpmodem/hfpmodem.h
+++ b/drivers/hfpmodem/hfpmodem.h
@@ -61,6 +61,9 @@ struct hfp_data {
 	unsigned int cind_val[HFP_INDICATOR_LAST];
 };
 
+extern void hfp_netreg_init();
+extern void hfp_netreg_exit();
+
 extern void hfp_voicecall_init();
 extern void hfp_voicecall_exit();
 
diff --git a/drivers/hfpmodem/network-registration.c b/drivers/hfpmodem/network-registration.c
new file mode 100644
index 0000000..e163b79
--- /dev/null
+++ b/drivers/hfpmodem/network-registration.c
@@ -0,0 +1,356 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2009  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2009 ProFUSION embedded systems. All rights reserved.
+ *
+ *  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
+ *  published by the Free Software Foundation.
+ *
+ *  This program 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 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <glib.h>
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/netreg.h>
+
+#include "gatchat.h"
+#include "gatresult.h"
+#include "common.h"
+
+#include "hfpmodem.h"
+
+#define HFP_MAX_OPERATOR_NAME_LENGTH 16
+
+static const char *cops_prefix[] = { "+COPS:", NULL };
+static const char *cind_prefix[] = { "+CIND:", NULL };
+
+struct netreg_data {
+	GAtChat *chat;
+	unsigned char cind_pos[HFP_INDICATOR_LAST];
+	int cind_val[HFP_INDICATOR_LAST];
+};
+
+static void cops_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_netreg_operator_cb_t cb = cbd->cb;
+	struct ofono_network_operator op;
+	GAtResultIter iter;
+	int format;
+	const char *name;
+	struct ofono_error error;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, NULL, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+COPS:"))
+		goto error;
+
+	g_at_result_iter_skip_next(&iter);
+
+	ok = g_at_result_iter_next_number(&iter, &format);
+
+	if (ok == FALSE || format != 0)
+		goto error;
+
+	if (g_at_result_iter_next_string(&iter, &name) == FALSE)
+		goto error;
+
+	strncpy(op.name, name, HFP_MAX_OPERATOR_NAME_LENGTH);
+	op.name[HFP_MAX_OPERATOR_NAME_LENGTH] = '\0';
+
+	op.mcc[0] = '\0';
+	op.mnc[0] = '\0';
+
+	cb(&error, &op, cbd->data);
+
+	return;
+
+error:
+	CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+}
+
+static void ciev_notify(GAtResult *result, gpointer user_data)
+{
+	struct ofono_netreg *netreg = user_data;
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+	GAtResultIter iter;
+	int index, value, status;
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CIEV:"))
+		return;
+
+	if (!g_at_result_iter_next_number(&iter, &index))
+		return;
+
+	if (!g_at_result_iter_next_number(&iter, &value))
+		return;
+
+	if (index == nd->cind_pos[HFP_INDICATOR_SERVICE]) {
+		nd->cind_val[HFP_INDICATOR_SERVICE] = value;
+		if (value)
+			status = NETWORK_REGISTRATION_STATUS_REGISTERED;
+		else
+			status = NETWORK_REGISTRATION_STATUS_NOT_REGISTERED;
+
+		ofono_netreg_status_notify(netreg, status, -1, -1, -1);
+	} else if (index == nd->cind_pos[HFP_INDICATOR_ROAM]) {
+		nd->cind_val[HFP_INDICATOR_ROAM] = value;
+		if (value)
+			status = NETWORK_REGISTRATION_STATUS_ROAMING;
+
+		ofono_netreg_status_notify(netreg, status, -1, -1, -1);
+	} else if (index == nd->cind_pos[HFP_INDICATOR_SIGNAL]) {
+		nd->cind_val[HFP_INDICATOR_SIGNAL] = value;
+		ofono_netreg_strength_notify(netreg, value * 20);
+	}
+
+	return;
+}
+
+static void signal_strength_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_netreg_strength_cb_t cb = cbd->cb;
+	struct netreg_data *nd = ofono_netreg_get_data(cbd->user);
+	GAtResultIter iter;
+	int index, strength;
+	struct ofono_error error;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, -1, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CIND:")) {
+		CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+		return;
+	}
+
+	index = 1;
+
+	while (g_at_result_iter_next_number(&iter, &strength)) {
+		if (index == nd->cind_pos[HFP_INDICATOR_SIGNAL]) {
+			nd->cind_val[HFP_INDICATOR_SIGNAL] = strength;
+			break;
+		}
+
+		index++;
+	}
+
+	ofono_debug("signal_strength_cb: %d", strength);
+
+	cb(&error, strength * 20, cbd->data);
+}
+
+static void registration_status_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_netreg_status_cb_t cb = cbd->cb;
+	struct netreg_data *nd = ofono_netreg_get_data(cbd->user);
+	GAtResultIter iter;
+	int index, value, status;
+	struct ofono_error error;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, -1, -1, -1, -1, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CIND:")) {
+		CALLBACK_WITH_FAILURE(cb, -1, -1, -1, -1, cbd->data);
+		return;
+	}
+
+	index = 1;
+
+	while (g_at_result_iter_next_number(&iter, &value)) {
+
+		if (index == nd->cind_pos[HFP_INDICATOR_SERVICE])
+			nd->cind_val[HFP_INDICATOR_SERVICE] = value;
+
+		if (index == nd->cind_pos[HFP_INDICATOR_ROAM])
+			nd->cind_val[HFP_INDICATOR_ROAM] = value;
+
+		index++;
+	}
+
+	if (nd->cind_val[HFP_INDICATOR_SERVICE])
+		status = NETWORK_REGISTRATION_STATUS_REGISTERED;
+	else
+		status = NETWORK_REGISTRATION_STATUS_NOT_REGISTERED;
+
+	if (nd->cind_val[HFP_INDICATOR_ROAM])
+		status = NETWORK_REGISTRATION_STATUS_ROAMING;
+
+	cb(&error, status, -1, -1, -1, cbd->data);
+}
+
+static void hfp_registration_status(struct ofono_netreg *netreg,
+					ofono_netreg_status_cb_t cb,
+					void *data)
+{
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	gboolean ok;
+
+	if (!cbd)
+		goto error;
+
+	cbd->user = netreg;
+
+	ok = g_at_chat_send(nd->chat, "AT+CIND?", cind_prefix,
+				registration_status_cb, cbd, g_free);
+	if (ok)
+		return;
+
+error:
+	if (cbd)
+		g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, -1, -1, -1, -1, data);
+}
+
+static void hfp_current_operator(struct ofono_netreg *netreg,
+				ofono_netreg_operator_cb_t cb, void *data)
+{
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	gboolean ok;
+
+	if (!cbd)
+		goto error;
+
+	cbd->user = netreg;
+
+	ok = g_at_chat_send(nd->chat, "AT+COPS=3,0", NULL,
+			NULL, cbd, NULL);
+
+	if (ok)
+		ok = g_at_chat_send(nd->chat, "AT+COPS?", cops_prefix,
+				cops_cb, cbd, g_free);
+
+	if (ok)
+		return;
+
+error:
+	CALLBACK_WITH_FAILURE(cb, NULL, data);
+}
+
+static void hfp_signal_strength(struct ofono_netreg *netreg,
+				ofono_netreg_strength_cb_t cb, void *data)
+{
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+	struct cb_data *cbd = cb_data_new(cb, data);
+
+	if (!cbd)
+		goto error;
+
+	cbd->user = netreg;
+
+	if (g_at_chat_send(nd->chat, "AT+CIND?", cind_prefix,
+			signal_strength_cb, cbd, g_free) > 0)
+		return;
+
+error:
+	if (cbd)
+		g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, -1, data);
+}
+
+static gboolean hfp_netreg_register(gpointer user_data)
+{
+	struct ofono_netreg *netreg = user_data;
+
+	ofono_netreg_register(netreg);
+
+	return FALSE;
+}
+
+static int hfp_netreg_probe(struct ofono_netreg *netreg, unsigned int vendor,
+				void *user_data)
+{
+	struct hfp_data *data = user_data;
+	struct netreg_data *nd;
+
+	nd = g_new0(struct netreg_data, 1);
+	nd->chat = data->chat;
+	memcpy(nd->cind_pos, data->cind_pos, HFP_INDICATOR_LAST);
+	memcpy(nd->cind_val, data->cind_val, HFP_INDICATOR_LAST);
+
+	ofono_netreg_set_data(netreg, nd);
+
+	g_at_chat_register(nd->chat, "+CIEV:", ciev_notify, FALSE,
+			netreg, NULL);
+
+	g_idle_add(hfp_netreg_register, netreg);
+
+	return 0;
+}
+
+static void hfp_netreg_remove(struct ofono_netreg *netreg)
+{
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+
+	g_free(nd);
+}
+
+static struct ofono_netreg_driver driver = {
+	.name				= "hfpmodem",
+	.probe				= hfp_netreg_probe,
+	.remove				= hfp_netreg_remove,
+	.registration_status		= hfp_registration_status,
+	.current_operator		= hfp_current_operator,
+	.strength			= hfp_signal_strength,
+};
+
+void hfp_netreg_init()
+{
+	ofono_netreg_driver_register(&driver);
+}
+
+void hfp_netreg_exit()
+{
+	ofono_netreg_driver_unregister(&driver);
+}
diff --git a/plugins/hfp.c b/plugins/hfp.c
index 5e94a05..be812cd 100644
--- a/plugins/hfp.c
+++ b/plugins/hfp.c
@@ -311,6 +311,7 @@ static void hfp_pre_sim(struct ofono_modem *modem)
 
 	DBG("%p", modem);
 	ofono_voicecall_create(modem, 0, "hfpmodem", data);
+	ofono_netreg_create(modem, 0, "hfpmodem", data);
 }
 
 static void hfp_post_sim(struct ofono_modem *modem)
-- 
1.6.4.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] Create network registration driver for hfpmodem
       [not found] <0463F45F3606F4428ED35AC8C709F92E089B9CBAB7@pdsmsx502.ccr.corp.intel.com>
@ 2009-11-03 17:46 ` Zhenhua Zhang
  2009-11-03 16:53   ` Gustavo F. Padovan
  0 siblings, 1 reply; 9+ messages in thread
From: Zhenhua Zhang @ 2009-11-03 17:46 UTC (permalink / raw)
  To: ofono

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

Hi Padovan,

Gustavo F. Padovan wrote:
> This driver handles phone informations about registration status, signal
> strength and roaming status listening +CIEV commands.  It also gets the
> Network Operator name with +COPS commands.
> ---
>  Makefile.am                             |    3 +-
>  drivers/hfpmodem/hfpmodem.c             |    2 +
>  drivers/hfpmodem/hfpmodem.h             |    3 +
>  drivers/hfpmodem/network-registration.c |  365 +++++++++++++++++++++++++++++++
>  plugins/hfp.c                           |    1 +
>  5 files changed, 373 insertions(+), 1 deletions(-)
>  create mode 100644 drivers/hfpmodem/network-registration.c

On compiling your code I got:

  CC     drivers/hfpmodem/network-registration.o
cc1: warnings being treated as errors
drivers/hfpmodem/network-registration.c: In function ‘cops_cb’:
drivers/hfpmodem/network-registration.c:101: error: label ‘error’
defined but not used
drivers/hfpmodem/network-registration.c:58: error: unused variable ‘nd’
make[1]: *** [drivers/hfpmodem/network-registration.o] Error 1
make: *** [all] Error 2

So I have below patch to remove 'nd' and refine labels in cops_cb.
Please review it.

I would suggest to replace 'out' label by return. We really don't need
two labels that is confusing. Atmodem netreg has the same problem.

---
 drivers/hfpmodem/network-registration.c |   19 +++++--------------
 1 files changed, 5 insertions(+), 14 deletions(-)

diff --git a/drivers/hfpmodem/network-registration.c
b/drivers/hfpmodem/network-registration.c
index 6cfaf57..e163b79 100644
--- a/drivers/hfpmodem/network-registration.c
+++ b/drivers/hfpmodem/network-registration.c
@@ -55,7 +55,6 @@ struct netreg_data {
 static void cops_cb(gboolean ok, GAtResult *result, gpointer user_data)
 {
 	struct cb_data *cbd = user_data;
-	struct netreg_data *nd = ofono_netreg_get_data(cbd->user);
 	ofono_netreg_operator_cb_t cb = cbd->cb;
 	struct ofono_network_operator op;
 	GAtResultIter iter;
@@ -67,23 +66,23 @@ static void cops_cb(gboolean ok, GAtResult *result,
gpointer user_data)
 
 	if (!ok) {
 		cb(&error, NULL, cbd->data);
-		goto out;
+		return;
 	}
 
 	g_at_result_iter_init(&iter, result);
 
 	if (!g_at_result_iter_next(&iter, "+COPS:"))
-		return;
+		goto error;
 
 	g_at_result_iter_skip_next(&iter);
 
 	ok = g_at_result_iter_next_number(&iter, &format);
 
 	if (ok == FALSE || format != 0)
-		return;
+		goto error;
 
 	if (g_at_result_iter_next_string(&iter, &name) == FALSE)
-		return;
+		goto error;
 
 	strncpy(op.name, name, HFP_MAX_OPERATOR_NAME_LENGTH);
 	op.name[HFP_MAX_OPERATOR_NAME_LENGTH] = '\0';
@@ -93,15 +92,10 @@ static void cops_cb(gboolean ok, GAtResult *result,
gpointer user_data)
 
 	cb(&error, &op, cbd->data);
 
-out:
-	g_free(cbd);
-
 	return;
 
 error:
 	CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
-
-	g_free(cbd);
 }
 
 static void ciev_notify(GAtResult *result, gpointer user_data)
@@ -274,15 +268,12 @@ static void hfp_current_operator(struct
ofono_netreg *netreg,
 
 	if (ok)
 		ok = g_at_chat_send(nd->chat, "AT+COPS?", cops_prefix,
-				cops_cb, cbd, NULL);
+				cops_cb, cbd, g_free);
 
 	if (ok)
 		return;
 
 error:
-	if (cbd)
-		g_free(cbd);
-
 	CALLBACK_WITH_FAILURE(cb, NULL, data);
 }
 
-- 
1.6.2.5



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] Create network registration driver for hfpmodem
  2009-11-03 17:04 [PATCH 1/1] Create network registration driver for hfpmodem Gustavo F. Padovan
@ 2009-11-04 17:54 ` Denis Kenzior
  0 siblings, 0 replies; 9+ messages in thread
From: Denis Kenzior @ 2009-11-04 17:54 UTC (permalink / raw)
  To: ofono

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

Hi Gustavo,

> This driver handles phone informations about registration status, signal
> strength and roaming status listening +CIEV commands.  It also gets the
> Network Operator name with +COPS commands.

This patch has been applied.  I just had to do some _very_ minor cleanups of 
style.

Unfortunately I cannot test the hfp registered -> roaming and roaming -> 
registered scenarios.  So if someone could confirm that this works I'd 
appreciate it

Regards,
-Denis

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2009-11-04 17:54 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-11-03 17:04 [PATCH 1/1] Create network registration driver for hfpmodem Gustavo F. Padovan
2009-11-04 17:54 ` Denis Kenzior
     [not found] <0463F45F3606F4428ED35AC8C709F92E089B9CBAB7@pdsmsx502.ccr.corp.intel.com>
2009-11-03 17:46 ` Zhenhua Zhang
2009-11-03 16:53   ` Gustavo F. Padovan
  -- strict thread matches above, loose matches on Subject: below --
2009-11-03 17:44 Gustavo F. Padovan
2009-10-30 22:55 Gustavo F. Padovan
2009-10-23 21:36 [PATCH 0/1] netreg driver for HFP Gustavo F. Padovan
2009-10-23 21:36 ` [PATCH 1/1] Create network registration driver for hfpmodem Gustavo F. Padovan
2009-10-26  9:01   ` Naveen Verma
2009-10-26 14:27     ` Gustavo F. Padovan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.