All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Add support of Huawei EM770 modem
@ 2010-02-10 10:17 Gu, Yang
  2010-02-10 17:03 ` Andrzej Zaborowski
  2010-02-10 22:37 ` Denis Kenzior
  0 siblings, 2 replies; 11+ messages in thread
From: Gu, Yang @ 2010-02-10 10:17 UTC (permalink / raw)
  To: ofono

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

Hi,
This patch is to enable Huawei EM770 modem, which is a full feature modem that supports voicecall, phonebook, call forwarding, call barring, etc.

There are two known parts of code that may have problem and need your comments.
1. Once connecting this modem to PC via USB, we can get 5 tty ports: ttyUSB0, ttyUSB1, ttyUSB2, ttyUSB3 and ttyUSB4. The correct way to talk to this modem is using ttyUSB2. I'm not sure if I handled this correctly in file udev.c.
2. When creating the modem, a global modem id will be appended to the name of it while constructing the path. This modem has name "huawei_em770", thus the path becomes things like "/huawei_em7700" or "/huawei_em7701". This looks strange. Need I change the name of this modem, or can we use some smarter way to append the modem id? 

There is also one known issue for this modem: The return of "CSMS=?" from this modem is not compatible with spec. This is deemed as a modem issue, so the sms wouldn't work before this hardware issue get solved. 

Comments are welcome!

Regards,
-Yang


[-- Attachment #2: 0001-Add-support-of-Huawei-EM770-modem.patch --]
[-- Type: application/octet-stream, Size: 8637 bytes --]

From 319a05c2fd93b627f965a6848542805f47037c76 Mon Sep 17 00:00:00 2001
From: Yang Gu <yang.gu@intel.com>
Date: Wed, 10 Feb 2010 17:51:04 +0800
Subject: [PATCH] Add support of Huawei EM770 modem

Comparing with general Huawei modem, EM770 is a full feature modem that
supports voicecall, phonebook, call forwarding, call barring, etc.
---
 Makefile.am            |    3 +
 plugins/huawei-em770.c |  226 ++++++++++++++++++++++++++++++++++++++++++++++++
 plugins/ofono.rules    |    1 +
 plugins/udev.c         |   23 +++++
 4 files changed, 253 insertions(+), 0 deletions(-)
 create mode 100644 plugins/huawei-em770.c

diff --git a/Makefile.am b/Makefile.am
index 5e5bb56..df539f3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -195,6 +195,9 @@ builtin_sources += plugins/hso.c
 builtin_modules += huawei
 builtin_sources += plugins/huawei.c
 
+builtin_modules += huawei_em770
+builtin_sources += plugins/huawei-em770.c
+
 builtin_modules += novatel
 builtin_sources += plugins/novatel.c
 
diff --git a/plugins/huawei-em770.c b/plugins/huawei-em770.c
new file mode 100644
index 0000000..0ce4aff
--- /dev/null
+++ b/plugins/huawei-em770.c
@@ -0,0 +1,226 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2010  Intel Corporation. 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
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <gatchat.h>
+#include <gattty.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/call-barring.h>
+#include <ofono/call-forwarding.h>
+#include <ofono/call-meter.h>
+#include <ofono/call-settings.h>
+#include <ofono/devinfo.h>
+#include <ofono/message-waiting.h>
+#include <ofono/netreg.h>
+#include <ofono/phonebook.h>
+#include <ofono/sim.h>
+#include <ofono/sms.h>
+#include <ofono/ssn.h>
+#include <ofono/ussd.h>
+#include <ofono/gprs.h>
+#include <ofono/voicecall.h>
+
+#include <drivers/atmodem/vendor.h>
+
+struct em770_data {
+	GAtChat *chat;
+};
+
+static int em770_probe(struct ofono_modem *modem)
+{
+	struct em770_data *data;
+
+	DBG("%p", modem);
+
+	data = g_try_new0(struct em770_data, 1);
+	if (!data)
+		return -ENOMEM;
+
+	ofono_modem_set_data(modem, data);
+
+	return 0;
+}
+
+static void em770_remove(struct ofono_modem *modem)
+{
+	struct em770_data *data = ofono_modem_get_data(modem);
+
+	DBG("%p", modem);
+
+	ofono_modem_set_data(modem, NULL);
+
+	g_at_chat_unref(data->chat);
+	g_free(data);
+}
+
+static void em770_debug(const char *str, void *user_data)
+{
+	ofono_info("%s", str);
+}
+
+static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+
+	DBG("");
+
+	if (ok)
+		ofono_modem_set_powered(modem, TRUE);
+}
+
+static int em770_enable(struct ofono_modem *modem)
+{
+	struct em770_data *data = ofono_modem_get_data(modem);
+	GAtSyntax *syntax;
+	GIOChannel *channel;
+	const char *device;
+
+	DBG("%p", modem);
+
+	device = ofono_modem_get_string(modem, "Device");
+	if (!device)
+			return -EINVAL;
+
+	channel = g_at_tty_open(device, NULL);
+	if (!channel)
+		return -EIO;
+
+	syntax = g_at_syntax_new_gsmv1();
+	data->chat = g_at_chat_new(channel, syntax);
+	g_at_syntax_unref(syntax);
+	g_io_channel_unref(channel);
+
+	if (!data->chat)
+		return -EIO;
+
+	g_at_chat_add_terminator(data->chat, "COMMAND NOT SUPPORT", -1, FALSE);
+	g_at_chat_add_terminator(data->chat, "TOO MANY PARAMETERS", -1, FALSE);
+
+	if (getenv("OFONO_AT_DEBUG"))
+		g_at_chat_set_debug(data->chat, em770_debug, NULL);
+
+	g_at_chat_send(data->chat, "ATE0", NULL, NULL, NULL, NULL);
+
+	g_at_chat_send(data->chat, "AT+CFUN=1", NULL,
+					cfun_enable, modem, NULL);
+
+	return 0;
+}
+
+static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+	struct em770_data *data = ofono_modem_get_data(modem);
+
+	DBG("");
+
+	g_at_chat_shutdown(data->chat);
+	g_at_chat_unref(data->chat);
+	data->chat = NULL;
+
+	if (ok)
+		ofono_modem_set_powered(modem, FALSE);
+}
+
+static int em770_disable(struct ofono_modem *modem)
+{
+	struct em770_data *data = ofono_modem_get_data(modem);
+
+	DBG("%p", modem);
+
+	if (!data->chat)
+		return 0;
+
+	g_at_chat_cancel_all(data->chat);
+	g_at_chat_unregister_all(data->chat);
+	g_at_chat_send(data->chat, "AT+CFUN=0", NULL,
+					cfun_disable, modem, NULL);
+
+	return -EINPROGRESS;
+}
+
+static void em770_pre_sim(struct ofono_modem *modem)
+{
+	struct em770_data *data = ofono_modem_get_data(modem);
+
+	DBG("%p", modem);
+
+	ofono_devinfo_create(modem, 0, "atmodem", data->chat);
+	ofono_sim_create(modem, 0, "atmodem", data->chat);
+	ofono_voicecall_create(modem, 0, "atmodem", data->chat);
+}
+
+static void em770_post_sim(struct ofono_modem *modem)
+{
+	struct em770_data *data = ofono_modem_get_data(modem);
+	struct ofono_message_waiting *mw;
+
+	DBG("%p", modem);
+
+	ofono_ussd_create(modem, 0, "atmodem", data->chat);
+	ofono_call_forwarding_create(modem, 0, "atmodem", data->chat);
+	ofono_call_settings_create(modem, 0, "atmodem", data->chat);
+	ofono_netreg_create(modem, 0, "atmodem", data->chat);
+	ofono_call_meter_create(modem, 0, "atmodem", data->chat);
+	ofono_call_barring_create(modem, 0, "atmodem", data->chat);
+	ofono_ssn_create(modem, 0, "atmodem", data->chat);
+	ofono_sms_create(modem, OFONO_VENDOR_QUALCOMM_MSM, "atmodem", data->chat);
+	ofono_phonebook_create(modem, 0, "atmodem", data->chat);
+
+	mw = ofono_message_waiting_create(modem);
+	if (mw)
+		ofono_message_waiting_register(mw);
+}
+
+static struct ofono_modem_driver em770_driver = {
+	.name		= "huawei_em770",
+	.probe		= em770_probe,
+	.remove		= em770_remove,
+	.enable		= em770_enable,
+	.disable	= em770_disable,
+	.pre_sim	= em770_pre_sim,
+	.post_sim	= em770_post_sim,
+};
+
+static int em770_init(void)
+{
+	return ofono_modem_driver_register(&em770_driver);
+}
+
+static void em770_exit(void)
+{
+	ofono_modem_driver_unregister(&em770_driver);
+}
+
+OFONO_PLUGIN_DEFINE(huawei_em770, "HUAWEI EM770 modem driver", VERSION,
+		OFONO_PLUGIN_PRIORITY_DEFAULT, em770_init, em770_exit)
diff --git a/plugins/ofono.rules b/plugins/ofono.rules
index 3db0cf4..eeaa3c5 100644
--- a/plugins/ofono.rules
+++ b/plugins/ofono.rules
@@ -6,6 +6,7 @@ ENV{DEVTYPE}!="usb_device", GOTO="ofono_end"
 
 # HUAWEI Technology
 ATTRS{idVendor}=="12d1", ENV{OFONO_DRIVER}="huawei"
+ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1404", ENV{OFONO_DRIVER}="huawei_em770"
 
 # Novatel Wireless
 ATTRS{idVendor}=="1410", ENV{OFONO_DRIVER}="novatel"
diff --git a/plugins/udev.c b/plugins/udev.c
index 455bef3..29cf818 100644
--- a/plugins/udev.c
+++ b/plugins/udev.c
@@ -28,6 +28,7 @@
 #include <libudev.h>
 
 #include <glib.h>
+#include <string.h>
 
 #define OFONO_API_SUBJECT_TO_CHANGE
 #include <ofono/plugin.h>
@@ -208,6 +209,26 @@ static void add_huawei(struct ofono_modem *modem,
 	ofono_modem_register(modem);
 }
 
+static void add_huawei_em770(struct ofono_modem *modem,
+					struct udev_device *udev_device)
+{
+	const char *devnode, *name;
+	int registered;
+
+	registered = ofono_modem_get_integer(modem, "Registered");
+	if (registered != 0)
+		return;
+
+	name = udev_device_get_sysname(udev_device);
+	if (!strcmp(name, "ttyUSB2")) {
+		devnode = udev_device_get_devnode(udev_device);
+		ofono_modem_set_string(modem, "Device", devnode);
+
+		ofono_modem_set_integer(modem, "Registered", 1);
+		ofono_modem_register(modem);
+	}
+}
+
 static void add_novatel(struct ofono_modem *modem,
 					struct udev_device *udev_device)
 {
@@ -271,6 +292,8 @@ static void add_modem(struct udev_device *udev_device)
 		add_hso(modem, udev_device);
 	else if (g_strcmp0(driver, "huawei") == 0)
 		add_huawei(modem, udev_device);
+	else if (g_strcmp0(driver, "huawei_em770") == 0)
+		add_huawei_em770(modem, udev_device);
 	else if (g_strcmp0(driver, "novatel") == 0)
 		add_novatel(modem, udev_device);
 }
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 11+ messages in thread
* [PATCH] Add support of Huawei EM770 modem
@ 2010-03-16  6:37 Yang Gu
  2010-03-16  6:45 ` Marcel Holtmann
  0 siblings, 1 reply; 11+ messages in thread
From: Yang Gu @ 2010-03-16  6:37 UTC (permalink / raw)
  To: ofono

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

Comparing with general Huawei modem, EM770 is a full feature modem that
supports voicecall, phonebook, call forwarding, call barring, etc.
---
 Makefile.am            |    3 +
 plugins/huawei-em770.c |  226 ++++++++++++++++++++++++++++++++++++++++++++++++
 plugins/ofono.rules    |    1 +
 plugins/udev.c         |   27 ++++++
 4 files changed, 257 insertions(+), 0 deletions(-)
 create mode 100644 plugins/huawei-em770.c

diff --git a/Makefile.am b/Makefile.am
index 93d4f67..ee3e9e0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -195,6 +195,9 @@ builtin_sources += plugins/hso.c
 builtin_modules += huawei
 builtin_sources += plugins/huawei.c
 
+builtin_modules += huawei_em770
+builtin_sources += plugins/huawei-em770.c
+
 builtin_modules += novatel
 builtin_sources += plugins/novatel.c
 
diff --git a/plugins/huawei-em770.c b/plugins/huawei-em770.c
new file mode 100644
index 0000000..0ce4aff
--- /dev/null
+++ b/plugins/huawei-em770.c
@@ -0,0 +1,226 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2010  Intel Corporation. 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
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <gatchat.h>
+#include <gattty.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/call-barring.h>
+#include <ofono/call-forwarding.h>
+#include <ofono/call-meter.h>
+#include <ofono/call-settings.h>
+#include <ofono/devinfo.h>
+#include <ofono/message-waiting.h>
+#include <ofono/netreg.h>
+#include <ofono/phonebook.h>
+#include <ofono/sim.h>
+#include <ofono/sms.h>
+#include <ofono/ssn.h>
+#include <ofono/ussd.h>
+#include <ofono/gprs.h>
+#include <ofono/voicecall.h>
+
+#include <drivers/atmodem/vendor.h>
+
+struct em770_data {
+	GAtChat *chat;
+};
+
+static int em770_probe(struct ofono_modem *modem)
+{
+	struct em770_data *data;
+
+	DBG("%p", modem);
+
+	data = g_try_new0(struct em770_data, 1);
+	if (!data)
+		return -ENOMEM;
+
+	ofono_modem_set_data(modem, data);
+
+	return 0;
+}
+
+static void em770_remove(struct ofono_modem *modem)
+{
+	struct em770_data *data = ofono_modem_get_data(modem);
+
+	DBG("%p", modem);
+
+	ofono_modem_set_data(modem, NULL);
+
+	g_at_chat_unref(data->chat);
+	g_free(data);
+}
+
+static void em770_debug(const char *str, void *user_data)
+{
+	ofono_info("%s", str);
+}
+
+static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+
+	DBG("");
+
+	if (ok)
+		ofono_modem_set_powered(modem, TRUE);
+}
+
+static int em770_enable(struct ofono_modem *modem)
+{
+	struct em770_data *data = ofono_modem_get_data(modem);
+	GAtSyntax *syntax;
+	GIOChannel *channel;
+	const char *device;
+
+	DBG("%p", modem);
+
+	device = ofono_modem_get_string(modem, "Device");
+	if (!device)
+			return -EINVAL;
+
+	channel = g_at_tty_open(device, NULL);
+	if (!channel)
+		return -EIO;
+
+	syntax = g_at_syntax_new_gsmv1();
+	data->chat = g_at_chat_new(channel, syntax);
+	g_at_syntax_unref(syntax);
+	g_io_channel_unref(channel);
+
+	if (!data->chat)
+		return -EIO;
+
+	g_at_chat_add_terminator(data->chat, "COMMAND NOT SUPPORT", -1, FALSE);
+	g_at_chat_add_terminator(data->chat, "TOO MANY PARAMETERS", -1, FALSE);
+
+	if (getenv("OFONO_AT_DEBUG"))
+		g_at_chat_set_debug(data->chat, em770_debug, NULL);
+
+	g_at_chat_send(data->chat, "ATE0", NULL, NULL, NULL, NULL);
+
+	g_at_chat_send(data->chat, "AT+CFUN=1", NULL,
+					cfun_enable, modem, NULL);
+
+	return 0;
+}
+
+static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+	struct em770_data *data = ofono_modem_get_data(modem);
+
+	DBG("");
+
+	g_at_chat_shutdown(data->chat);
+	g_at_chat_unref(data->chat);
+	data->chat = NULL;
+
+	if (ok)
+		ofono_modem_set_powered(modem, FALSE);
+}
+
+static int em770_disable(struct ofono_modem *modem)
+{
+	struct em770_data *data = ofono_modem_get_data(modem);
+
+	DBG("%p", modem);
+
+	if (!data->chat)
+		return 0;
+
+	g_at_chat_cancel_all(data->chat);
+	g_at_chat_unregister_all(data->chat);
+	g_at_chat_send(data->chat, "AT+CFUN=0", NULL,
+					cfun_disable, modem, NULL);
+
+	return -EINPROGRESS;
+}
+
+static void em770_pre_sim(struct ofono_modem *modem)
+{
+	struct em770_data *data = ofono_modem_get_data(modem);
+
+	DBG("%p", modem);
+
+	ofono_devinfo_create(modem, 0, "atmodem", data->chat);
+	ofono_sim_create(modem, 0, "atmodem", data->chat);
+	ofono_voicecall_create(modem, 0, "atmodem", data->chat);
+}
+
+static void em770_post_sim(struct ofono_modem *modem)
+{
+	struct em770_data *data = ofono_modem_get_data(modem);
+	struct ofono_message_waiting *mw;
+
+	DBG("%p", modem);
+
+	ofono_ussd_create(modem, 0, "atmodem", data->chat);
+	ofono_call_forwarding_create(modem, 0, "atmodem", data->chat);
+	ofono_call_settings_create(modem, 0, "atmodem", data->chat);
+	ofono_netreg_create(modem, 0, "atmodem", data->chat);
+	ofono_call_meter_create(modem, 0, "atmodem", data->chat);
+	ofono_call_barring_create(modem, 0, "atmodem", data->chat);
+	ofono_ssn_create(modem, 0, "atmodem", data->chat);
+	ofono_sms_create(modem, OFONO_VENDOR_QUALCOMM_MSM, "atmodem", data->chat);
+	ofono_phonebook_create(modem, 0, "atmodem", data->chat);
+
+	mw = ofono_message_waiting_create(modem);
+	if (mw)
+		ofono_message_waiting_register(mw);
+}
+
+static struct ofono_modem_driver em770_driver = {
+	.name		= "huawei_em770",
+	.probe		= em770_probe,
+	.remove		= em770_remove,
+	.enable		= em770_enable,
+	.disable	= em770_disable,
+	.pre_sim	= em770_pre_sim,
+	.post_sim	= em770_post_sim,
+};
+
+static int em770_init(void)
+{
+	return ofono_modem_driver_register(&em770_driver);
+}
+
+static void em770_exit(void)
+{
+	ofono_modem_driver_unregister(&em770_driver);
+}
+
+OFONO_PLUGIN_DEFINE(huawei_em770, "HUAWEI EM770 modem driver", VERSION,
+		OFONO_PLUGIN_PRIORITY_DEFAULT, em770_init, em770_exit)
diff --git a/plugins/ofono.rules b/plugins/ofono.rules
index 3db0cf4..eeaa3c5 100644
--- a/plugins/ofono.rules
+++ b/plugins/ofono.rules
@@ -6,6 +6,7 @@ ENV{DEVTYPE}!="usb_device", GOTO="ofono_end"
 
 # HUAWEI Technology
 ATTRS{idVendor}=="12d1", ENV{OFONO_DRIVER}="huawei"
+ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1404", ENV{OFONO_DRIVER}="huawei_em770"
 
 # Novatel Wireless
 ATTRS{idVendor}=="1410", ENV{OFONO_DRIVER}="novatel"
diff --git a/plugins/udev.c b/plugins/udev.c
index 455bef3..93a4c92 100644
--- a/plugins/udev.c
+++ b/plugins/udev.c
@@ -28,6 +28,7 @@
 #include <libudev.h>
 
 #include <glib.h>
+#include <string.h>
 
 #define OFONO_API_SUBJECT_TO_CHANGE
 #include <ofono/plugin.h>
@@ -208,6 +209,30 @@ static void add_huawei(struct ofono_modem *modem,
 	ofono_modem_register(modem);
 }
 
+static void add_huawei_em770(struct ofono_modem *modem,
+					struct udev_device *udev_device)
+{
+	const char *devnode, *intf_number;
+	int registered;
+	struct udev_device *parent;
+
+	registered = ofono_modem_get_integer(modem, "Registered");
+	if (registered != 0)
+		return;
+
+	parent = udev_device_get_parent(udev_device);
+	parent = udev_device_get_parent(parent);
+	intf_number = udev_device_get_sysattr_value(parent, "bInterfaceNumber");
+
+	if (!strcmp(intf_number, "02")) {
+		devnode = udev_device_get_devnode(udev_device);
+		ofono_modem_set_string(modem, "Device", devnode);
+
+		ofono_modem_set_integer(modem, "Registered", 1);
+		ofono_modem_register(modem);
+	}
+}
+
 static void add_novatel(struct ofono_modem *modem,
 					struct udev_device *udev_device)
 {
@@ -271,6 +296,8 @@ static void add_modem(struct udev_device *udev_device)
 		add_hso(modem, udev_device);
 	else if (g_strcmp0(driver, "huawei") == 0)
 		add_huawei(modem, udev_device);
+	else if (g_strcmp0(driver, "huawei_em770") == 0)
+		add_huawei_em770(modem, udev_device);
 	else if (g_strcmp0(driver, "novatel") == 0)
 		add_novatel(modem, udev_device);
 }
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 11+ messages in thread
* [PATCH] Add support of Huawei EM770 modem
@ 2010-03-16  7:42 Yang Gu
  2010-03-16  8:34 ` Marcel Holtmann
  0 siblings, 1 reply; 11+ messages in thread
From: Yang Gu @ 2010-03-16  7:42 UTC (permalink / raw)
  To: ofono

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

Comparing with general Huawei modem, EM770 is a full feature modem that
supports voicecall, phonebook, call forwarding, call barring, etc.
---
 Makefile.am         |    3 +
 plugins/em770.c     |  226 +++++++++++++++++++++++++++++++++++++++++++++++++++
 plugins/ofono.rules |    1 +
 plugins/udev.c      |   27 ++++++
 4 files changed, 257 insertions(+), 0 deletions(-)
 create mode 100644 plugins/em770.c

diff --git a/Makefile.am b/Makefile.am
index 93d4f67..eca8eee 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -195,6 +195,9 @@ builtin_sources += plugins/hso.c
 builtin_modules += huawei
 builtin_sources += plugins/huawei.c
 
+builtin_modules += em770
+builtin_sources += plugins/em770.c
+
 builtin_modules += novatel
 builtin_sources += plugins/novatel.c
 
diff --git a/plugins/em770.c b/plugins/em770.c
new file mode 100644
index 0000000..a5d87f7
--- /dev/null
+++ b/plugins/em770.c
@@ -0,0 +1,226 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2010  Intel Corporation. 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
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <gatchat.h>
+#include <gattty.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/call-barring.h>
+#include <ofono/call-forwarding.h>
+#include <ofono/call-meter.h>
+#include <ofono/call-settings.h>
+#include <ofono/devinfo.h>
+#include <ofono/message-waiting.h>
+#include <ofono/netreg.h>
+#include <ofono/phonebook.h>
+#include <ofono/sim.h>
+#include <ofono/sms.h>
+#include <ofono/ssn.h>
+#include <ofono/ussd.h>
+#include <ofono/gprs.h>
+#include <ofono/voicecall.h>
+
+#include <drivers/atmodem/vendor.h>
+
+struct em770_data {
+	GAtChat *chat;
+};
+
+static int em770_probe(struct ofono_modem *modem)
+{
+	struct em770_data *data;
+
+	DBG("%p", modem);
+
+	data = g_try_new0(struct em770_data, 1);
+	if (!data)
+		return -ENOMEM;
+
+	ofono_modem_set_data(modem, data);
+
+	return 0;
+}
+
+static void em770_remove(struct ofono_modem *modem)
+{
+	struct em770_data *data = ofono_modem_get_data(modem);
+
+	DBG("%p", modem);
+
+	ofono_modem_set_data(modem, NULL);
+
+	g_at_chat_unref(data->chat);
+	g_free(data);
+}
+
+static void em770_debug(const char *str, void *user_data)
+{
+	ofono_info("%s", str);
+}
+
+static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+
+	DBG("");
+
+	if (ok)
+		ofono_modem_set_powered(modem, TRUE);
+}
+
+static int em770_enable(struct ofono_modem *modem)
+{
+	struct em770_data *data = ofono_modem_get_data(modem);
+	GAtSyntax *syntax;
+	GIOChannel *channel;
+	const char *device;
+
+	DBG("%p", modem);
+
+	device = ofono_modem_get_string(modem, "Device");
+	if (!device)
+			return -EINVAL;
+
+	channel = g_at_tty_open(device, NULL);
+	if (!channel)
+		return -EIO;
+
+	syntax = g_at_syntax_new_gsmv1();
+	data->chat = g_at_chat_new(channel, syntax);
+	g_at_syntax_unref(syntax);
+	g_io_channel_unref(channel);
+
+	if (!data->chat)
+		return -EIO;
+
+	g_at_chat_add_terminator(data->chat, "COMMAND NOT SUPPORT", -1, FALSE);
+	g_at_chat_add_terminator(data->chat, "TOO MANY PARAMETERS", -1, FALSE);
+
+	if (getenv("OFONO_AT_DEBUG"))
+		g_at_chat_set_debug(data->chat, em770_debug, NULL);
+
+	g_at_chat_send(data->chat, "ATE0", NULL, NULL, NULL, NULL);
+
+	g_at_chat_send(data->chat, "AT+CFUN=1", NULL,
+					cfun_enable, modem, NULL);
+
+	return 0;
+}
+
+static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+	struct em770_data *data = ofono_modem_get_data(modem);
+
+	DBG("");
+
+	g_at_chat_shutdown(data->chat);
+	g_at_chat_unref(data->chat);
+	data->chat = NULL;
+
+	if (ok)
+		ofono_modem_set_powered(modem, FALSE);
+}
+
+static int em770_disable(struct ofono_modem *modem)
+{
+	struct em770_data *data = ofono_modem_get_data(modem);
+
+	DBG("%p", modem);
+
+	if (!data->chat)
+		return 0;
+
+	g_at_chat_cancel_all(data->chat);
+	g_at_chat_unregister_all(data->chat);
+	g_at_chat_send(data->chat, "AT+CFUN=0", NULL,
+					cfun_disable, modem, NULL);
+
+	return -EINPROGRESS;
+}
+
+static void em770_pre_sim(struct ofono_modem *modem)
+{
+	struct em770_data *data = ofono_modem_get_data(modem);
+
+	DBG("%p", modem);
+
+	ofono_devinfo_create(modem, 0, "atmodem", data->chat);
+	ofono_sim_create(modem, 0, "atmodem", data->chat);
+	ofono_voicecall_create(modem, 0, "atmodem", data->chat);
+}
+
+static void em770_post_sim(struct ofono_modem *modem)
+{
+	struct em770_data *data = ofono_modem_get_data(modem);
+	struct ofono_message_waiting *mw;
+
+	DBG("%p", modem);
+
+	ofono_ussd_create(modem, 0, "atmodem", data->chat);
+	ofono_call_forwarding_create(modem, 0, "atmodem", data->chat);
+	ofono_call_settings_create(modem, 0, "atmodem", data->chat);
+	ofono_netreg_create(modem, 0, "atmodem", data->chat);
+	ofono_call_meter_create(modem, 0, "atmodem", data->chat);
+	ofono_call_barring_create(modem, 0, "atmodem", data->chat);
+	ofono_ssn_create(modem, 0, "atmodem", data->chat);
+	ofono_sms_create(modem, OFONO_VENDOR_QUALCOMM_MSM, "atmodem", data->chat);
+	ofono_phonebook_create(modem, 0, "atmodem", data->chat);
+
+	mw = ofono_message_waiting_create(modem);
+	if (mw)
+		ofono_message_waiting_register(mw);
+}
+
+static struct ofono_modem_driver em770_driver = {
+	.name		= "em770",
+	.probe		= em770_probe,
+	.remove		= em770_remove,
+	.enable		= em770_enable,
+	.disable	= em770_disable,
+	.pre_sim	= em770_pre_sim,
+	.post_sim	= em770_post_sim,
+};
+
+static int em770_init(void)
+{
+	return ofono_modem_driver_register(&em770_driver);
+}
+
+static void em770_exit(void)
+{
+	ofono_modem_driver_unregister(&em770_driver);
+}
+
+OFONO_PLUGIN_DEFINE(em770, "HUAWEI EM770 modem driver", VERSION,
+		OFONO_PLUGIN_PRIORITY_DEFAULT, em770_init, em770_exit)
diff --git a/plugins/ofono.rules b/plugins/ofono.rules
index 3db0cf4..a6202f9 100644
--- a/plugins/ofono.rules
+++ b/plugins/ofono.rules
@@ -6,6 +6,7 @@ ENV{DEVTYPE}!="usb_device", GOTO="ofono_end"
 
 # HUAWEI Technology
 ATTRS{idVendor}=="12d1", ENV{OFONO_DRIVER}="huawei"
+ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1404", ENV{OFONO_DRIVER}="em770"
 
 # Novatel Wireless
 ATTRS{idVendor}=="1410", ENV{OFONO_DRIVER}="novatel"
diff --git a/plugins/udev.c b/plugins/udev.c
index 455bef3..9c4f2c8 100644
--- a/plugins/udev.c
+++ b/plugins/udev.c
@@ -28,6 +28,7 @@
 #include <libudev.h>
 
 #include <glib.h>
+#include <string.h>
 
 #define OFONO_API_SUBJECT_TO_CHANGE
 #include <ofono/plugin.h>
@@ -208,6 +209,30 @@ static void add_huawei(struct ofono_modem *modem,
 	ofono_modem_register(modem);
 }
 
+static void add_em770(struct ofono_modem *modem,
+					struct udev_device *udev_device)
+{
+	const char *devnode, *intf_number;
+	int registered;
+	struct udev_device *parent;
+
+	registered = ofono_modem_get_integer(modem, "Registered");
+	if (registered != 0)
+		return;
+
+	parent = udev_device_get_parent(udev_device);
+	parent = udev_device_get_parent(parent);
+	intf_number = udev_device_get_sysattr_value(parent, "bInterfaceNumber");
+
+	if (!strcmp(intf_number, "02")) {
+		devnode = udev_device_get_devnode(udev_device);
+		ofono_modem_set_string(modem, "Device", devnode);
+
+		ofono_modem_set_integer(modem, "Registered", 1);
+		ofono_modem_register(modem);
+	}
+}
+
 static void add_novatel(struct ofono_modem *modem,
 					struct udev_device *udev_device)
 {
@@ -271,6 +296,8 @@ static void add_modem(struct udev_device *udev_device)
 		add_hso(modem, udev_device);
 	else if (g_strcmp0(driver, "huawei") == 0)
 		add_huawei(modem, udev_device);
+	else if (g_strcmp0(driver, "em770") == 0)
+		add_em770(modem, udev_device);
 	else if (g_strcmp0(driver, "novatel") == 0)
 		add_novatel(modem, udev_device);
 }
-- 
1.6.3.3


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

end of thread, other threads:[~2010-03-16  8:34 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-02-10 10:17 [PATCH] Add support of Huawei EM770 modem Gu, Yang
2010-02-10 17:03 ` Andrzej Zaborowski
2010-02-10 22:37 ` Denis Kenzior
2010-02-11  5:54   ` Gu, Yang
2010-02-12  1:53     ` Andrzej Zaborowski
2010-02-24  3:23       ` Gu, Yang
  -- strict thread matches above, loose matches on Subject: below --
2010-03-16  6:37 Yang Gu
2010-03-16  6:45 ` Marcel Holtmann
2010-03-16  7:05   ` Gu, Yang
2010-03-16  7:42 Yang Gu
2010-03-16  8:34 ` Marcel Holtmann

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.