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

* Re: [PATCH] Add support of Huawei EM770 modem
  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
  1 sibling, 0 replies; 11+ messages in thread
From: Andrzej Zaborowski @ 2010-02-10 17:03 UTC (permalink / raw)
  To: ofono

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

Hi Yang,

On 10 February 2010 11:17, Gu, Yang <yang.gu@intel.com> wrote:
> 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.

If there are more devices on the system that have a USB serial
interface the ttyUSBn numbers will be different so it would be more
reliable to decide based on some other characteristic of ttyUSB2 than
the name (don't know which, maybe you can retrieve USB
config/interface number).  If there's nothing better, then maybe take
n = 2 + the lowest number of the five devices.

Regards,

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

* Re: [PATCH] Add support of Huawei EM770 modem
  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
  1 sibling, 1 reply; 11+ messages in thread
From: Denis Kenzior @ 2010-02-10 22:37 UTC (permalink / raw)
  To: ofono

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

Hi Yang,

> 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

So Andrew had it exactly correct, you can't just use ttyUSB2 here.  Most 
devices have other udev attributes you can examine for what type of port it 
is, to help you pick the right one.  Perhaps examination of 'udevadm info --
attribute-walk --path=<device>' might be in order?

>  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?

We should be using the udev short serial from the device.  For some reason 
this seems to be failing on the EM770.  Can you check whether get_serial 
returns NULL for this device?

Regards,
-Denis

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

* RE: [PATCH] Add support of Huawei EM770 modem
  2010-02-10 22:37 ` Denis Kenzior
@ 2010-02-11  5:54   ` Gu, Yang
  2010-02-12  1:53     ` Andrzej Zaborowski
  0 siblings, 1 reply; 11+ messages in thread
From: Gu, Yang @ 2010-02-11  5:54 UTC (permalink / raw)
  To: ofono

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

Hi, Andrew and Denis,


>-----Original Message-----
>From: ofono-bounces(a)ofono.org [mailto:ofono-bounces(a)ofono.org] On Behalf Of
>Denis Kenzior
>Sent: Thursday, February 11, 2010 6:38 AM
>To: ofono(a)ofono.org
>Subject: Re: [PATCH] Add support of Huawei EM770 modem
>
>Hi Yang,
>
>> 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
>
>So Andrew had it exactly correct, you can't just use ttyUSB2 here.  Most
>devices have other udev attributes you can examine for what type of port it
>is, to help you pick the right one.  Perhaps examination of 'udevadm info --
>attribute-walk --path=<device>' might be in order?

The check of "ttyUSB2" in my code is not the same as you see in /dev directory. 
Below is the output of this modem along its path (not a full path and I removed some unimportant attributes in each path):
  looking at device '/devices/pci0000:00/0000:00:1a.7/usb1/1-3/1-3:1.2/ttyUSB2/tty/ttyUSB2':  (device1)
    KERNEL=="ttyUSB2"
    SUBSYSTEM=="tty"
    DRIVER==""

  looking at parent device '/devices/pci0000:00/0000:00:1a.7/usb1/1-3/1-3:1.2/ttyUSB2': (device2)
    KERNELS=="ttyUSB2"
    SUBSYSTEMS=="usb-serial"
    DRIVERS=="option1"
    ATTRS{port_number}=="0"

  looking at parent device '/devices/pci0000:00/0000:00:1a.7/usb1/1-3/1-3:1.2': (device3)
    KERNELS=="1-3:1.2"
    SUBSYSTEMS=="usb"
    DRIVERS=="option"
    ATTRS{bInterfaceNumber}=="02"
    ATTRS{modalias}=="usb:v12D1p1404d0000dc00dsc00dp00icFFiscFFipFF"
    ATTRS{supports_autosuspend}=="0"

  looking at parent device '/devices/pci0000:00/0000:00:1a.7/usb1/1-3':(device4)
    KERNELS=="1-3"
    ATTRS{configuration}=="Huawei   Configuration"
    ATTRS{bNumInterfaces}==" 5"
    ATTRS{idVendor}=="12d1"
    ATTRS{idProduct}=="1404"
    ATTRS{manufacturer}=="HUAWEI Technology"
    ATTRS{product}=="HUAWEI Mobile"

In oFono code, "device4" represents the modem, while "device1" is the udev_device when calling function add_huawei_em770(modem, udev_device). When I check if it's ttyUSB2 or not in my code, I think I'm checking the device1 and its sysname (Showed as KERNEL in device1, but not the one showed in /dev directory), and in the context of this modem (device4). I do believe there may be some other ttyUSB2 in the system, for example, we have another em770 modem pluged in. But these two ttyUSB2 are in different context. I ever tried to change the name showed in /dev directory by writing some udev rules, but this sysname (KERNEL) seems stable (It's still ttyUSB2). Is it possible this sysname gets changed under some circumstance expect the kernel or driver changes? If not, I still think it's safe and convenient to check this value here. 
Maybe we can use another attribute "bInterfaceNumber". But this attribute is udev_device's parent's parent (device3), so the code could become more complicated. What's your opinion?

>
>>  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?
>
>We should be using the udev short serial from the device.  For some reason
>this seems to be failing on the EM770.  Can you check whether get_serial
>returns NULL for this device?

Yes. get_serial() will return NULL, and we just use its type as name. 

>Regards,
>-Denis
>_______________________________________________
>ofono mailing list
>ofono(a)ofono.org
>http://lists.ofono.org/listinfo/ofono


Regards,
-Yang

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

* Re: [PATCH] Add support of Huawei EM770 modem
  2010-02-11  5:54   ` Gu, Yang
@ 2010-02-12  1:53     ` Andrzej Zaborowski
  2010-02-24  3:23       ` Gu, Yang
  0 siblings, 1 reply; 11+ messages in thread
From: Andrzej Zaborowski @ 2010-02-12  1:53 UTC (permalink / raw)
  To: ofono

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

On 11 February 2010 06:54, Gu, Yang <yang.gu@intel.com> wrote:
> In oFono code, "device4" represents the modem, while "device1" is the udev_device when calling function add_huawei_em770(modem, udev_device). When I check if it's ttyUSB2 or not in my code, I think I'm checking the device1 and its sysname (Showed as KERNEL in device1, but not the one showed in /dev directory), and in the context of this modem (device4). I do believe there may be some other ttyUSB2 in the system, for example, we have another em770 modem pluged in. But these two ttyUSB2 are in different context. I ever tried to change the name showed in /dev directory by writing some udev rules, but this sysname (KERNEL) seems stable (It's still ttyUSB2). Is it possible this sysname gets changed under some circumstance expect the kernel or driver changes? If not, I still think it's safe and convenient to check this value here.

Honestly I don't know.  But the whole /dev path may change between
kernel versions, for example I believe "ttyUSB" was "ttyU" a long time
ago (I'm not 100% sure).  So in my opinion the safe way is to compare
the "bInetrfaceNumber" and "configuration" of the parent devices to
"02" and "Huawei  Configuration".

Best regards

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

* [PATCH] Add support of Huawei EM770 modem
  2010-02-12  1:53     ` Andrzej Zaborowski
@ 2010-02-24  3:23       ` Gu, Yang
  0 siblings, 0 replies; 11+ messages in thread
From: Gu, Yang @ 2010-02-24  3:23 UTC (permalink / raw)
  To: ofono

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

Hi,
	This is the updated patch to guarantee the correct port is used by using "bInterfaceNumber" attribute. Please review!


Regards,
-Yang


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

From 832eedda86297c8e97adcc18fea23b1ff1ca7fd8 Mon Sep 17 00:00:00 2001
From: Yang Gu <yang.gu@intel.com>
Date: Wed, 24 Feb 2010 11:13:21 +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         |   27 ++++++
 4 files changed, 257 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..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  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

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

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

Hi Yang,

> 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

for simplicity just let call it em770.c and everything where you have
huawei_em770 just use em770. We do similar things for G1 etc.

Regards

Marcel



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

* RE: [PATCH] Add support of Huawei EM770 modem
  2010-03-16  6:45 ` Marcel Holtmann
@ 2010-03-16  7:05   ` Gu, Yang
  0 siblings, 0 replies; 11+ messages in thread
From: Gu, Yang @ 2010-03-16  7:05 UTC (permalink / raw)
  To: ofono

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


>-----Original Message-----
>From: ofono-bounces(a)ofono.org [mailto:ofono-bounces(a)ofono.org] On Behalf Of
>Marcel Holtmann
>Sent: Tuesday, March 16, 2010 2:45 PM
>To: ofono(a)ofono.org
>Subject: Re: [PATCH] Add support of Huawei EM770 modem
>
>Hi Yang,
>
>> 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
>
>for simplicity just let call it em770.c and everything where you have
>huawei_em770 just use em770. We do similar things for G1 etc.

I added the prefix "huawei" on purpose so that other users may not confuse about what kind of modem it belongs. Anyway, I will remove it soon. 

>
>Regards
>
>Marcel
>
>
>_______________________________________________
>ofono mailing list
>ofono(a)ofono.org
>http://lists.ofono.org/listinfo/ofono

^ permalink raw reply	[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

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

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

Hi Yang,

> 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

patch has been applied. Thanks.

Regards

Marcel



^ permalink raw reply	[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.