[PATCH v2 2/2] dun_gw: Add BlueZ 5 version

2013-03-12 Thread Frédéric Danis
This patch adds initial implementation of the D-Bus Profile1
interface and methods responsible for handling Bluetooth connections.

The DUN GW profile interface is registered as soon as a GPRS capable
modem is registered in oFono.
---
 Makefile.am |3 +
 plugins/bluez5.h|1 +
 plugins/dun_gw_bluez5.c |  235 +++
 3 files changed, 239 insertions(+)
 create mode 100644 plugins/dun_gw_bluez5.c

diff --git a/Makefile.am b/Makefile.am
index bf4806b..ebe20bd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -443,6 +443,9 @@ builtin_sources += plugins/hfp_hf_bluez5.c plugins/bluez5.h
 
 builtin_modules += hfp_ag_bluez5
 builtin_sources += plugins/hfp_ag_bluez5.c plugins/bluez5.h
+
+builtin_modules += dun_gw_bluez5
+builtin_sources += plugins/dun_gw_bluez5.c plugins/bluez5.h
 endif
 endif
 endif
diff --git a/plugins/bluez5.h b/plugins/bluez5.h
index 573a54c..5b8c1f5 100644
--- a/plugins/bluez5.h
+++ b/plugins/bluez5.h
@@ -25,6 +25,7 @@
 #define BLUEZ_DEVICE_INTERFACE BLUEZ_SERVICE ".Device1"
 #define BLUEZ_ERROR_INTERFACE  BLUEZ_SERVICE ".Error"
 
+#define DUN_GW_UUID"1103--1000-8000-00805f9b34fb"
 #define HFP_HS_UUID"111e--1000-8000-00805f9b34fb"
 #define HFP_AG_UUID"111f--1000-8000-00805f9b34fb"
 
diff --git a/plugins/dun_gw_bluez5.c b/plugins/dun_gw_bluez5.c
new file mode 100644
index 000..326ea9f
--- /dev/null
+++ b/plugins/dun_gw_bluez5.c
@@ -0,0 +1,235 @@
+/*
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2013  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 
+#endif
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include 
+#include 
+#include 
+#include 
+
+#include "bluez5.h"
+
+#ifndef DBUS_TYPE_UNIX_FD
+#define DBUS_TYPE_UNIX_FD -1
+#endif
+
+#define DUN_GW_VERSION_1_0 0x0100
+#define DUN_GW_CHANNEL 1
+#define DUN_GW_EXT_PROFILE_PATH"/bluetooth/profile/dun_gw"
+
+static guint modemwatch_id;
+static GList *modems;
+
+static DBusMessage *profile_new_connection(DBusConnection *conn,
+   DBusMessage *msg, void *data)
+{
+   DBusMessageIter entry;
+   const char *device;
+   int fd;
+   struct ofono_emulator *em;
+   struct ofono_modem *modem;
+
+   DBG("Profile handler NewConnection");
+
+   if (dbus_message_iter_init(msg, &entry) == FALSE)
+   goto invalid;
+
+   if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_OBJECT_PATH)
+   goto invalid;
+
+   dbus_message_iter_get_basic(&entry, &device);
+   dbus_message_iter_next(&entry);
+
+   if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_UNIX_FD)
+   goto invalid;
+
+   dbus_message_iter_get_basic(&entry, &fd);
+   dbus_message_iter_next(&entry);
+
+   if (fd < 0)
+   goto invalid;
+
+   DBG("%s", device);
+
+   /* Pick the first powered modem */
+   modem = modems->data;
+   if (modem == NULL) {
+   close(fd);
+   return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
+   ".Rejected",
+   "No voice call capable modem");
+   }
+
+   DBG("Picked modem %p for emulator", modem);
+
+   em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_DUN);
+   if (em == NULL) {
+   close(fd);
+   return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
+   ".Rejected",
+   "Not enough resources");
+   }
+
+   ofono_emulator_register(em, fd);
+
+   return dbus_message_new_method_return(msg);
+
+invalid:
+   return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE ".Rejected",
+   "Invalid arguments in method call");
+}
+
+static DBusMessage *profile_release(DBusConnection *conn,
+   DBusMessage *msg, void *user_data)
+{
+   DBG("Profile handler Release");
+
+   return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
+   

[PATCH v2 1/2] bluetooth: Rename DUN GW plugin

2013-03-12 Thread Frédéric Danis
As BlueZ 5 introduced backwards incompatible API changes, and we want to
keep support for BlueZ 4 based DUN GW plugin for some time, we need to
separate DUN GW plugin which is based on BlueZ 4 from the one based on
BlueZ 5.

The dun_gw.c plugin is renamed to dun_gw_bluez4. This will make it easy
to add a DUN GW plugin for BlueZ 5.
---
 Makefile.am   |4 ++--
 plugins/{dun_gw.c => dun_gw_bluez4.c} |5 +++--
 2 files changed, 5 insertions(+), 4 deletions(-)
 rename plugins/{dun_gw.c => dun_gw_bluez4.c} (96%)

diff --git a/Makefile.am b/Makefile.am
index 3b998af..bf4806b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -425,8 +425,8 @@ builtin_sources += plugins/hfp_hf_bluez4.c plugins/bluez4.h
 builtin_modules += hfp_ag_bluez4
 builtin_sources += plugins/hfp_ag_bluez4.c plugins/bluez4.h
 
-builtin_modules += dun_gw
-builtin_sources += plugins/dun_gw.c plugins/bluez4.h
+builtin_modules += dun_gw_bluez4
+builtin_sources += plugins/dun_gw_bluez4.c plugins/bluez4.h
 
 builtin_modules += connman
 builtin_sources += plugins/connman.c
diff --git a/plugins/dun_gw.c b/plugins/dun_gw_bluez4.c
similarity index 96%
rename from plugins/dun_gw.c
rename to plugins/dun_gw_bluez4.c
index fc8bde4..a1de7a4 100644
--- a/plugins/dun_gw.c
+++ b/plugins/dun_gw_bluez4.c
@@ -167,5 +167,6 @@ static void dun_gw_exit(void)
}
 }
 
-OFONO_PLUGIN_DEFINE(dun_gw, "Dial-up Networking Profile Plugins", VERSION,
-   OFONO_PLUGIN_PRIORITY_DEFAULT, dun_gw_init, dun_gw_exit)
+OFONO_PLUGIN_DEFINE(dun_gw_bluez4, "Dial-up Networking Profile Plugins",
+   VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT,
+   dun_gw_init, dun_gw_exit)
-- 
1.7.9.5

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH 2/2] dun_gw: Add BlueZ 5 version

2013-03-12 Thread Frédéric Danis
This patch adds initial implementation of the D-Bus Profile1
interface and methods responsible for handling Bluetooth connections.

The DUN GW profile interface is registered as soon as a GPRS capable
modem is registered in oFono.
---
 Makefile.am |3 +
 plugins/bluez5.h|1 +
 plugins/dun_gw_bluez5.c |  235 +++
 3 files changed, 239 insertions(+)
 create mode 100644 plugins/dun_gw_bluez5.c

diff --git a/Makefile.am b/Makefile.am
index bf4806b..ebe20bd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -443,6 +443,9 @@ builtin_sources += plugins/hfp_hf_bluez5.c plugins/bluez5.h
 
 builtin_modules += hfp_ag_bluez5
 builtin_sources += plugins/hfp_ag_bluez5.c plugins/bluez5.h
+
+builtin_modules += dun_gw_bluez5
+builtin_sources += plugins/dun_gw_bluez5.c plugins/bluez5.h
 endif
 endif
 endif
diff --git a/plugins/bluez5.h b/plugins/bluez5.h
index 573a54c..5b8c1f5 100644
--- a/plugins/bluez5.h
+++ b/plugins/bluez5.h
@@ -25,6 +25,7 @@
 #define BLUEZ_DEVICE_INTERFACE BLUEZ_SERVICE ".Device1"
 #define BLUEZ_ERROR_INTERFACE  BLUEZ_SERVICE ".Error"
 
+#define DUN_GW_UUID"1103--1000-8000-00805f9b34fb"
 #define HFP_HS_UUID"111e--1000-8000-00805f9b34fb"
 #define HFP_AG_UUID"111f--1000-8000-00805f9b34fb"
 
diff --git a/plugins/dun_gw_bluez5.c b/plugins/dun_gw_bluez5.c
new file mode 100644
index 000..902df32
--- /dev/null
+++ b/plugins/dun_gw_bluez5.c
@@ -0,0 +1,235 @@
+/*
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011  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 
+#endif
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include 
+#include 
+#include 
+#include 
+
+#include "bluez5.h"
+
+#ifndef DBUS_TYPE_UNIX_FD
+#define DBUS_TYPE_UNIX_FD -1
+#endif
+
+#define DUN_GW_VERSION_1_0 0x0100
+#define DUN_GW_CHANNEL 1
+#define DUN_GW_EXT_PROFILE_PATH"/bluetooth/profile/dun_gw"
+
+static guint modemwatch_id;
+static GList *modems;
+
+static DBusMessage *profile_new_connection(DBusConnection *conn,
+   DBusMessage *msg, void *data)
+{
+   DBusMessageIter entry;
+   const char *device;
+   int fd;
+   struct ofono_emulator *em;
+   struct ofono_modem *modem;
+
+   DBG("Profile handler NewConnection");
+
+   if (dbus_message_iter_init(msg, &entry) == FALSE)
+   goto invalid;
+
+   if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_OBJECT_PATH)
+   goto invalid;
+
+   dbus_message_iter_get_basic(&entry, &device);
+   dbus_message_iter_next(&entry);
+
+   if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_UNIX_FD)
+   goto invalid;
+
+   dbus_message_iter_get_basic(&entry, &fd);
+   dbus_message_iter_next(&entry);
+
+   if (fd < 0)
+   goto invalid;
+
+   DBG("%s", device);
+
+   /* Pick the first powered modem */
+   modem = modems->data;
+   if (modem == NULL) {
+   close(fd);
+   return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
+   ".Rejected",
+   "No voice call capable modem");
+   }
+
+   DBG("Picked modem %p for emulator", modem);
+
+   em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_DUN);
+   if (em == NULL) {
+   close(fd);
+   return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
+   ".Rejected",
+   "Not enough resources");
+   }
+
+   ofono_emulator_register(em, fd);
+
+   return dbus_message_new_method_return(msg);
+
+invalid:
+   return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE ".Rejected",
+   "Invalid arguments in method call");
+}
+
+static DBusMessage *profile_release(DBusConnection *conn,
+   DBusMessage *msg, void *user_data)
+{
+   DBG("Profile handler Release");
+
+   return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
+   

[PATCH 1/2] bluetooth: Rename DUN GW plugin

2013-03-12 Thread Frédéric Danis
As BlueZ 5 introduced backwards incompatible API changes, and we want to
keep support for BlueZ 4 based DUN GW plugin for some time, we need to
separate DUN GW plugin which is based on BlueZ 4 from the one based on
BlueZ 5.

The dun_gw.c plugin is renamed to dun_gw_bluez4. This will make it easy
to add a DUN GW plugin for BlueZ 5.
---
 Makefile.am   |4 ++--
 plugins/{dun_gw.c => dun_gw_bluez4.c} |5 +++--
 2 files changed, 5 insertions(+), 4 deletions(-)
 rename plugins/{dun_gw.c => dun_gw_bluez4.c} (96%)

diff --git a/Makefile.am b/Makefile.am
index 3b998af..bf4806b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -425,8 +425,8 @@ builtin_sources += plugins/hfp_hf_bluez4.c plugins/bluez4.h
 builtin_modules += hfp_ag_bluez4
 builtin_sources += plugins/hfp_ag_bluez4.c plugins/bluez4.h
 
-builtin_modules += dun_gw
-builtin_sources += plugins/dun_gw.c plugins/bluez4.h
+builtin_modules += dun_gw_bluez4
+builtin_sources += plugins/dun_gw_bluez4.c plugins/bluez4.h
 
 builtin_modules += connman
 builtin_sources += plugins/connman.c
diff --git a/plugins/dun_gw.c b/plugins/dun_gw_bluez4.c
similarity index 96%
rename from plugins/dun_gw.c
rename to plugins/dun_gw_bluez4.c
index fc8bde4..a1de7a4 100644
--- a/plugins/dun_gw.c
+++ b/plugins/dun_gw_bluez4.c
@@ -167,5 +167,6 @@ static void dun_gw_exit(void)
}
 }
 
-OFONO_PLUGIN_DEFINE(dun_gw, "Dial-up Networking Profile Plugins", VERSION,
-   OFONO_PLUGIN_PRIORITY_DEFAULT, dun_gw_init, dun_gw_exit)
+OFONO_PLUGIN_DEFINE(dun_gw_bluez4, "Dial-up Networking Profile Plugins",
+   VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT,
+   dun_gw_init, dun_gw_exit)
-- 
1.7.9.5

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH 5/5] hfp_ag_bluez5: Add SCO listen socket

2013-02-05 Thread Frédéric Danis
This patch adds the initial SCO server socket handling.
---
 plugins/hfp_ag_bluez5.c |   83 +++
 1 file changed, 83 insertions(+)

diff --git a/plugins/hfp_ag_bluez5.c b/plugins/hfp_ag_bluez5.c
index c6b858e..ee8c8bf 100644
--- a/plugins/hfp_ag_bluez5.c
+++ b/plugins/hfp_ag_bluez5.c
@@ -48,6 +48,7 @@ struct hfp_ag {
struct ofono_emulator *em;
bdaddr_t local;
bdaddr_t peer;
+   guint sco_watch;
 };
 
 static guint modemwatch_id;
@@ -64,6 +65,9 @@ static void free_hfp_ag(void *data)
if (hfp_ag == NULL)
return;
 
+   if (hfp_ag->sco_watch)
+   g_source_remove(hfp_ag->sco_watch);
+
hfp_ags = g_slist_remove(hfp_ags, hfp_ag);
g_free(hfp_ag);
 }
@@ -206,6 +210,82 @@ static const GDBusMethodTable profile_methods[] = {
{ }
 };
 
+static gboolean sco_cb(GIOChannel *io, GIOCondition cond,
+   gpointer user_data)
+
+{
+   struct hfp_ag *hfp_ag = user_data;
+   char adapter_address[18];
+   char device_address[18];
+
+   if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
+   hfp_ag->sco_watch = 0;
+
+   bt_ba2str(&hfp_ag->local, adapter_address);
+   bt_ba2str(&hfp_ag->peer, device_address);
+   DBG("SCO: %s - %s (closed)", adapter_address, device_address);
+
+   return FALSE;
+   }
+
+   return TRUE;
+}
+
+static gboolean hfp_ag_sco_accept(int fd, struct sockaddr_sco *raddr)
+{
+   struct sockaddr_sco laddr;
+   socklen_t optlen;
+   GSList *l;
+   char adapter_address[18];
+   char device_address[18];
+   struct hfp_ag *hfp_ag = NULL;
+   GIOChannel *sco_io;
+   int err;
+
+   memset(&laddr, 0, sizeof(laddr));
+   optlen = sizeof(laddr);
+   if (getsockname(fd, (struct sockaddr *) &laddr, &optlen) < 0) {
+   err = errno;
+   ofono_error("SCO getsockname(): %s (%d)", strerror(err), err);
+   return FALSE;
+   }
+
+   for (l = hfp_ags; l; l = l->next) {
+   struct hfp_ag *tmp = l->data;
+
+   if (bt_bacmp(&laddr.sco_bdaddr, &tmp->local) != 0)
+   continue;
+
+   if (bt_bacmp(&raddr->sco_bdaddr, &tmp->peer) != 0)
+   continue;
+
+   hfp_ag = tmp;
+   break;
+   }
+
+   if (!hfp_ag) {
+   ofono_error("Rejecting SCO: SLC connection missing!");
+   return FALSE;
+   }
+
+   bt_ba2str(&laddr.sco_bdaddr, adapter_address);
+   bt_ba2str(&raddr->sco_bdaddr, device_address);
+   DBG("SCO: %s < %s (incoming)", adapter_address, device_address);
+
+   sco_io = g_io_channel_unix_new(fd);
+
+   g_io_channel_set_close_on_unref(sco_io, TRUE);
+   g_io_channel_set_flags(sco_io, G_IO_FLAG_NONBLOCK, NULL);
+
+   hfp_ag->sco_watch = g_io_add_watch(sco_io,
+   G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+   sco_cb, hfp_ag);
+
+   g_io_channel_unref(sco_io);
+
+   return TRUE;
+}
+
 static void sim_state_watch(enum ofono_sim_state new_state, void *data)
 {
struct ofono_modem *modem = data;
@@ -219,6 +299,7 @@ static void sim_state_watch(enum ofono_sim_state new_state, 
void *data)
if (modems != NULL)
return;
 
+   bt_unregister_sco_server(hfp_ag_sco_accept);
bluetooth_unregister_profile(conn, HFP_AG_EXT_PROFILE_PATH);
 
return;
@@ -234,6 +315,8 @@ static void sim_state_watch(enum ofono_sim_state new_state, 
void *data)
 
bluetooth_register_profile(conn, HFP_AG_UUID, "hfp_ag",
HFP_AG_EXT_PROFILE_PATH);
+
+   bt_register_sco_server(hfp_ag_sco_accept);
 }
 
 static gboolean sim_watch_remove(gpointer key, gpointer value,
-- 
1.7.9.5

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH 4/5] hfp_ag_bluez5: Add list of HFP AG emulators

2013-02-05 Thread Frédéric Danis
This will be used to retrieve hfp_ag related to the incoming SCO
---
 plugins/hfp_ag_bluez5.c |   56 +++
 1 file changed, 56 insertions(+)

diff --git a/plugins/hfp_ag_bluez5.c b/plugins/hfp_ag_bluez5.c
index 80dd601..c6b858e 100644
--- a/plugins/hfp_ag_bluez5.c
+++ b/plugins/hfp_ag_bluez5.c
@@ -44,9 +44,29 @@
 
 #define HFP_AG_EXT_PROFILE_PATH   "/bluetooth/profile/hfp_ag"
 
+struct hfp_ag {
+   struct ofono_emulator *em;
+   bdaddr_t local;
+   bdaddr_t peer;
+};
+
 static guint modemwatch_id;
 static GList *modems;
 static GHashTable *sim_hash = NULL;
+static GSList *hfp_ags;
+
+static void free_hfp_ag(void *data)
+{
+   struct hfp_ag *hfp_ag = data;
+
+   DBG("");
+
+   if (hfp_ag == NULL)
+   return;
+
+   hfp_ags = g_slist_remove(hfp_ags, hfp_ag);
+   g_free(hfp_ag);
+}
 
 static DBusMessage *profile_new_connection(DBusConnection *conn,
DBusMessage *msg, void *data)
@@ -54,8 +74,13 @@ static DBusMessage *profile_new_connection(DBusConnection 
*conn,
DBusMessageIter entry;
const char *device;
int fd;
+   struct sockaddr_rc saddr;
+   bdaddr_t local;
+   bdaddr_t peer;
+   socklen_t optlen;
struct ofono_emulator *em;
struct ofono_modem *modem;
+   struct hfp_ag *hfp_ag;
 
DBG("Profile handler NewConnection");
 
@@ -79,6 +104,26 @@ static DBusMessage *profile_new_connection(DBusConnection 
*conn,
 
DBG("%s", device);
 
+   memset(&saddr, 0, sizeof(saddr));
+   optlen = sizeof(saddr);
+   if (getsockname(fd, (struct sockaddr *) &saddr, &optlen) < 0) {
+   ofono_error("RFCOMM getsockname(): %s (%d)", strerror(errno),
+   errno);
+   goto error;
+   }
+
+   local = saddr.rc_bdaddr;
+
+   memset(&saddr, 0, sizeof(saddr));
+   optlen = sizeof(saddr);
+   if (getpeername(fd, (struct sockaddr *) &saddr, &optlen) < 0) {
+   ofono_error("RFCOMM getpeername(): %s (%d)", strerror(errno),
+   errno);
+   goto error;
+   }
+
+   peer = saddr.rc_bdaddr;
+
/* Pick the first voicecall capable modem */
modem = modems->data;
if (modem == NULL) {
@@ -100,8 +145,19 @@ static DBusMessage *profile_new_connection(DBusConnection 
*conn,
 
ofono_emulator_register(em, fd);
 
+   hfp_ag = g_new0(struct hfp_ag, 1);
+   hfp_ag->em = em;
+   hfp_ag->local = local;
+   hfp_ag->peer = peer;
+   ofono_emulator_set_data(em, hfp_ag, free_hfp_ag);
+
+   hfp_ags = g_slist_append(hfp_ags, hfp_ag);
+
return dbus_message_new_method_return(msg);
 
+error:
+   close(fd);
+
 invalid:
return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE ".Rejected",
"Invalid arguments in method call");
-- 
1.7.9.5

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH 3/5] emulator: Add set/get data APIs

2013-02-05 Thread Frédéric Danis
---
 src/emulator.c |   17 +
 1 file changed, 17 insertions(+)

diff --git a/src/emulator.c b/src/emulator.c
index c3165eb..14a39f3 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -52,6 +52,8 @@ struct ofono_emulator {
gboolean clip;
gboolean ccwa;
int pns_id;
+   void *data;
+   ofono_destroy_func destroy;
 };
 
 struct indicator {
@@ -951,6 +953,9 @@ static void emulator_remove(struct ofono_atom *atom)
 
DBG("atom: %p", atom);
 
+   if (em->destroy)
+   em->destroy(em->data);
+
g_free(em);
 }
 
@@ -994,6 +999,18 @@ void ofono_emulator_remove(struct ofono_emulator *em)
__ofono_atom_free(em->atom);
 }
 
+void ofono_emulator_set_data(struct ofono_emulator *em, void *data,
+   ofono_destroy_func destroy)
+{
+   em->data = data;
+   em->destroy = destroy;
+}
+
+void *ofono_emulator_get_data(struct ofono_emulator *em)
+{
+   return em->data;
+}
+
 void ofono_emulator_send_final(struct ofono_emulator *em,
const struct ofono_error *final)
 {
-- 
1.7.9.5

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH 2/5] include: Add set/get data APIs to emulator

2013-02-05 Thread Frédéric Danis
---
 include/emulator.h |5 +
 1 file changed, 5 insertions(+)

diff --git a/include/emulator.h b/include/emulator.h
index 5cd894b..6dc1938 100644
--- a/include/emulator.h
+++ b/include/emulator.h
@@ -74,6 +74,11 @@ void ofono_emulator_register(struct ofono_emulator *em, int 
fd);
 
 void ofono_emulator_remove(struct ofono_emulator *em);
 
+void ofono_emulator_set_data(struct ofono_emulator *em, void *data,
+   ofono_destroy_func destroy);
+
+void *ofono_emulator_get_data(struct ofono_emulator *em);
+
 void ofono_emulator_send_final(struct ofono_emulator *em,
const struct ofono_error *final);
 void ofono_emulator_send_unsolicited(struct ofono_emulator *em,
-- 
1.7.9.5

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH 1/5] bluez5: Add SCO server register/unregister

2013-02-05 Thread Frédéric Danis
SCO server should be shared by both HFP HF and HFP AG plugins.
---
 plugins/bluez5.c|  117 +++
 plugins/bluez5.h|5 ++
 plugins/hfp_hf_bluez5.c |   72 ++---
 3 files changed, 127 insertions(+), 67 deletions(-)

diff --git a/plugins/bluez5.c b/plugins/bluez5.c
index d5c566e..5d10f44 100644
--- a/plugins/bluez5.c
+++ b/plugins/bluez5.c
@@ -26,6 +26,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 
@@ -41,6 +43,9 @@
 
 #define BLUEZ_PROFILE_MGMT_INTERFACE   BLUEZ_SERVICE ".ProfileManager1"
 
+static guint sco_watch;
+static GSList *sco_cbs;
+
 void bt_bacpy(bdaddr_t *dst, const bdaddr_t *src)
 {
memcpy(dst, src, sizeof(bdaddr_t));
@@ -57,6 +62,118 @@ int bt_bacmp(const bdaddr_t *ba1, const bdaddr_t *ba2)
return memcmp(ba1, ba2, sizeof(bdaddr_t));
 }
 
+static gboolean sco_accept(GIOChannel *io, GIOCondition cond,
+   gpointer user_data)
+{
+   struct sockaddr_sco saddr;
+   socklen_t alen;
+   int sk, nsk;
+   GSList *l;
+
+   if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
+   return FALSE;
+
+   sk = g_io_channel_unix_get_fd(io);
+
+   memset(&saddr, 0, sizeof(saddr));
+   alen = sizeof(saddr);
+
+   nsk = accept(sk, (struct sockaddr *) &saddr, &alen);
+   if (nsk < 0)
+   return TRUE;
+
+   for (l = sco_cbs; l; l = l->next) {
+   bt_sco_accept_cb cb = l->data;
+
+   if (cb(nsk, &saddr))
+   return TRUE;
+   }
+
+   ofono_warn("No SCO callback for incoming connection");
+   close(nsk);
+
+   return TRUE;
+}
+
+static int sco_init(void)
+{
+   GIOChannel *sco_io;
+   struct sockaddr_sco saddr;
+   int sk, defer_setup = 1;
+
+   sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET | O_NONBLOCK | SOCK_CLOEXEC,
+   BTPROTO_SCO);
+   if (sk < 0)
+   return -errno;
+
+   /* Bind to local address */
+   memset(&saddr, 0, sizeof(saddr));
+   saddr.sco_family = AF_BLUETOOTH;
+   bt_bacpy(&saddr.sco_bdaddr, BDADDR_ANY);
+
+   if (bind(sk, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
+   close(sk);
+   return -errno;
+   }
+
+   if (setsockopt(sk, SOL_BLUETOOTH, BT_DEFER_SETUP,
+   &defer_setup, sizeof(defer_setup)) < 0)
+   ofono_warn("Can't enable deferred setup: %s (%d)",
+   strerror(errno), errno);
+
+   if (listen(sk, 5) < 0) {
+   close(sk);
+   return -errno;
+   }
+
+   sco_io = g_io_channel_unix_new(sk);
+   g_io_channel_set_close_on_unref(sco_io, TRUE);
+
+   sco_watch = g_io_add_watch(sco_io,
+   G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+   sco_accept, NULL);
+
+   g_io_channel_unref(sco_io);
+
+   return 0;
+}
+
+int bt_register_sco_server(bt_sco_accept_cb cb)
+{
+   int err;
+
+   if (!cb) {
+   ofono_error("SCO: invalid callback");
+   return -1;
+   }
+
+   if (!sco_cbs) {
+   err = sco_init();
+   if (err < 0) {
+   ofono_error("SCO: %s(%d)", strerror(-err), -err);
+   return err;
+   }
+   }
+
+   sco_cbs = g_slist_append(sco_cbs, cb);
+
+   return 0;
+}
+
+void bt_unregister_sco_server(bt_sco_accept_cb cb)
+{
+   if (!cb) {
+   ofono_error("SCO: invalid callback");
+   return;
+   }
+
+   sco_cbs = g_slist_remove(sco_cbs, cb);
+   if (sco_cbs)
+   return;
+
+   g_source_remove(sco_watch);
+}
+
 static void profile_register_cb(DBusPendingCall *call, gpointer user_data)
 {
DBusMessage *reply;
diff --git a/plugins/bluez5.h b/plugins/bluez5.h
index cdbfe72..29eba12 100644
--- a/plugins/bluez5.h
+++ b/plugins/bluez5.h
@@ -69,6 +69,11 @@ int bt_ba2str(const bdaddr_t *ba, char *str);
 
 int bt_bacmp(const bdaddr_t *ba1, const bdaddr_t *ba2);
 
+typedef gboolean (*bt_sco_accept_cb)(int fd, struct sockaddr_sco *saddr);
+
+int bt_register_sco_server(bt_sco_accept_cb cb);
+void bt_unregister_sco_server(bt_sco_accept_cb cb);
+
 int bluetooth_register_profile(DBusConnection *conn, const char *uuid,
const char *name, const char *object);
 
diff --git a/plugins/hfp_hf_bluez5.c b/plugins/hfp_hf_bluez5.c
index 2f4a89e..a8738bd 100644
--- a/plugins/hfp_hf_bluez5.c
+++ b/plugins/hfp_hf_bluez5.c
@@ -65,7 +65,6 @@ struct hfp {
 
 static GHashTable *modem_hash = NULL;
 static GDBusClient *bluez = NULL;
-static guint sco_watch = 0;
 
 static void hfp_debug(const char *str, void *user_data)
 {
@@ -360,69 +359,11 @@ static const GDBusMethodTable profile_methods[]

[PATCH 2/2] hfp_ag: Add BlueZ 5 version

2013-01-29 Thread Frédéric Danis
This patch adds initial implementation of the D-Bus Profile1
interface and methods responsible for handling Bluetooth connections.

The HFP AG profile interface is registered as soon as a voice capable
modem is registered in oFono.
---
 Makefile.am |3 +
 plugins/hfp_ag_bluez5.c |  269 +++
 2 files changed, 272 insertions(+)
 create mode 100644 plugins/hfp_ag_bluez5.c

diff --git a/Makefile.am b/Makefile.am
index ee6d24c..ef4d314 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -439,6 +439,9 @@ builtin_sources += plugins/bluez5.c plugins/bluez5.h
 
 builtin_modules += hfp_bluez5
 builtin_sources += plugins/hfp_hf_bluez5.c plugins/bluez5.h
+
+builtin_modules += hfp_ag_bluez5
+builtin_sources += plugins/hfp_ag_bluez5.c plugins/bluez5.h
 endif
 endif
 endif
diff --git a/plugins/hfp_ag_bluez5.c b/plugins/hfp_ag_bluez5.c
new file mode 100644
index 000..59e37bc
--- /dev/null
+++ b/plugins/hfp_ag_bluez5.c
@@ -0,0 +1,269 @@
+/*
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011  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 
+#endif
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include 
+#include 
+#include 
+#include 
+
+#include "bluez5.h"
+
+#ifndef DBUS_TYPE_UNIX_FD
+#define DBUS_TYPE_UNIX_FD -1
+#endif
+
+#define HFP_AG_EXT_PROFILE_PATH   "/bluetooth/profile/hfp_ag"
+
+static guint modemwatch_id;
+static GList *modems;
+static GHashTable *sim_hash = NULL;
+
+static DBusMessage *profile_new_connection(DBusConnection *conn,
+   DBusMessage *msg, void *data)
+{
+   DBusMessageIter entry;
+   const char *device;
+   int fd;
+   struct ofono_emulator *em;
+   struct ofono_modem *modem;
+
+   DBG("Profile handler NewConnection");
+
+   if (dbus_message_iter_init(msg, &entry) == FALSE)
+   goto invalid;
+
+   if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_OBJECT_PATH)
+   goto invalid;
+
+   dbus_message_iter_get_basic(&entry, &device);
+   dbus_message_iter_next(&entry);
+
+   if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_UNIX_FD)
+   goto invalid;
+
+   dbus_message_iter_get_basic(&entry, &fd);
+   dbus_message_iter_next(&entry);
+
+   if (fd < 0)
+   goto invalid;
+
+   DBG("%s", device);
+
+   /* Pick the first voicecall capable modem */
+   modem = modems->data;
+   if (modem == NULL) {
+   close(fd);
+   return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
+   ".Rejected",
+   "No voice call capable modem");
+   }
+
+   DBG("Picked modem %p for emulator", modem);
+
+   em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_HFP);
+   if (em == NULL) {
+   close(fd);
+   return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
+   ".Rejected",
+   "Not enough resources");
+   }
+
+   ofono_emulator_register(em, fd);
+
+   return dbus_message_new_method_return(msg);
+
+invalid:
+   return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE ".Rejected",
+   "Invalid arguments in method call");
+}
+
+static DBusMessage *profile_release(DBusConnection *conn,
+   DBusMessage *msg, void *user_data)
+{
+   DBG("Profile handler Release");
+
+   return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
+   ".NotImplemented",
+   "Implementation not provided");
+}
+
+static DBusMessage *profile_cancel(DBusConnection *conn,
+   DBusMessage *msg, void *user_data)
+{
+   DBG("Profile handler Cancel");
+
+   return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
+   ".NotImplemented",
+   "Implementation not provided");
+}
+
+static DBusMessage *profile_disconnection(DBusConnection *conn,
+   

[PATCH 1/2] bluetooth: Rename HFP AG plugin

2013-01-29 Thread Frédéric Danis
As BlueZ 5 introduced backwards incompatible API changes, and we want to
keep support for BlueZ 4 based HFP AG plugin for some time, we need to
separate HFP AG plugin which is based on BlueZ 4 from the one based on
BlueZ 5.

The hfp_ag.c plugin is renamed to hfp_ag_bluez4. This will make it easy
to add an HFP AG plugin for BlueZ 5.
---
 Makefile.am   |4 ++--
 plugins/{hfp_ag.c => hfp_ag_bluez4.c} |5 +++--
 2 files changed, 5 insertions(+), 4 deletions(-)
 rename plugins/{hfp_ag.c => hfp_ag_bluez4.c} (97%)

diff --git a/Makefile.am b/Makefile.am
index f24cac7..ee6d24c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -421,8 +421,8 @@ builtin_sources += plugins/sap.c plugins/bluez4.h
 builtin_modules += hfp_bluez4
 builtin_sources += plugins/hfp_hf_bluez4.c plugins/bluez4.h
 
-builtin_modules += hfp_ag
-builtin_sources += plugins/hfp_ag.c plugins/bluez4.h
+builtin_modules += hfp_ag_bluez4
+builtin_sources += plugins/hfp_ag_bluez4.c plugins/bluez4.h
 
 builtin_modules += dun_gw
 builtin_sources += plugins/dun_gw.c plugins/bluez4.h
diff --git a/plugins/hfp_ag.c b/plugins/hfp_ag_bluez4.c
similarity index 97%
rename from plugins/hfp_ag.c
rename to plugins/hfp_ag_bluez4.c
index 12374ad..039b665 100644
--- a/plugins/hfp_ag.c
+++ b/plugins/hfp_ag_bluez4.c
@@ -213,5 +213,6 @@ static void hfp_ag_exit(void)
}
 }
 
-OFONO_PLUGIN_DEFINE(hfp_ag, "Hands-Free Audio Gateway Profile Plugins", 
VERSION,
-   OFONO_PLUGIN_PRIORITY_DEFAULT, hfp_ag_init, hfp_ag_exit)
+OFONO_PLUGIN_DEFINE(hfp_ag_bluez4, "Hands-Free Audio Gateway Profile Plugins",
+   VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT,
+   hfp_ag_init, hfp_ag_exit)
-- 
1.7.9.5

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v6 11/12] emulator: Update supported features

2012-08-01 Thread Frédéric Danis
Add ECNR (Echo Cancelation/Noise Reduction) and Inband Ringtone
capabilities to supported features (+BRSF event)
---
 src/emulator.c |2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/emulator.c b/src/emulator.c
index 14a39f3..791d88b 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -981,6 +981,8 @@ struct ofono_emulator *ofono_emulator_create(struct 
ofono_modem *modem,
 
em->type = type;
em->l_features |= HFP_AG_FEATURE_3WAY;
+   em->l_features |= HFP_AG_FEATURE_ECNR;
+   em->l_features |= HFP_AG_FEATURE_IN_BAND_RING_TONE;
em->l_features |= HFP_AG_FEATURE_REJECT_CALL;
em->l_features |= HFP_AG_FEATURE_ENHANCED_CALL_STATUS;
em->l_features |= HFP_AG_FEATURE_ENHANCED_CALL_CONTROL;
-- 
1.7.9.5

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v6 12/12] dun_gw: Update to org.bluez.Telephony interface

2012-08-01 Thread Frédéric Danis
Bluez moves agent registration from a per device interface to
a per adapter interface.
Update dun_gw modem emulator to reflect this change.
---
 plugins/dun_gw.c |  119 --
 1 file changed, 52 insertions(+), 67 deletions(-)

diff --git a/plugins/dun_gw.c b/plugins/dun_gw.c
index 75b62eb..5cc839e 100644
--- a/plugins/dun_gw.c
+++ b/plugins/dun_gw.c
@@ -35,77 +35,65 @@
 
 #include "bluetooth.h"
 
-#define DUN_GW_CHANNEL 1
+#define AGENT_PATH "/dun_gw"
+#define VERSION_1_00x0100
+
+#ifndef DBUS_TYPE_UNIX_FD
+#define DBUS_TYPE_UNIX_FD -1
+#endif
 
-static struct server *server;
 static guint modemwatch_id;
 static GList *modems;
 
-static const gchar *dun_record =
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"  \n"
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n";
-
-static void dun_gw_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
+static DBusMessage *dun_gw_agent_new_connection(DBusConnection *conn,
+   DBusMessage *msg, void *data)
 {
-   struct ofono_emulator *em = user_data;
-   struct ofono_modem *modem;
int fd;
+   const char *device;
+   guint16 version = 0;
+   struct ofono_emulator *em;
+   struct ofono_modem *modem;
 
-   DBG("");
+   fd = bluetooth_parse_newconnection_message(msg, &device, &version, NULL,
+   NULL);
+   if (fd < 0)
+   return __ofono_error_invalid_args(msg);
 
-   if (err) {
-   DBG("%s", err->message);
-   g_io_channel_shutdown(io, TRUE, NULL);
-   return;
-   }
+   DBG("New connection for %s (version 0x%04X)", device, version);
 
/* Pick the first powered modem */
modem = modems->data;
+   if (modem == NULL)
+   return __ofono_error_failed(msg);
+
DBG("Picked modem %p for emulator", modem);
 
em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_DUN);
-   if (em == NULL) {
-   g_io_channel_shutdown(io, TRUE, NULL);
-   return;
-   }
-
-   fd = g_io_channel_unix_get_fd(io);
-   g_io_channel_set_close_on_unref(io, FALSE);
+   if (em == NULL)
+   return __ofono_error_failed(msg);
 
ofono_emulator_register(em, fd);
+
+   return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *dun_gw_agent_release(DBusConnection *conn,
+   DBusMessage *msg, void *data)
+{
+   DBG("");
+
+   return dbus_message_new_method_return(msg);
 }
 
+static const GDBusMethodTable agent_methods[] = {
+   { GDBUS_ASYNC_METHOD("NewConnection",
+   GDBUS_ARGS({ "fd", "h" },
+   { "property", "a{sv}" }),
+   NULL, dun_gw_agent_new_connection) },
+   { GDBUS_METHOD("Release", NULL, NULL, dun_gw_agent_release) },
+   { }
+};
+
 static void gprs_watch(struct ofono_atom *atom,
enum ofono_atom_watch_condition cond,
void *data)
@@ -115,17 +103,16 @@ static void gprs_watch(struct ofono_atom *atom,
if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) {
modems = g_list_append(modems, modem);
 
-   if (modems->next == NULL)
-   server = bluetooth_register_server(DUN_GW_CHANNEL,
-   dun_record,
-   dun_gw_connect_cb,
-   NULL);
+   if (modems->next != NULL)
+   return;
+
+   bluetooth_register_telephony_agent(AGENT_PATH, DUN_GW_UUID,
+  VERSION_1_0, 0,
+  agent_methods, NULL, NULL);
} else {
modems = g_list_remove(modems, modem);
-   if (modems == NULL && server != NULL) {
-   bluetooth_unregister_server(server);
-   server = NULL;
-   }
+   if (modems == NULL)
+   bluetooth_unregister_telephony_agent(AGENT_PATH);
}
 }
 
@@ -149,6 +136,9 @@ static int dun_gw_init(void)
 {
DBG("");
 
+   if (DBUS_TYPE_UNIX_FD < 0)
+   return -EBADF;
+
modemwatch_id = __ofono_modemwatch_add(modem_watch, NULL, NULL);
 
__ofono_modem_foreach(call_modemwatch, NULL);
@@ -160,11 +150,6 @@ static void dun_gw_exit(void)
 {
__ofono_modemwatch_remove(modemwatch_id);
g_list_free(modems);
-
-   if (server) {
-   bluetooth_unregister_ser

[RFC v6 10/12] hfp_ag: Add AT+VGS support

2012-08-01 Thread Frédéric Danis
---
 plugins/hfp_ag.c |   74 ++
 1 file changed, 74 insertions(+)

diff --git a/plugins/hfp_ag.c b/plugins/hfp_ag.c
index f865208..3084cd6 100644
--- a/plugins/hfp_ag.c
+++ b/plugins/hfp_ag.c
@@ -56,6 +56,8 @@ struct bt_audio {
guint watch;
int mic_gain;
int mic_pending;
+   int sp_gain;
+   int sp_pending;
 };
 
 static guint modemwatch_id;
@@ -214,6 +216,39 @@ fail:
};
 }
 
+static void emulator_vgs_cb(struct ofono_emulator *em,
+   struct ofono_emulator_request *req, void *userdata)
+{
+   struct bt_audio *audio = userdata;
+   struct ofono_error result;
+   int val;
+   dbus_uint16_t dbus_val;
+
+   switch (ofono_emulator_request_get_type(req)) {
+   case OFONO_EMULATOR_REQUEST_TYPE_SET:
+   if (!ofono_emulator_request_next_number(req, &val))
+   goto fail;
+
+   if (val < 0 && val > 15)
+   goto fail;
+
+   if (audio->sp_pending != -1)
+   ofono_error("Receiving AT+VGS while processing one");
+
+   audio->sp_pending = val;
+   dbus_val = val;
+   audio_transport_set_property(audio, "OutputGain",
+   DBUS_TYPE_UINT16, &dbus_val);
+   break;
+
+   default:
+fail:
+   result.error = 0;
+   result.type = OFONO_ERROR_TYPE_FAILURE;
+   ofono_emulator_send_final(em, &result);
+   };
+}
+
 static gboolean audio_property_changed(DBusConnection *connection,
DBusMessage *message, void *user_data)
 {
@@ -286,6 +321,43 @@ static gboolean audio_property_changed(DBusConnection 
*connection,
} else if (audio->mic_pending == value)
audio->mic_pending = -1;
audio->mic_gain = value;
+   } else if (g_str_equal(property, "OutputGain") == TRUE) {
+   DBusMessageIter variant;
+   dbus_uint16_t dbus_val;
+   int value;
+
+   if (!(audio->r_features & HFP_HF_FEATURE_REMOTE_VOLUME_CONTROL))
+   return TRUE;
+
+   if (!dbus_message_iter_next(&iter))
+   return TRUE;
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+   return TRUE;
+
+   dbus_message_iter_recurse(&iter, &variant);
+
+   if (dbus_message_iter_get_arg_type(&variant) !=
+   DBUS_TYPE_UINT16)
+   return TRUE;
+
+   dbus_message_iter_get_basic(&variant, &dbus_val);
+   value = dbus_val;
+
+   /* Send unsolicited +VGS only if :
+*   - the value has changed
+*   - and this is not a side effect of AT+VGS
+* But, if we receive a value change while waiting for another
+* pending change, we may have to send +VGS for other changes
+* (multiple AT+VGS received) to keep speaker gain in sync
+*/
+   if (audio->sp_pending != value && audio->sp_gain != value) {
+   sprintf(buf, "+VGS: %d", value);
+   ofono_emulator_send_unsolicited(audio->em, buf);
+   audio->sp_pending = -1;
+   } else if (audio->sp_pending == value)
+   audio->sp_pending = -1;
+   audio->sp_gain = value;
}
 
return TRUE;
@@ -348,11 +420,13 @@ static DBusMessage 
*hfp_ag_agent_new_connection(DBusConnection *conn,
audio->path = g_strdup(path);
audio->r_features = features;
audio->mic_pending = -1;
+   audio->sp_pending = -1;
ofono_emulator_set_data(em, audio,
(ofono_destroy_func)free_audio_management);
 
ofono_emulator_add_handler(em, "+NREC", emulator_nrec_cb, audio, NULL);
ofono_emulator_add_handler(em, "+VGM", emulator_vgm_cb, audio, NULL);
+   ofono_emulator_add_handler(em, "+VGS", emulator_vgs_cb, audio, NULL);
 
audio->watch = g_dbus_add_signal_watch(conn, NULL, path,
BLUEZ_TRANSPORT_INTERFACE,
-- 
1.7.9.5

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v6 09/12] hfp_ag: Add AT+VGM support

2012-08-01 Thread Frédéric Danis
---
 plugins/hfp_ag.c |   74 ++
 1 file changed, 74 insertions(+)

diff --git a/plugins/hfp_ag.c b/plugins/hfp_ag.c
index 6821500..f865208 100644
--- a/plugins/hfp_ag.c
+++ b/plugins/hfp_ag.c
@@ -54,6 +54,8 @@ struct bt_audio {
guint16 r_features;
DBusPendingCall *call;
guint watch;
+   int mic_gain;
+   int mic_pending;
 };
 
 static guint modemwatch_id;
@@ -179,6 +181,39 @@ fail:
};
 }
 
+static void emulator_vgm_cb(struct ofono_emulator *em,
+   struct ofono_emulator_request *req, void *userdata)
+{
+   struct bt_audio *audio = userdata;
+   struct ofono_error result;
+   int val;
+   dbus_uint16_t dbus_val;
+
+   switch (ofono_emulator_request_get_type(req)) {
+   case OFONO_EMULATOR_REQUEST_TYPE_SET:
+   if (!ofono_emulator_request_next_number(req, &val))
+   goto fail;
+
+   if (val < 0 && val > 15)
+   goto fail;
+
+   if (audio->mic_pending != -1)
+   ofono_error("Receiving AT+VGM while processing one");
+
+   audio->mic_pending = val;
+   dbus_val = val;
+   audio_transport_set_property(audio, "InputGain",
+   DBUS_TYPE_UINT16, &dbus_val);
+   break;
+
+   default:
+fail:
+   result.error = 0;
+   result.type = OFONO_ERROR_TYPE_FAILURE;
+   ofono_emulator_send_final(em, &result);
+   };
+}
+
 static gboolean audio_property_changed(DBusConnection *connection,
DBusMessage *message, void *user_data)
 {
@@ -214,6 +249,43 @@ static gboolean audio_property_changed(DBusConnection 
*connection,
 
sprintf(buf, "+BSIR: %d", value);
ofono_emulator_send_unsolicited(audio->em, buf);
+   } else if (g_str_equal(property, "InputGain") == TRUE) {
+   DBusMessageIter variant;
+   dbus_uint16_t dbus_val;
+   int value;
+
+   if (!(audio->r_features & HFP_HF_FEATURE_REMOTE_VOLUME_CONTROL))
+   return TRUE;
+
+   if (!dbus_message_iter_next(&iter))
+   return TRUE;
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+   return TRUE;
+
+   dbus_message_iter_recurse(&iter, &variant);
+
+   if (dbus_message_iter_get_arg_type(&variant) !=
+   DBUS_TYPE_UINT16)
+   return TRUE;
+
+   dbus_message_iter_get_basic(&variant, &dbus_val);
+   value = dbus_val;
+
+   /* Send unsolicited +VGM only if :
+*   - the value has changed
+*   - and this is not a side effect of AT+VGM
+* But, if we receive a value change while waiting for another
+* pending change, we may have to send +VGM for other changes
+* (multiple AT+VGM received) to keep mic gain in sync
+*/
+   if (audio->mic_pending != value && audio->mic_gain != value) {
+   sprintf(buf, "+VGM: %d", value);
+   ofono_emulator_send_unsolicited(audio->em, buf);
+   audio->mic_pending = -1;
+   } else if (audio->mic_pending == value)
+   audio->mic_pending = -1;
+   audio->mic_gain = value;
}
 
return TRUE;
@@ -275,10 +347,12 @@ static DBusMessage 
*hfp_ag_agent_new_connection(DBusConnection *conn,
audio->em = em;
audio->path = g_strdup(path);
audio->r_features = features;
+   audio->mic_pending = -1;
ofono_emulator_set_data(em, audio,
(ofono_destroy_func)free_audio_management);
 
ofono_emulator_add_handler(em, "+NREC", emulator_nrec_cb, audio, NULL);
+   ofono_emulator_add_handler(em, "+VGM", emulator_vgm_cb, audio, NULL);
 
audio->watch = g_dbus_add_signal_watch(conn, NULL, path,
BLUEZ_TRANSPORT_INTERFACE,
-- 
1.7.9.5

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v6 08/12] hfp_ag: Add +BSIR support

2012-08-01 Thread Frédéric Danis
---
 plugins/hfp_ag.c |   52 
 1 file changed, 52 insertions(+)

diff --git a/plugins/hfp_ag.c b/plugins/hfp_ag.c
index 342f959..6821500 100644
--- a/plugins/hfp_ag.c
+++ b/plugins/hfp_ag.c
@@ -38,6 +38,7 @@
 #define AGENT_PATH "/hfp_ag"
 #define VERSION_1_5 0x0105
 #define FEATURES   (HFP_AG_FEATURE_3WAY | HFP_AG_FEATURE_ECNR | \
+   HFP_AG_FEATURE_IN_BAND_RING_TONE | \
HFP_AG_FEATURE_REJECT_CALL | \
HFP_AG_FEATURE_ENHANCED_CALL_STATUS | \
HFP_AG_FEATURE_ENHANCED_CALL_CONTROL | \
@@ -52,6 +53,7 @@ struct bt_audio {
char *path;
guint16 r_features;
DBusPendingCall *call;
+   guint watch;
 };
 
 static guint modemwatch_id;
@@ -177,8 +179,50 @@ fail:
};
 }
 
+static gboolean audio_property_changed(DBusConnection *connection,
+   DBusMessage *message, void *user_data)
+{
+   struct bt_audio *audio = user_data;
+   const char *property;
+   char buf[10];
+   DBusMessageIter iter;
+
+   dbus_message_iter_init(message, &iter);
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+   return FALSE;
+
+   dbus_message_iter_get_basic(&iter, &property);
+
+   if (g_str_equal(property, "InbandRingtone") == TRUE) {
+   DBusMessageIter variant;
+   gboolean value;
+
+   if (!dbus_message_iter_next(&iter))
+   return TRUE;
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+   return TRUE;
+
+   dbus_message_iter_recurse(&iter, &variant);
+
+   if (dbus_message_iter_get_arg_type(&variant) !=
+   DBUS_TYPE_BOOLEAN)
+   return TRUE;
+
+   dbus_message_iter_get_basic(&variant, &value);
+
+   sprintf(buf, "+BSIR: %d", value);
+   ofono_emulator_send_unsolicited(audio->em, buf);
+   }
+
+   return TRUE;
+}
+
 static void free_audio_management(struct bt_audio *audio)
 {
+   DBusConnection *connection = ofono_dbus_get_connection();
+
DBG("");
 
if (audio == NULL)
@@ -187,6 +231,8 @@ static void free_audio_management(struct bt_audio *audio)
if (audio->call)
dbus_pending_call_cancel(audio->call);
 
+   g_dbus_remove_watch(connection, audio->watch);
+
g_free(audio->path);
g_free(audio);
 }
@@ -234,6 +280,12 @@ static DBusMessage 
*hfp_ag_agent_new_connection(DBusConnection *conn,
 
ofono_emulator_add_handler(em, "+NREC", emulator_nrec_cb, audio, NULL);
 
+   audio->watch = g_dbus_add_signal_watch(conn, NULL, path,
+   BLUEZ_TRANSPORT_INTERFACE,
+   "PropertyChanged",
+   audio_property_changed,
+   audio, NULL);
+
return dbus_message_new_method_return(msg);
 }
 
-- 
1.7.9.5

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v6 07/12] hfp_ag: Add AT+NREC support

2012-08-01 Thread Frédéric Danis
---
 plugins/hfp_ag.c |  153 +-
 1 file changed, 152 insertions(+), 1 deletion(-)

diff --git a/plugins/hfp_ag.c b/plugins/hfp_ag.c
index 2652f3f..342f959 100644
--- a/plugins/hfp_ag.c
+++ b/plugins/hfp_ag.c
@@ -37,7 +37,8 @@
 
 #define AGENT_PATH "/hfp_ag"
 #define VERSION_1_5 0x0105
-#define FEATURES   (HFP_AG_FEATURE_3WAY | HFP_AG_FEATURE_REJECT_CALL | \
+#define FEATURES   (HFP_AG_FEATURE_3WAY | HFP_AG_FEATURE_ECNR | \
+   HFP_AG_FEATURE_REJECT_CALL | \
HFP_AG_FEATURE_ENHANCED_CALL_STATUS | \
HFP_AG_FEATURE_ENHANCED_CALL_CONTROL | \
HFP_AG_FEATURE_EXTENDED_RES_CODE)
@@ -46,10 +47,150 @@
 #define DBUS_TYPE_UNIX_FD -1
 #endif
 
+struct bt_audio {
+   struct ofono_emulator *em;
+   char *path;
+   guint16 r_features;
+   DBusPendingCall *call;
+};
+
 static guint modemwatch_id;
 static GList *modems;
 static GHashTable *sim_hash = NULL;
 
+static void audio_transport_set_property_cb(DBusPendingCall *call,
+   gpointer user_data)
+{
+   struct bt_audio *audio = user_data;
+   DBusMessage *reply;
+   struct DBusError derr;
+   struct ofono_error result;
+
+   reply = dbus_pending_call_steal_reply(call);
+
+   dbus_error_init(&derr);
+
+   if (dbus_set_error_from_message(&derr, reply)) {
+   ofono_error("MediaTransport.SetProperties replied an error: " \
+   "%s, %s", derr.name, derr.message);
+   dbus_error_free(&derr);
+   result.type = OFONO_ERROR_TYPE_FAILURE;
+   } else
+   result.type = OFONO_ERROR_TYPE_NO_ERROR;
+
+   result.error = 0;
+   ofono_emulator_send_final(audio->em, &result);
+
+   dbus_message_unref(reply);
+
+   dbus_pending_call_unref(audio->call);
+   audio->call = NULL;
+}
+
+static void audio_transport_set_property(struct bt_audio *audio,
+   const char *name, int type, const void *value)
+{
+   DBusMessage *msg;
+   DBusMessageIter iter, var;
+   const char *str_type;
+   DBusConnection *connection;
+   struct ofono_error result;
+
+   if (audio->call != NULL)
+   goto fail;
+
+   if (audio->path == NULL)
+   goto fail;
+
+   switch (type) {
+   case DBUS_TYPE_BOOLEAN:
+   str_type = DBUS_TYPE_BOOLEAN_AS_STRING;
+   break;
+
+   case DBUS_TYPE_UINT16:
+   str_type = DBUS_TYPE_UINT16_AS_STRING;
+   break;
+
+   default:
+   goto fail;
+   }
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE, audio->path,
+   BLUEZ_TRANSPORT_INTERFACE, "SetProperty");
+   if (msg == NULL)
+   goto fail;
+
+   dbus_message_iter_init_append(msg, &iter);
+   dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
+
+   dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, str_type,
+   &var);
+   dbus_message_iter_append_basic(&var, type, value);
+   dbus_message_iter_close_container(&iter, &var);
+
+   connection = ofono_dbus_get_connection();
+
+   if (!dbus_connection_send_with_reply(connection, msg, &audio->call,
+   -1)) {
+   ofono_error("Sending SetProperty failed");
+   dbus_message_unref(msg);
+   goto fail;
+   }
+
+   dbus_pending_call_set_notify(audio->call,
+   audio_transport_set_property_cb,
+   audio, NULL);
+
+   dbus_message_unref(msg);
+   return;
+
+fail:
+   result.error = 0;
+   result.type = OFONO_ERROR_TYPE_FAILURE;
+   ofono_emulator_send_final(audio->em, &result);
+}
+
+static void emulator_nrec_cb(struct ofono_emulator *em,
+   struct ofono_emulator_request *req, void *userdata)
+{
+   struct bt_audio *audio = userdata;
+   struct ofono_error result;
+   int val;
+
+   switch (ofono_emulator_request_get_type(req)) {
+   case OFONO_EMULATOR_REQUEST_TYPE_SET:
+   if (!ofono_emulator_request_next_number(req, &val))
+   goto fail;
+
+   if (val != 0 && val != 1)
+   goto fail;
+
+   audio_transport_set_property(audio, "NREC", DBUS_TYPE_BOOLEAN,
+   &val);
+   break;
+
+   default:
+fail:
+   result.error = 0;
+   result.type = OFONO_ERROR_TYPE_FAILURE;
+   ofono_emulator_send_final(em, &result);
+   };
+}
+
+static void free_audio_management(struct bt_audio *audio)
+{
+   DBG("");
+
+   if (audio == 

[RFC v6 06/12] emulator: Add set/get data APIs

2012-08-01 Thread Frédéric Danis
---
 src/emulator.c |   17 +
 1 file changed, 17 insertions(+)

diff --git a/src/emulator.c b/src/emulator.c
index c3165eb..14a39f3 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -52,6 +52,8 @@ struct ofono_emulator {
gboolean clip;
gboolean ccwa;
int pns_id;
+   void *data;
+   ofono_destroy_func destroy;
 };
 
 struct indicator {
@@ -951,6 +953,9 @@ static void emulator_remove(struct ofono_atom *atom)
 
DBG("atom: %p", atom);
 
+   if (em->destroy)
+   em->destroy(em->data);
+
g_free(em);
 }
 
@@ -994,6 +999,18 @@ void ofono_emulator_remove(struct ofono_emulator *em)
__ofono_atom_free(em->atom);
 }
 
+void ofono_emulator_set_data(struct ofono_emulator *em, void *data,
+   ofono_destroy_func destroy)
+{
+   em->data = data;
+   em->destroy = destroy;
+}
+
+void *ofono_emulator_get_data(struct ofono_emulator *em)
+{
+   return em->data;
+}
+
 void ofono_emulator_send_final(struct ofono_emulator *em,
const struct ofono_error *final)
 {
-- 
1.7.9.5

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v6 05/12] include: Add set/get data APIs to emulator

2012-08-01 Thread Frédéric Danis
---
 include/emulator.h |5 +
 1 file changed, 5 insertions(+)

diff --git a/include/emulator.h b/include/emulator.h
index 5cd894b..6dc1938 100644
--- a/include/emulator.h
+++ b/include/emulator.h
@@ -74,6 +74,11 @@ void ofono_emulator_register(struct ofono_emulator *em, int 
fd);
 
 void ofono_emulator_remove(struct ofono_emulator *em);
 
+void ofono_emulator_set_data(struct ofono_emulator *em, void *data,
+   ofono_destroy_func destroy);
+
+void *ofono_emulator_get_data(struct ofono_emulator *em);
+
 void ofono_emulator_send_final(struct ofono_emulator *em,
const struct ofono_error *final);
 void ofono_emulator_send_unsolicited(struct ofono_emulator *em,
-- 
1.7.9.5

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v6 04/12] bluetooth: Add define for MediaTransport interface

2012-08-01 Thread Frédéric Danis
---
 plugins/bluetooth.h |1 +
 1 file changed, 1 insertion(+)

diff --git a/plugins/bluetooth.h b/plugins/bluetooth.h
index 6a2fbf0..ecc89c3 100644
--- a/plugins/bluetooth.h
+++ b/plugins/bluetooth.h
@@ -31,6 +31,7 @@
 #define BLUEZ_SERIAL_INTERFACE BLUEZ_SERVICE ".Serial"
 #defineBLUEZ_TELEPHONY_INTERFACE   BLUEZ_SERVICE ".Telephony"
 #defineBLUEZ_TELEPHONY_AGENT_INTERFACE BLUEZ_SERVICE ".TelephonyAgent"
+#defineBLUEZ_TRANSPORT_INTERFACE   BLUEZ_SERVICE ".MediaTransport"
 
 #define DBUS_TIMEOUT 15
 
-- 
1.7.9.5

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v6 03/12] hfp_ag: Update to org.bluez.Telephony interface

2012-08-01 Thread Frédéric Danis
Bluez moves agent registration from a per device interface to
a per adapter interface.
Update hfp_ag modem emulator to reflect this change.
---
 plugins/hfp_ag.c |  128 +-
 1 file changed, 58 insertions(+), 70 deletions(-)

diff --git a/plugins/hfp_ag.c b/plugins/hfp_ag.c
index c2d1d30..2652f3f 100644
--- a/plugins/hfp_ag.c
+++ b/plugins/hfp_ag.c
@@ -35,97 +35,85 @@
 
 #include "bluetooth.h"
 
-#define HFP_AG_CHANNEL 13
+#define AGENT_PATH "/hfp_ag"
+#define VERSION_1_5 0x0105
+#define FEATURES   (HFP_AG_FEATURE_3WAY | HFP_AG_FEATURE_REJECT_CALL | \
+   HFP_AG_FEATURE_ENHANCED_CALL_STATUS | \
+   HFP_AG_FEATURE_ENHANCED_CALL_CONTROL | \
+   HFP_AG_FEATURE_EXTENDED_RES_CODE)
+
+#ifndef DBUS_TYPE_UNIX_FD
+#define DBUS_TYPE_UNIX_FD -1
+#endif
 
-static struct server *server;
 static guint modemwatch_id;
 static GList *modems;
 static GHashTable *sim_hash = NULL;
 
-static const gchar *hfp_ag_record =
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"  \n"
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n";
-
-static void hfp_ag_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
+static DBusMessage *hfp_ag_agent_new_connection(DBusConnection *conn,
+   DBusMessage *msg, void *data)
 {
-   struct ofono_modem *modem;
-   struct ofono_emulator *em;
int fd;
+   const char *device;
+   const char *path = NULL;
+   guint16 version = 0;
+   guint16 features = 0;
+   struct ofono_emulator *em;
+   struct ofono_modem *modem;
 
-   DBG("");
+   fd = bluetooth_parse_newconnection_message(msg, &device, &version,
+   &features, &path);
+   if (fd < 0)
+   return __ofono_error_invalid_args(msg);
 
-   if (err) {
-   DBG("%s", err->message);
-   return;
-   }
+   DBG("New connection for %s (version 0x%04X, features 0x%02X, " \
+   "media transport path: %s)",
+   device, version, features, path);
 
/* Pick the first voicecall capable modem */
modem = modems->data;
if (modem == NULL)
-   return;
+   return __ofono_error_failed(msg);
 
DBG("Picked modem %p for emulator", modem);
 
em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_HFP);
if (em == NULL)
-   return;
-
-   fd = g_io_channel_unix_get_fd(io);
-   g_io_channel_set_close_on_unref(io, FALSE);
+   return __ofono_error_failed(msg);
 
ofono_emulator_register(em, fd);
+
+   return dbus_message_new_method_return(msg);
 }
 
+static DBusMessage *hfp_ag_agent_release(DBusConnection *conn,
+   DBusMessage *msg, void *data)
+{
+   DBG("");
+
+   return dbus_message_new_method_return(msg);
+}
+
+static const GDBusMethodTable agent_methods[] = {
+   { GDBUS_ASYNC_METHOD("NewConnection",
+   GDBUS_ARGS({ "fd", "h" },
+   { "property", "a{sv}" }),
+   NULL, hfp_ag_agent_new_connection) },
+   { GDBUS_METHOD("Release", NULL, NULL, hfp_ag_agent_release) },
+   { }
+};
+
 static void sim_state_watch(enum ofono_sim_state new_state, void *data)
 {
struct ofono_modem *modem = data;
 
if (new_state != OFONO_SIM_STATE_READY) {
+   if (modems == NULL)
+   return;
+
modems = g_list_remove(modems, modem);
-   if (modems == NULL && server != NULL) {
-   bluetooth_unregister_server(server);
-   server = NULL;
-   }
+   if (modems == NULL)
+   bluetooth_unregister_telephony_agent(AGENT_PATH);
 
return;
}
@@ -138,8 +126,9 @@ static void sim_state_watch(enum ofono_sim_state new_state, 
void *data)
if (modems->next != NULL)
return;
 
-   server = bluetooth_register_server(HFP_AG_CHANNEL, hfp_ag_record,
-   hfp_ag_connect_cb, NULL);
+   bluetooth_register_telephony_agent(AGENT_PATH, HFP_AG_UUID,
+   VERSION_1_5, FEATURES,
+   agent_methods, NULL, NULL);
 }
 
 static gboolean sim_watch_remove(gpointer key, gpointer value,
@@ -192,6 +181,9 @@ static void call_modemwatch(struct ofono_modem *modem, void 
*user)
 
 stati

[RFC v6 02/12] hfp_hf: Update to org.bluez.Telephony interface

2012-08-01 Thread Frédéric Danis
Bluez moves agent registration from a per device interface to
a per adapter interface.
Update hfp_hf modem to reflect this change.
---
 plugins/hfp_hf.c |  169 +-
 1 file changed, 65 insertions(+), 104 deletions(-)

diff --git a/plugins/hfp_hf.c b/plugins/hfp_hf.c
index 7c500e3..e618518 100644
--- a/plugins/hfp_hf.c
+++ b/plugins/hfp_hf.c
@@ -51,7 +51,7 @@
 
 #defineBLUEZ_GATEWAY_INTERFACE BLUEZ_SERVICE 
".HandsfreeGateway"
 
-#define HFP_AGENT_INTERFACE "org.bluez.HandsfreeAgent"
+#define HFP_AGENT_PATH "/hfp_hf"
 #define HFP_AGENT_ERROR_INTERFACE "org.bluez.Error"
 
 #ifndef DBUS_TYPE_UNIX_FD
@@ -66,7 +66,6 @@ struct hfp_data {
char *handsfree_path;
char *handsfree_address;
DBusMessage *slc_msg;
-   gboolean agent_registered;
DBusPendingCall *call;
 };
 
@@ -158,54 +157,6 @@ static int service_level_connection(struct ofono_modem 
*modem, int fd)
return -EINPROGRESS;
 }
 
-static DBusMessage *hfp_agent_new_connection(DBusConnection *conn,
-   DBusMessage *msg, void *data)
-{
-   int fd, err;
-   struct ofono_modem *modem = data;
-   struct hfp_data *hfp_data = ofono_modem_get_data(modem);
-   guint16 version;
-
-   if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UNIX_FD, &fd,
-   DBUS_TYPE_UINT16, &version, DBUS_TYPE_INVALID))
-   return __ofono_error_invalid_args(msg);
-
-   hfp_slc_info_init(&hfp_data->info, version);
-
-   err = service_level_connection(modem, fd);
-   if (err < 0 && err != -EINPROGRESS)
-   return __ofono_error_failed(msg);
-
-   hfp_data->slc_msg = msg;
-   dbus_message_ref(msg);
-
-   return NULL;
-}
-
-static DBusMessage *hfp_agent_release(DBusConnection *conn,
-   DBusMessage *msg, void *data)
-{
-   struct ofono_modem *modem = data;
-   struct hfp_data *hfp_data = ofono_modem_get_data(modem);
-   const char *obj_path = ofono_modem_get_path(modem);
-
-   g_dbus_unregister_interface(connection, obj_path, HFP_AGENT_INTERFACE);
-   hfp_data->agent_registered = FALSE;
-
-   g_hash_table_remove(modem_hash, hfp_data->handsfree_path);
-   ofono_modem_remove(modem);
-
-   return dbus_message_new_method_return(msg);
-}
-
-static const GDBusMethodTable agent_methods[] = {
-   { GDBUS_ASYNC_METHOD("NewConnection",
-   GDBUS_ARGS({ "fd", "h" }, { "version", "q" }),
-   NULL, hfp_agent_new_connection) },
-   { GDBUS_METHOD("Release", NULL, NULL, hfp_agent_release) },
-   { }
-};
-
 static int hfp_hf_probe(const char *device, const char *dev_addr,
const char *adapter_addr, const char *alias)
 {
@@ -297,76 +248,24 @@ static void hfp_hf_set_alias(const char *device, const 
char *alias)
ofono_modem_set_name(modem, alias);
 }
 
-static int hfp_register_ofono_handsfree(struct ofono_modem *modem)
-{
-   const char *obj_path = ofono_modem_get_path(modem);
-   struct hfp_data *data = ofono_modem_get_data(modem);
-   DBusMessage *msg;
-
-   DBG("Registering oFono Agent to bluetooth daemon");
-
-   msg = dbus_message_new_method_call(BLUEZ_SERVICE, data->handsfree_path,
-   BLUEZ_GATEWAY_INTERFACE, "RegisterAgent");
-   if (msg == NULL)
-   return -ENOMEM;
-
-   dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &obj_path,
-   DBUS_TYPE_INVALID);
-
-   g_dbus_send_message(connection, msg);
-   return 0;
-}
-
-static int hfp_unregister_ofono_handsfree(struct ofono_modem *modem)
-{
-   const char *obj_path = ofono_modem_get_path(modem);
-   struct hfp_data *data = ofono_modem_get_data(modem);
-   DBusMessage *msg;
-
-   DBG("Unregistering oFono Agent from bluetooth daemon");
-
-   msg = dbus_message_new_method_call(BLUEZ_SERVICE, data->handsfree_path,
-   BLUEZ_GATEWAY_INTERFACE, "UnregisterAgent");
-   if (msg == NULL)
-   return -ENOMEM;
-
-   dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &obj_path,
-   DBUS_TYPE_INVALID);
-
-   g_dbus_send_message(connection, msg);
-   return 0;
-}
-
 static int hfp_probe(struct ofono_modem *modem)
 {
-   const char *obj_path = ofono_modem_get_path(modem);
struct hfp_data *data = ofono_modem_get_data(modem);
 
if (data == NULL)
return -EINVAL;
 
-   g_dbus_register_interface(connection, obj_path, HFP_AGENT_INTERFACE,
-   agent_methods, NULL, NULL, modem, NULL);
-
-   data->agent_registered = TRUE;
-
-   if (hfp_register_ofono_handsfree(modem) != 0)
-   return -EINVAL;
-
return 0;
 }
 
 static void hfp_remove(struct ofono_modem *modem)
 {
struct

[RFC v6 01/12] bluetooth: Add org.bluez.Telephony helpers

2012-08-01 Thread Frédéric Danis
Add function to register/unregister Telephony agent to BlueZ
---
 plugins/bluetooth.c |  191 +++
 plugins/bluetooth.h |   13 
 2 files changed, 204 insertions(+)

diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index 5d28530..3e8291a 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -44,6 +44,7 @@ static GHashTable *uuid_hash = NULL;
 static GHashTable *adapter_address_hash = NULL;
 static gint bluetooth_refcount;
 static GSList *server_list = NULL;
+static GSList *telephony_list = NULL;
 static const char *adapter_any_name = "any";
 static char *adapter_any_path;
 
@@ -65,6 +66,13 @@ struct cb_data {
GIOChannel *io;
 };
 
+struct agent {
+   char *path;
+   char *uuid;
+   guint16 version;
+   guint16 features;
+};
+
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
char *buf, int size)
 {
@@ -146,6 +154,60 @@ fail:
return err;
 }
 
+static void register_telephony_agent(const char *path, const char *handle,
+   struct agent *agent)
+{
+   DBusMessage *msg;
+   DBusMessageIter iter, dict;
+
+   DBG("Registering oFono Agent for %s to %s", agent->uuid, path);
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE, path,
+   BLUEZ_TELEPHONY_INTERFACE, "RegisterAgent");
+   if (msg == NULL)
+   return;
+
+   dbus_message_iter_init_append(msg, &iter);
+
+   dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+   &agent->path);
+
+   dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+   DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+   DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+   DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+   ofono_dbus_dict_append(&dict, "UUID", DBUS_TYPE_STRING, &agent->uuid);
+
+   ofono_dbus_dict_append(&dict, "Version", DBUS_TYPE_UINT16,
+   &agent->version);
+   ofono_dbus_dict_append(&dict, "Features", DBUS_TYPE_UINT16,
+   &agent->features);
+
+   dbus_message_iter_close_container(&iter, &dict);
+
+   g_dbus_send_message(connection, msg);
+}
+
+static void unregister_telephony_agent(const char *path, const char *handle,
+   struct agent *agent)
+{
+   DBusMessage *msg;
+
+   DBG("Unregistering oFono Agent for %s from %s", agent->uuid, path);
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE, path,
+   BLUEZ_TELEPHONY_INTERFACE,
+   "UnregisterAgent");
+   if (msg == NULL)
+   return;
+
+   dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &agent->path,
+   DBUS_TYPE_INVALID);
+
+   g_dbus_send_message(connection, msg);
+}
+
 typedef void (*PropertyHandler)(DBusMessageIter *iter, gpointer user_data);
 
 struct property_handler {
@@ -455,6 +517,9 @@ static void adapter_properties_cb(DBusPendingCall *call, 
gpointer user_data)
g_free, -1, DBUS_TYPE_INVALID);
}
 
+   for (l = telephony_list; l; l = l->next)
+   register_telephony_agent(path, NULL, l->data);
+
 done:
g_slist_free(device_list);
dbus_message_unref(reply);
@@ -985,5 +1050,131 @@ void bluetooth_unregister_server(struct server *server)
bluetooth_unref();
 }
 
+int bluetooth_parse_newconnection_message(DBusMessage *msg, const char 
**device,
+   guint16 *version, guint16 *features,
+   const char **transport_path)
+{
+   DBusMessageIter args, props;
+   int fd;
+   gboolean has_device = FALSE;
+
+   dbus_message_iter_init(msg, &args);
+
+   if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_UNIX_FD)
+   return -EINVAL;
+
+   dbus_message_iter_get_basic(&args, &fd);
+   dbus_message_iter_next(&args);
+
+   dbus_message_iter_recurse(&args, &props);
+   if (dbus_message_iter_get_arg_type(&props) != DBUS_TYPE_DICT_ENTRY)
+   return -EINVAL;
+
+   while (dbus_message_iter_get_arg_type(&props) == DBUS_TYPE_DICT_ENTRY) {
+   const char *key;
+   DBusMessageIter value, entry;
+   int var;
+
+   dbus_message_iter_recurse(&props, &entry);
+   dbus_message_iter_get_basic(&entry, &key);
+
+   dbus_message_iter_next(&entry);
+   dbus_message_iter_recurse(&entry, &value);
+
+   var = dbus_message_iter_get_arg_type(&value);
+   if (strcasecmp(key, "Device") == 0) {
+   if (var !

[RFC v6 00/12] Add org.bluez.Telephony interface

2012-08-01 Thread Frédéric Danis
Those patches integrates the future org.bluez.Telephony interface into
oFono for HFP HF, HFP AG and DUN GW plugins.

For HFP AG and DUN GW plugins, the bluetooth rfcomm server is replaced
by a Telephony Agent registered to org.bluez.Telephony.
For HFP HF plugin, RegisterAgent call of org.bluez.HandsfreeGateway is
replaced by the one of org.bluez.Telephony

Any comments appreciated.

Regards

PS: 
This version works with version 16 of "Add org.bluez.Telephony interface"
patches sent to BlueZ mailing list.

Since latest RFC :
- Patches 1, 2 and 3: remove UUID when parsing properties of NewConnection 
method
- Patch 3: update to use new GDBus
- Patches 7 to 10 (previously 5 to 8): move audio code from bluetooth.c to
  hfp_ag.c (dundee did not build if code is in bluetooth.c)
- Patch 9 (previously 7):
  - use right dbus_uint16_t variables when sending volume properties
  - changes volume management from MicrophoneGain to InputGain
- Patch 10 (previously 8):
  - use right dbus_uint16_t variables when sending volume properties
  - changes volume management from SpeakerGain to OutputGain

Frédéric Danis (12):
  bluetooth: Add org.bluez.Telephony helpers
  hfp_hf: Update to org.bluez.Telephony interface
  hfp_ag: Update to org.bluez.Telephony interface
  bluetooth: Add define for MediaTransport interface
  include: Add set/get data APIs to emulator
  emulator: Add set/get data APIs
  hfp_ag: Add AT+NREC support
  hfp_ag: Add +BSIR support
  hfp_ag: Add AT+VGM support
  hfp_ag: Add AT+VGS support
  emulator: Update supported features
  dun_gw: Update to org.bluez.Telephony interface

 include/emulator.h  |5 +
 plugins/bluetooth.c |  191 +
 plugins/bluetooth.h |   14 ++
 plugins/dun_gw.c|  119 ++---
 plugins/hfp_ag.c|  477 +++
 plugins/hfp_hf.c|  169 +++---
 src/emulator.c  |   19 ++
 7 files changed, 754 insertions(+), 240 deletions(-)

-- 
1.7.9.5

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v5 12/12] emulator: Update supported features

2012-04-26 Thread Frédéric Danis
Add ECNR (Echo Cancelation/Noise Reduction) and Inband Ringtone
capabilities to supported features (+BRSF event)
---
 src/emulator.c |2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index 2c40898..93f49e7 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -984,6 +984,8 @@ struct ofono_emulator *ofono_emulator_create(struct 
ofono_modem *modem,
 
em->type = type;
em->l_features |= HFP_AG_FEATURE_3WAY;
+   em->l_features |= HFP_AG_FEATURE_ECNR;
+   em->l_features |= HFP_AG_FEATURE_IN_BAND_RING_TONE;
em->l_features |= HFP_AG_FEATURE_REJECT_CALL;
em->l_features |= HFP_AG_FEATURE_ENHANCED_CALL_STATUS;
em->l_features |= HFP_AG_FEATURE_ENHANCED_CALL_CONTROL;
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v5 11/12] hfp_ag: Add media transport support

2012-04-26 Thread Frédéric Danis
---
 plugins/hfp_ag.c |8 +++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/plugins/hfp_ag.c b/plugins/hfp_ag.c
index ea9c112..9279745 100644
--- a/plugins/hfp_ag.c
+++ b/plugins/hfp_ag.c
@@ -37,7 +37,9 @@
 
 #define AGENT_PATH "/hfp_ag"
 #define VERSION_1_5 0x0105
-#define FEATURES   (HFP_AG_FEATURE_3WAY | HFP_AG_FEATURE_REJECT_CALL | \
+#define FEATURES   (HFP_AG_FEATURE_3WAY | HFP_AG_FEATURE_ECNR | \
+   HFP_AG_FEATURE_IN_BAND_RING_TONE | \
+   HFP_AG_FEATURE_REJECT_CALL | \
HFP_AG_FEATURE_ENHANCED_CALL_STATUS | \
HFP_AG_FEATURE_ENHANCED_CALL_CONTROL | \
HFP_AG_FEATURE_EXTENDED_RES_CODE)
@@ -60,6 +62,7 @@ static DBusMessage 
*hfp_ag_agent_new_connection(DBusConnection *conn,
guint16 features = 0;
struct ofono_emulator *em;
struct ofono_modem *modem;
+   struct bt_audio *audio;
 
fd = bluetooth_parse_newconnection_message(msg, &device, &uuid,
&version, &features, &path);
@@ -82,6 +85,9 @@ static DBusMessage 
*hfp_ag_agent_new_connection(DBusConnection *conn,
return __ofono_error_failed(msg);
 
ofono_emulator_register(em, fd);
+   audio = bluetooth_set_audio_management(em, path, features);
+   ofono_emulator_set_data(em, audio,
+   (ofono_destroy_func)bluetooth_free_audio_management);
 
return dbus_message_new_method_return(msg);
 }
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v5 10/12] emulator: add set/get data APIs

2012-04-26 Thread Frédéric Danis
---
 src/emulator.c |   17 +
 1 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index e7c7d41..2c40898 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -52,6 +52,8 @@ struct ofono_emulator {
gboolean clip;
gboolean ccwa;
int pns_id;
+   void *data;
+   ofono_destroy_func destroy;
 };
 
 struct indicator {
@@ -954,6 +956,9 @@ static void emulator_remove(struct ofono_atom *atom)
 
DBG("atom: %p", atom);
 
+   if (em->destroy)
+   em->destroy(em->data);
+
g_free(em);
 }
 
@@ -997,6 +1002,18 @@ void ofono_emulator_remove(struct ofono_emulator *em)
__ofono_atom_free(em->atom);
 }
 
+void ofono_emulator_set_data(struct ofono_emulator *em, void *data,
+   ofono_destroy_func destroy)
+{
+   em->data = data;
+   em->destroy = destroy;
+}
+
+void *ofono_emulator_get_data(struct ofono_emulator *em)
+{
+   return em->data;
+}
+
 void ofono_emulator_send_final(struct ofono_emulator *em,
const struct ofono_error *final)
 {
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v5 09/12] include: add set/get data APIs to emulator

2012-04-26 Thread Frédéric Danis
---
 include/emulator.h |5 +
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/include/emulator.h b/include/emulator.h
index 5cd894b..6dc1938 100644
--- a/include/emulator.h
+++ b/include/emulator.h
@@ -74,6 +74,11 @@ void ofono_emulator_register(struct ofono_emulator *em, int 
fd);
 
 void ofono_emulator_remove(struct ofono_emulator *em);
 
+void ofono_emulator_set_data(struct ofono_emulator *em, void *data,
+   ofono_destroy_func destroy);
+
+void *ofono_emulator_get_data(struct ofono_emulator *em);
+
 void ofono_emulator_send_final(struct ofono_emulator *em,
const struct ofono_error *final);
 void ofono_emulator_send_unsolicited(struct ofono_emulator *em,
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v5 08/12] bluetooth: Add AT+VGS support

2012-04-26 Thread Frédéric Danis
---
 plugins/bluetooth.c |   70 +++
 1 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index 07a73b3..65d7954 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -83,6 +83,8 @@ struct bt_audio {
guint watch;
int mic_gain;
int mic_pending;
+   int sp_gain;
+   int sp_pending;
 };
 
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
@@ -316,6 +318,37 @@ fail:
};
 }
 
+static void emulator_vgs_cb(struct ofono_emulator *em,
+   struct ofono_emulator_request *req, void *userdata)
+{
+   struct bt_audio *audio = userdata;
+   struct ofono_error result;
+   int val;
+
+   switch (ofono_emulator_request_get_type(req)) {
+   case OFONO_EMULATOR_REQUEST_TYPE_SET:
+   if (!ofono_emulator_request_next_number(req, &val))
+   goto fail;
+
+   if (val < 0 && val > 15)
+   goto fail;
+
+   if (audio->sp_pending != -1)
+   ofono_error("Receiving AT+VGS while processing one");
+
+   audio->sp_pending = val;
+   audio_transport_set_property(audio, "SpeakerGain",
+   DBUS_TYPE_UINT16, &val);
+   break;
+
+   default:
+fail:
+   result.error = 0;
+   result.type = OFONO_ERROR_TYPE_FAILURE;
+   ofono_emulator_send_final(em, &result);
+   };
+}
+
 static gboolean audio_property_changed(DBusConnection *connection,
DBusMessage *message, void *user_data)
 {
@@ -386,6 +419,41 @@ static gboolean audio_property_changed(DBusConnection 
*connection,
} else if (audio->mic_pending == value)
audio->mic_pending = -1;
audio->mic_gain = value;
+   } else if (g_str_equal(property, "SpeakerGain") == TRUE) {
+   DBusMessageIter variant;
+   int value;
+
+   if (!(audio->r_features & HFP_HF_FEATURE_REMOTE_VOLUME_CONTROL))
+   return TRUE;
+
+   if (!dbus_message_iter_next(&iter))
+   return TRUE;
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+   return TRUE;
+
+   dbus_message_iter_recurse(&iter, &variant);
+
+   if (dbus_message_iter_get_arg_type(&variant) !=
+   DBUS_TYPE_UINT16)
+   return TRUE;
+
+   dbus_message_iter_get_basic(&variant, &value);
+
+   /* Send unsolicited +VGS only if :
+*   - the value has changed
+*   - and this is not a side effect of AT+VGS
+* But, if we receive a value change while waiting for another
+* pending change, we may have to send +VGS for other changes
+* (multiple AT+VGS received) to keep speaker gain in sync
+*/
+   if (audio->sp_pending != value && audio->sp_gain != value) {
+   sprintf(buf, "+VGS: %d", value);
+   ofono_emulator_send_unsolicited(audio->em, buf);
+   audio->sp_pending = -1;
+   } else if (audio->sp_pending == value)
+   audio->sp_pending = -1;
+   audio->sp_gain = value;
}
 
return TRUE;
@@ -419,9 +487,11 @@ struct bt_audio *bluetooth_set_audio_management(void *em, 
const char *path,
audio->path = g_strdup(path);
audio->r_features = features;
audio->mic_pending = -1;
+   audio->sp_pending = -1;
 
ofono_emulator_add_handler(em, "+NREC", emulator_nrec_cb, audio, NULL);
ofono_emulator_add_handler(em, "+VGM", emulator_vgm_cb, audio, NULL);
+   ofono_emulator_add_handler(em, "+VGS", emulator_vgs_cb, audio, NULL);
 
audio->watch = g_dbus_add_signal_watch(connection, NULL, path,
BLUEZ_TRANSPORT_INTERFACE,
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v5 07/12] bluetooth: Add AT+VGM support

2012-04-26 Thread Frédéric Danis
---
 plugins/bluetooth.c |   70 +++
 1 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index 75a4f00..07a73b3 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -81,6 +81,8 @@ struct bt_audio {
guint16 r_features;
DBusPendingCall *call;
guint watch;
+   int mic_gain;
+   int mic_pending;
 };
 
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
@@ -283,6 +285,37 @@ fail:
};
 }
 
+static void emulator_vgm_cb(struct ofono_emulator *em,
+   struct ofono_emulator_request *req, void *userdata)
+{
+   struct bt_audio *audio = userdata;
+   struct ofono_error result;
+   int val;
+
+   switch (ofono_emulator_request_get_type(req)) {
+   case OFONO_EMULATOR_REQUEST_TYPE_SET:
+   if (!ofono_emulator_request_next_number(req, &val))
+   goto fail;
+
+   if (val < 0 && val > 15)
+   goto fail;
+
+   if (audio->mic_pending != -1)
+   ofono_error("Receiving AT+VGM while processing one");
+
+   audio->mic_pending = val;
+   audio_transport_set_property(audio, "MicrophoneGain",
+   DBUS_TYPE_UINT16, &val);
+   break;
+
+   default:
+fail:
+   result.error = 0;
+   result.type = OFONO_ERROR_TYPE_FAILURE;
+   ofono_emulator_send_final(em, &result);
+   };
+}
+
 static gboolean audio_property_changed(DBusConnection *connection,
DBusMessage *message, void *user_data)
 {
@@ -318,6 +351,41 @@ static gboolean audio_property_changed(DBusConnection 
*connection,
 
sprintf(buf, "+BSIR: %d", value);
ofono_emulator_send_unsolicited(audio->em, buf);
+   } else if (g_str_equal(property, "MicrophoneGain") == TRUE) {
+   DBusMessageIter variant;
+   int value;
+
+   if (!(audio->r_features & HFP_HF_FEATURE_REMOTE_VOLUME_CONTROL))
+   return TRUE;
+
+   if (!dbus_message_iter_next(&iter))
+   return TRUE;
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+   return TRUE;
+
+   dbus_message_iter_recurse(&iter, &variant);
+
+   if (dbus_message_iter_get_arg_type(&variant) !=
+   DBUS_TYPE_UINT16)
+   return TRUE;
+
+   dbus_message_iter_get_basic(&variant, &value);
+
+   /* Send unsolicited +VGM only if :
+*   - the value has changed
+*   - and this is not a side effect of AT+VGM
+* But, if we receive a value change while waiting for another
+* pending change, we may have to send +VGM for other changes
+* (multiple AT+VGM received) to keep mic gain in sync
+*/
+   if (audio->mic_pending != value && audio->mic_gain != value) {
+   sprintf(buf, "+VGM: %d", value);
+   ofono_emulator_send_unsolicited(audio->em, buf);
+   audio->mic_pending = -1;
+   } else if (audio->mic_pending == value)
+   audio->mic_pending = -1;
+   audio->mic_gain = value;
}
 
return TRUE;
@@ -350,8 +418,10 @@ struct bt_audio *bluetooth_set_audio_management(void *em, 
const char *path,
audio->em = em;
audio->path = g_strdup(path);
audio->r_features = features;
+   audio->mic_pending = -1;
 
ofono_emulator_add_handler(em, "+NREC", emulator_nrec_cb, audio, NULL);
+   ofono_emulator_add_handler(em, "+VGM", emulator_vgm_cb, audio, NULL);
 
audio->watch = g_dbus_add_signal_watch(connection, NULL, path,
BLUEZ_TRANSPORT_INTERFACE,
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v5 05/12] bluetooth: Add AT+NREC support

2012-04-26 Thread Frédéric Danis
---
 plugins/bluetooth.c |  159 +++
 1 files changed, 159 insertions(+), 0 deletions(-)

diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index 971e2c6..6624718 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -37,6 +37,8 @@
 #include 
 
 #include 
+#include 
+#include 
 #include "bluetooth.h"
 
 static DBusConnection *connection;
@@ -73,6 +75,13 @@ struct agent {
guint16 features;
 };
 
+struct bt_audio {
+   struct ofono_emulator *em;
+   char *path;
+   guint16 r_features;
+   DBusPendingCall *call;
+};
+
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
char *buf, int size)
 {
@@ -154,6 +163,156 @@ fail:
return err;
 }
 
+static void audio_transport_set_property_cb(DBusPendingCall *call,
+   gpointer user_data)
+{
+   struct bt_audio *audio = user_data;
+   DBusMessage *reply;
+   struct DBusError derr;
+   struct ofono_error result;
+
+   reply = dbus_pending_call_steal_reply(call);
+
+   dbus_error_init(&derr);
+
+   if (dbus_set_error_from_message(&derr, reply)) {
+   ofono_error("MediaTransport.SetProperties replied an error: " \
+   "%s, %s", derr.name, derr.message);
+   dbus_error_free(&derr);
+   result.type = OFONO_ERROR_TYPE_FAILURE;
+   } else
+   result.type = OFONO_ERROR_TYPE_NO_ERROR;
+
+   result.error = 0;
+   ofono_emulator_send_final(audio->em, &result);
+
+   dbus_message_unref(reply);
+
+   dbus_pending_call_unref(audio->call);
+   audio->call = NULL;
+}
+
+static void audio_transport_set_property(struct bt_audio *audio,
+   const char *name, int type, const void *value)
+{
+   DBusMessage *msg;
+   DBusMessageIter iter, var;
+   const char *str_type;
+   DBusConnection *connection;
+   struct ofono_error result;
+
+   if (audio->call != NULL)
+   goto fail;
+
+   if (audio->path == NULL)
+   goto fail;
+
+   switch (type) {
+   case DBUS_TYPE_BOOLEAN:
+   str_type = DBUS_TYPE_BOOLEAN_AS_STRING;
+   break;
+
+   case DBUS_TYPE_UINT16:
+   str_type = DBUS_TYPE_UINT16_AS_STRING;
+   break;
+
+   default:
+   goto fail;
+   }
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE, audio->path,
+   BLUEZ_TRANSPORT_INTERFACE, "SetProperty");
+   if (msg == NULL)
+   goto fail;
+
+   dbus_message_iter_init_append(msg, &iter);
+   dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
+
+   dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, str_type,
+   &var);
+   dbus_message_iter_append_basic(&var, type, value);
+   dbus_message_iter_close_container(&iter, &var);
+
+   connection = ofono_dbus_get_connection();
+
+   if (!dbus_connection_send_with_reply(connection, msg, &audio->call,
+   -1)) {
+   ofono_error("Sending SetProperty failed");
+   dbus_message_unref(msg);
+   goto fail;
+   }
+
+   dbus_pending_call_set_notify(audio->call,
+   audio_transport_set_property_cb,
+   audio, NULL);
+
+   dbus_message_unref(msg);
+   return;
+
+fail:
+   result.error = 0;
+   result.type = OFONO_ERROR_TYPE_FAILURE;
+   ofono_emulator_send_final(audio->em, &result);
+}
+
+static void emulator_nrec_cb(struct ofono_emulator *em,
+   struct ofono_emulator_request *req, void *userdata)
+{
+   struct bt_audio *audio = userdata;
+   struct ofono_error result;
+   int val;
+
+   switch (ofono_emulator_request_get_type(req)) {
+   case OFONO_EMULATOR_REQUEST_TYPE_SET:
+   if (!ofono_emulator_request_next_number(req, &val))
+   goto fail;
+
+   if (val != 0 && val != 1)
+   goto fail;
+
+   audio_transport_set_property(audio, "NREC", DBUS_TYPE_BOOLEAN,
+   &val);
+   break;
+
+   default:
+fail:
+   result.error = 0;
+   result.type = OFONO_ERROR_TYPE_FAILURE;
+   ofono_emulator_send_final(em, &result);
+   };
+}
+
+void bluetooth_free_audio_management(struct bt_audio *audio)
+{
+   DBG("");
+
+   if (audio == NULL)
+   return;
+
+   if (audio->call)
+   dbus_pending_call_cancel(audio->call);
+
+   g_free(audio->path);
+   g_free(audio);
+}
+
+struct bt_audio *bluetooth_set_audio_management(void *e

[RFC v5 06/12] bluetooth: Add +BSIR support

2012-04-26 Thread Frédéric Danis
---
 plugins/bluetooth.c |   49 +
 1 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index 6624718..75a4f00 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -80,6 +80,7 @@ struct bt_audio {
char *path;
guint16 r_features;
DBusPendingCall *call;
+   guint watch;
 };
 
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
@@ -282,6 +283,46 @@ fail:
};
 }
 
+static gboolean audio_property_changed(DBusConnection *connection,
+   DBusMessage *message, void *user_data)
+{
+   struct bt_audio *audio = user_data;
+   const char *property;
+   char buf[10];
+   DBusMessageIter iter;
+
+   dbus_message_iter_init(message, &iter);
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+   return FALSE;
+
+   dbus_message_iter_get_basic(&iter, &property);
+
+   if (g_str_equal(property, "InbandRingtone") == TRUE) {
+   DBusMessageIter variant;
+   gboolean value;
+
+   if (!dbus_message_iter_next(&iter))
+   return TRUE;
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+   return TRUE;
+
+   dbus_message_iter_recurse(&iter, &variant);
+
+   if (dbus_message_iter_get_arg_type(&variant) !=
+   DBUS_TYPE_BOOLEAN)
+   return TRUE;
+
+   dbus_message_iter_get_basic(&variant, &value);
+
+   sprintf(buf, "+BSIR: %d", value);
+   ofono_emulator_send_unsolicited(audio->em, buf);
+   }
+
+   return TRUE;
+}
+
 void bluetooth_free_audio_management(struct bt_audio *audio)
 {
DBG("");
@@ -292,6 +333,8 @@ void bluetooth_free_audio_management(struct bt_audio *audio)
if (audio->call)
dbus_pending_call_cancel(audio->call);
 
+   g_dbus_remove_watch(connection, audio->watch);
+
g_free(audio->path);
g_free(audio);
 }
@@ -310,6 +353,12 @@ struct bt_audio *bluetooth_set_audio_management(void *em, 
const char *path,
 
ofono_emulator_add_handler(em, "+NREC", emulator_nrec_cb, audio, NULL);
 
+   audio->watch = g_dbus_add_signal_watch(connection, NULL, path,
+   BLUEZ_TRANSPORT_INTERFACE,
+   "PropertyChanged",
+   audio_property_changed,
+   audio, NULL);
+
return audio;
 }
 
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v5 04/12] bluetooth: Add audio APIs for HFP AG

2012-04-26 Thread Frédéric Danis
---
 plugins/bluetooth.h |5 +
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/plugins/bluetooth.h b/plugins/bluetooth.h
index f81fc99..87563e7 100644
--- a/plugins/bluetooth.h
+++ b/plugins/bluetooth.h
@@ -30,6 +30,7 @@
 #defineBLUEZ_SERVICE_INTERFACE BLUEZ_SERVICE ".Service"
 #defineBLUEZ_TELEPHONY_INTERFACE   BLUEZ_SERVICE ".Telephony"
 #defineBLUEZ_TELEPHONY_AGENT_INTERFACE BLUEZ_SERVICE ".TelephonyAgent"
+#defineBLUEZ_TRANSPORT_INTERFACE   BLUEZ_SERVICE ".MediaTransport"
 
 #define DBUS_TIMEOUT 15
 
@@ -59,6 +60,7 @@ struct bluetooth_sap_driver {
 };
 
 struct server;
+struct bt_audio;
 
 typedef void (*ConnectFunc)(GIOChannel *io, GError *err, gpointer user_data);
 
@@ -85,6 +87,9 @@ int bluetooth_sap_client_register(struct bluetooth_sap_driver 
*sap,
struct ofono_modem *modem);
 void bluetooth_sap_client_unregister(struct ofono_modem *modem);
 
+struct bt_audio *bluetooth_set_audio_management(void *em, const char *path,
+   guint16 features);
+void bluetooth_free_audio_management(struct bt_audio *audio);
 int bluetooth_parse_newconnection_message(DBusMessage *msg, const char 
**device,
const char **uuid, guint16 *version,
guint16 *features,
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v5 03/12] hfp_ag: Update to org.bluez.Telephony interface

2012-04-26 Thread Frédéric Danis
Bluez moves agent registration from a per device interface to
a per adapter interface.
Update hfp_ag modem emulator to reflect this change.
---
 plugins/hfp_ag.c |  126 --
 1 files changed, 56 insertions(+), 70 deletions(-)

diff --git a/plugins/hfp_ag.c b/plugins/hfp_ag.c
index c2d1d30..ea9c112 100644
--- a/plugins/hfp_ag.c
+++ b/plugins/hfp_ag.c
@@ -35,97 +35,83 @@
 
 #include "bluetooth.h"
 
-#define HFP_AG_CHANNEL 13
+#define AGENT_PATH "/hfp_ag"
+#define VERSION_1_5 0x0105
+#define FEATURES   (HFP_AG_FEATURE_3WAY | HFP_AG_FEATURE_REJECT_CALL | \
+   HFP_AG_FEATURE_ENHANCED_CALL_STATUS | \
+   HFP_AG_FEATURE_ENHANCED_CALL_CONTROL | \
+   HFP_AG_FEATURE_EXTENDED_RES_CODE)
+
+#ifndef DBUS_TYPE_UNIX_FD
+#define DBUS_TYPE_UNIX_FD -1
+#endif
 
-static struct server *server;
 static guint modemwatch_id;
 static GList *modems;
 static GHashTable *sim_hash = NULL;
 
-static const gchar *hfp_ag_record =
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"  \n"
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n";
-
-static void hfp_ag_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
+static DBusMessage *hfp_ag_agent_new_connection(DBusConnection *conn,
+   DBusMessage *msg, void *data)
 {
-   struct ofono_modem *modem;
-   struct ofono_emulator *em;
int fd;
+   const char *device, *uuid;
+   const char *path = NULL;
+   guint16 version = 0;
+   guint16 features = 0;
+   struct ofono_emulator *em;
+   struct ofono_modem *modem;
 
-   DBG("");
+   fd = bluetooth_parse_newconnection_message(msg, &device, &uuid,
+   &version, &features, &path);
+   if (fd < 0)
+   return __ofono_error_invalid_args(msg);
 
-   if (err) {
-   DBG("%s", err->message);
-   return;
-   }
+   DBG("New connection for %s on %s (version 0x%04X, features 0x%02X, " \
+   "media transport path: %s)",
+   device, uuid, version, features, path);
 
/* Pick the first voicecall capable modem */
modem = modems->data;
if (modem == NULL)
-   return;
+   return __ofono_error_failed(msg);
 
DBG("Picked modem %p for emulator", modem);
 
em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_HFP);
if (em == NULL)
-   return;
-
-   fd = g_io_channel_unix_get_fd(io);
-   g_io_channel_set_close_on_unref(io, FALSE);
+   return __ofono_error_failed(msg);
 
ofono_emulator_register(em, fd);
+
+   return dbus_message_new_method_return(msg);
 }
 
+static DBusMessage *hfp_ag_agent_release(DBusConnection *conn,
+   DBusMessage *msg, void *data)
+{
+   DBG("");
+
+   return dbus_message_new_method_return(msg);
+}
+
+static GDBusMethodTable agent_methods[] = {
+   { "NewConnection", "ha{sv}", "", hfp_ag_agent_new_connection,
+   G_DBUS_METHOD_FLAG_ASYNC },
+   { "Release", "", "", hfp_ag_agent_release },
+   { NULL, NULL, NULL, NULL }
+};
+
 static void sim_state_watch(enum ofono_sim_state new_state, void *data)
 {
struct ofono_modem *modem = data;
 
if (new_state != OFONO_SIM_STATE_READY) {
+   if (modems == NULL)
+   return;
+
modems = g_list_remove(modems, modem);
-   if (modems == NULL && server != NULL) {
-   bluetooth_unregister_server(server);
-   server = NULL;
-   }
+   if (modems == NULL)
+   bluetooth_unregister_telephony_agent(AGENT_PATH);
 
return;
}
@@ -138,8 +124,9 @@ static void sim_state_watch(enum ofono_sim_state new_state, 
void *data)
if (modems->next != NULL)
return;
 
-   server = bluetooth_register_server(HFP_AG_CHANNEL, hfp_ag_record,
-   hfp_ag_connect_cb, NULL);
+   bluetooth_register_telephony_agent(AGENT_PATH, HFP_AG_UUID,
+   VERSION_1_5, FEATURES,
+   agent_methods, NULL, NULL);
 }
 
 static gboolean sim_watch_remove(gpointer key, gpointer value,
@@ -192,6 +179,9 @@ static void call_modemwatch(struct ofono_modem *modem, void 
*user)
 
 static int hfp_ag_init(void)
 {
+   if (DBUS_TYPE_UNIX_FD < 0)
+   return -EBADF;
+
sim_hash = g_

[RFC v5 02/12] hfp_hf: Update to org.bluez.Telephony interface

2012-04-26 Thread Frédéric Danis
Bluez moves agent registration from a per device interface to
a per adapter interface.
Update hfp_hf modem to reflect this change.
---
 plugins/hfp_hf.c |  166 -
 1 files changed, 63 insertions(+), 103 deletions(-)

diff --git a/plugins/hfp_hf.c b/plugins/hfp_hf.c
index c11525e..7c3747b 100644
--- a/plugins/hfp_hf.c
+++ b/plugins/hfp_hf.c
@@ -51,7 +51,7 @@
 
 #defineBLUEZ_GATEWAY_INTERFACE BLUEZ_SERVICE 
".HandsfreeGateway"
 
-#define HFP_AGENT_INTERFACE "org.bluez.HandsfreeAgent"
+#define HFP_AGENT_PATH "/hfp_hf"
 #define HFP_AGENT_ERROR_INTERFACE "org.bluez.Error"
 
 #ifndef DBUS_TYPE_UNIX_FD
@@ -66,7 +66,6 @@ struct hfp_data {
char *handsfree_path;
char *handsfree_address;
DBusMessage *slc_msg;
-   gboolean agent_registered;
DBusPendingCall *call;
 };
 
@@ -158,53 +157,6 @@ static int service_level_connection(struct ofono_modem 
*modem, int fd)
return -EINPROGRESS;
 }
 
-static DBusMessage *hfp_agent_new_connection(DBusConnection *conn,
-   DBusMessage *msg, void *data)
-{
-   int fd, err;
-   struct ofono_modem *modem = data;
-   struct hfp_data *hfp_data = ofono_modem_get_data(modem);
-   guint16 version;
-
-   if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UNIX_FD, &fd,
-   DBUS_TYPE_UINT16, &version, DBUS_TYPE_INVALID))
-   return __ofono_error_invalid_args(msg);
-
-   hfp_slc_info_init(&hfp_data->info, version);
-
-   err = service_level_connection(modem, fd);
-   if (err < 0 && err != -EINPROGRESS)
-   return __ofono_error_failed(msg);
-
-   hfp_data->slc_msg = msg;
-   dbus_message_ref(msg);
-
-   return NULL;
-}
-
-static DBusMessage *hfp_agent_release(DBusConnection *conn,
-   DBusMessage *msg, void *data)
-{
-   struct ofono_modem *modem = data;
-   struct hfp_data *hfp_data = ofono_modem_get_data(modem);
-   const char *obj_path = ofono_modem_get_path(modem);
-
-   g_dbus_unregister_interface(connection, obj_path, HFP_AGENT_INTERFACE);
-   hfp_data->agent_registered = FALSE;
-
-   g_hash_table_remove(modem_hash, hfp_data->handsfree_path);
-   ofono_modem_remove(modem);
-
-   return dbus_message_new_method_return(msg);
-}
-
-static GDBusMethodTable agent_methods[] = {
-   { "NewConnection", "hq", "", hfp_agent_new_connection,
-   G_DBUS_METHOD_FLAG_ASYNC },
-   { "Release", "", "", hfp_agent_release },
-   { NULL, NULL, NULL, NULL }
-};
-
 static int hfp_hf_probe(const char *device, const char *dev_addr,
const char *adapter_addr, const char *alias)
 {
@@ -296,76 +248,24 @@ static void hfp_hf_set_alias(const char *device, const 
char *alias)
ofono_modem_set_name(modem, alias);
 }
 
-static int hfp_register_ofono_handsfree(struct ofono_modem *modem)
-{
-   const char *obj_path = ofono_modem_get_path(modem);
-   struct hfp_data *data = ofono_modem_get_data(modem);
-   DBusMessage *msg;
-
-   DBG("Registering oFono Agent to bluetooth daemon");
-
-   msg = dbus_message_new_method_call(BLUEZ_SERVICE, data->handsfree_path,
-   BLUEZ_GATEWAY_INTERFACE, "RegisterAgent");
-   if (msg == NULL)
-   return -ENOMEM;
-
-   dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &obj_path,
-   DBUS_TYPE_INVALID);
-
-   g_dbus_send_message(connection, msg);
-   return 0;
-}
-
-static int hfp_unregister_ofono_handsfree(struct ofono_modem *modem)
-{
-   const char *obj_path = ofono_modem_get_path(modem);
-   struct hfp_data *data = ofono_modem_get_data(modem);
-   DBusMessage *msg;
-
-   DBG("Unregistering oFono Agent from bluetooth daemon");
-
-   msg = dbus_message_new_method_call(BLUEZ_SERVICE, data->handsfree_path,
-   BLUEZ_GATEWAY_INTERFACE, "UnregisterAgent");
-   if (msg == NULL)
-   return -ENOMEM;
-
-   dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &obj_path,
-   DBUS_TYPE_INVALID);
-
-   g_dbus_send_message(connection, msg);
-   return 0;
-}
-
 static int hfp_probe(struct ofono_modem *modem)
 {
-   const char *obj_path = ofono_modem_get_path(modem);
struct hfp_data *data = ofono_modem_get_data(modem);
 
if (data == NULL)
return -EINVAL;
 
-   g_dbus_register_interface(connection, obj_path, HFP_AGENT_INTERFACE,
-   agent_methods, NULL, NULL, modem, NULL);
-
-   data->agent_registered = TRUE;
-
-   if (hfp_register_ofono_handsfree(modem) != 0)
-   return -EINVAL;
-
return 0;
 }
 
 static void hfp_remove(struct ofono_modem *modem)
 {
struct hfp_data *data = ofono_modem_get_data(modem);
-   const char *obj_path = ofono_mo

[RFC v5 01/12] bluetooth: Add org.bluez.Telephony helpers

2012-04-26 Thread Frédéric Danis
Add function to register/unregister Telephony agent to BlueZ
---
 plugins/bluetooth.c |  198 +++
 plugins/bluetooth.h |   14 
 2 files changed, 212 insertions(+), 0 deletions(-)

diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index dbf79eb..971e2c6 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -44,6 +44,7 @@ static GHashTable *uuid_hash = NULL;
 static GHashTable *adapter_address_hash = NULL;
 static gint bluetooth_refcount;
 static GSList *server_list = NULL;
+static GSList *telephony_list = NULL;
 static const char *adapter_any_name = "any";
 static char *adapter_any_path;
 
@@ -65,6 +66,13 @@ struct cb_data {
GIOChannel *io;
 };
 
+struct agent {
+   char *path;
+   char *uuid;
+   guint16 version;
+   guint16 features;
+};
+
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
char *buf, int size)
 {
@@ -146,6 +154,60 @@ fail:
return err;
 }
 
+static void register_telephony_agent(const char *path, const char *handle,
+   struct agent *agent)
+{
+   DBusMessage *msg;
+   DBusMessageIter iter, dict;
+
+   DBG("Registering oFono Agent for %s to %s", agent->uuid, path);
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE, path,
+   BLUEZ_TELEPHONY_INTERFACE, "RegisterAgent");
+   if (msg == NULL)
+   return;
+
+   dbus_message_iter_init_append(msg, &iter);
+
+   dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+   &agent->path);
+
+   dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+   DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+   DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+   DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+   ofono_dbus_dict_append(&dict, "UUID", DBUS_TYPE_STRING, &agent->uuid);
+
+   ofono_dbus_dict_append(&dict, "Version", DBUS_TYPE_UINT16,
+   &agent->version);
+   ofono_dbus_dict_append(&dict, "Features", DBUS_TYPE_UINT16,
+   &agent->features);
+
+   dbus_message_iter_close_container(&iter, &dict);
+
+   g_dbus_send_message(connection, msg);
+}
+
+static void unregister_telephony_agent(const char *path, const char *handle,
+   struct agent *agent)
+{
+   DBusMessage *msg;
+
+   DBG("Unregistering oFono Agent for %s from %s", agent->uuid, path);
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE, path,
+   BLUEZ_TELEPHONY_INTERFACE,
+   "UnregisterAgent");
+   if (msg == NULL)
+   return;
+
+   dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &agent->path,
+   DBUS_TYPE_INVALID);
+
+   g_dbus_send_message(connection, msg);
+}
+
 typedef void (*PropertyHandler)(DBusMessageIter *iter, gpointer user_data);
 
 struct property_handler {
@@ -455,6 +517,9 @@ static void adapter_properties_cb(DBusPendingCall *call, 
gpointer user_data)
g_free, -1, DBUS_TYPE_INVALID);
}
 
+   for (l = telephony_list; l; l = l->next)
+   register_telephony_agent(path, NULL, l->data);
+
 done:
g_slist_free(device_list);
dbus_message_unref(reply);
@@ -982,5 +1047,138 @@ void bluetooth_unregister_server(struct server *server)
bluetooth_unref();
 }
 
+int bluetooth_parse_newconnection_message(DBusMessage *msg, const char 
**device,
+   const char **uuid, guint16 *version,
+   guint16 *features,
+   const char **transport_path)
+{
+   DBusMessageIter args, props;
+   int fd;
+   gboolean has_device = FALSE;
+   gboolean has_uuid = FALSE;
+
+   dbus_message_iter_init(msg, &args);
+
+   if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_UNIX_FD)
+   return -EINVAL;
+
+   dbus_message_iter_get_basic(&args, &fd);
+   dbus_message_iter_next(&args);
+
+   dbus_message_iter_recurse(&args, &props);
+   if (dbus_message_iter_get_arg_type(&props) != DBUS_TYPE_DICT_ENTRY)
+   return -EINVAL;
+
+   while (dbus_message_iter_get_arg_type(&props) == DBUS_TYPE_DICT_ENTRY) {
+   const char *key;
+   DBusMessageIter value, entry;
+   int var;
+
+   dbus_message_iter_recurse(&props, &entry);
+   dbus_message_iter_get_basic(&entry, &key);
+
+   dbus_message_iter_next(&entry);
+   dbus_message_iter_recurse(&entry, &value);
+
+   var = dbus_message_iter

[RFC v5 00/12] org.bluez.Telephony interface integration

2012-04-26 Thread Frédéric Danis
Those patches integrates the future org.bluez.Telephony interface into
oFono for HFP HF and HFP AG plugins.

For HFP AG plugin, the bluetooth rfcomm server is replaced by a
Telephony Agent registered to org.bluez.Telephony.
For HFP HF plugin, RegisterAgent call of org.bluez.HandsfreeGateway is
replaced by the one of org.bluez.Telephony

Since latest RFC :
- Patch 4
  forward declare the structute used in bluetooth plug-in by
  bluetooth_set_audio_management() and bluetooth_free_audio_management()
- Patch 5
  Fix DBus pending call management in case of HFP emulator unregistration
  Remove ofono_emulator_remove_handler() calls
- Patches 9 and 10
  Add APIs to set/get data for emulator atom
- Patch 11 (previously 9)
  Remove IO watch as data destroyer associated to emulator will be called
  on atom removal

RFC v4:
- Patche 1
  move agent registration from adapter_added() to adapter_properties_cb()
- Patches 4 to 10:
  Rewrote support of AT+NREC, AT+VGM, +VGM, AT+VGS, +VGS and +BSIR into
  bluetooth plugin


Frédéric Danis (12):
  bluetooth: Add org.bluez.Telephony helpers
  hfp_hf: Update to org.bluez.Telephony interface
  hfp_ag: Update to org.bluez.Telephony interface
  bluetooth: Add audio APIs for HFP AG
  bluetooth: Add AT+NREC support
  bluetooth: Add +BSIR support
  bluetooth: Add AT+VGM support
  bluetooth: Add AT+VGS support
  include: add set/get data APIs to emulator
  emulator: add set/get data APIs
  hfp_ag: Add media transport support
  emulator: Update supported features

 include/emulator.h  |5 +
 plugins/bluetooth.c |  546 +++
 plugins/bluetooth.h |   19 ++
 plugins/hfp_ag.c|  132 ++---
 plugins/hfp_hf.c|  166 ++--
 src/emulator.c  |   19 ++
 6 files changed, 714 insertions(+), 173 deletions(-)

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v4 10/10] emulator: Update supported features

2012-04-06 Thread Frédéric Danis
Add ECNR (Echo Cancelation/Noise Reduction) and Inband Ringtone
capabilities to supported features (+BRSF event)
---
 src/emulator.c |2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index e7c7d41..371e96c 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -979,6 +979,8 @@ struct ofono_emulator *ofono_emulator_create(struct 
ofono_modem *modem,
 
em->type = type;
em->l_features |= HFP_AG_FEATURE_3WAY;
+   em->l_features |= HFP_AG_FEATURE_ECNR;
+   em->l_features |= HFP_AG_FEATURE_IN_BAND_RING_TONE;
em->l_features |= HFP_AG_FEATURE_REJECT_CALL;
em->l_features |= HFP_AG_FEATURE_ENHANCED_CALL_STATUS;
em->l_features |= HFP_AG_FEATURE_ENHANCED_CALL_CONTROL;
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v4 08/10] bluetooth: Add AT+VGS support

2012-04-06 Thread Frédéric Danis
---
 plugins/bluetooth.c |   71 +++
 1 files changed, 71 insertions(+), 0 deletions(-)

diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index 3560440..107c197 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -81,6 +81,8 @@ struct hfp_data {
guint watch;
int mic_gain;
int mic_pending;
+   int sp_gain;
+   int sp_pending;
 };
 
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
@@ -301,6 +303,37 @@ fail:
};
 }
 
+static void emulator_vgs_cb(struct ofono_emulator *em,
+   struct ofono_emulator_request *req, void *userdata)
+{
+   struct hfp_data *hfp = userdata;
+   struct ofono_error result;
+   int val;
+
+   switch (ofono_emulator_request_get_type(req)) {
+   case OFONO_EMULATOR_REQUEST_TYPE_SET:
+   if (!ofono_emulator_request_next_number(req, &val))
+   goto fail;
+
+   if (val < 0 && val > 15)
+   goto fail;
+
+   if (hfp->sp_pending != -1)
+   ofono_error("Receiving AT+VGS while processing one");
+
+   hfp->sp_pending = val;
+   audio_transport_set_property(hfp, "SpeakerGain",
+   DBUS_TYPE_UINT16, &val);
+   break;
+
+   default:
+fail:
+   result.error = 0;
+   result.type = OFONO_ERROR_TYPE_FAILURE;
+   ofono_emulator_send_final(em, &result);
+   };
+}
+
 static gboolean audio_property_changed(DBusConnection *connection,
DBusMessage *message, void *user_data)
 {
@@ -371,6 +404,41 @@ static gboolean audio_property_changed(DBusConnection 
*connection,
} else if (hfp->mic_pending == value)
hfp->mic_pending = -1;
hfp->mic_gain = value;
+   } else if (g_str_equal(property, "SpeakerGain") == TRUE) {
+   DBusMessageIter variant;
+   int value;
+
+   if (!(hfp->r_features & HFP_HF_FEATURE_REMOTE_VOLUME_CONTROL))
+   return TRUE;
+
+   if (!dbus_message_iter_next(&iter))
+   return TRUE;
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+   return TRUE;
+
+   dbus_message_iter_recurse(&iter, &variant);
+
+   if (dbus_message_iter_get_arg_type(&variant) !=
+   DBUS_TYPE_UINT16)
+   return TRUE;
+
+   dbus_message_iter_get_basic(&variant, &value);
+
+   /* Send unsolicited +VGS only if :
+*   - the value has changed
+*   - and this is not a side effect of AT+VGS
+* But, if we receive a value change while waiting for another
+* pending change, we may have to send +VGS for other changes
+* (multiple AT+VGS received) to keep speaker gain in sync
+*/
+   if (hfp->sp_pending != value && hfp->sp_gain != value) {
+   sprintf(buf, "+VGS: %d", value);
+   ofono_emulator_send_unsolicited(hfp->em, buf);
+   hfp->sp_pending = -1;
+   } else if (hfp->sp_pending == value)
+   hfp->sp_pending = -1;
+   hfp->sp_gain = value;
}
 
return TRUE;
@@ -384,6 +452,7 @@ void bluetooth_free_audio_management(void *data)
 
ofono_emulator_remove_handler(hfp->em, "+NREC");
ofono_emulator_remove_handler(hfp->em, "+VGM");
+   ofono_emulator_remove_handler(hfp->em, "+VGS");
 
g_dbus_remove_watch(connection, hfp->watch);
 
@@ -403,9 +472,11 @@ void *bluetooth_set_audio_management(void *em, const char 
*path,
hfp->path = g_strdup(path);
hfp->r_features = features;
hfp->mic_pending = -1;
+   hfp->sp_pending = -1;
 
ofono_emulator_add_handler(em, "+NREC", emulator_nrec_cb, hfp, NULL);
ofono_emulator_add_handler(em, "+VGM", emulator_vgm_cb, hfp, NULL);
+   ofono_emulator_add_handler(em, "+VGS", emulator_vgs_cb, hfp, NULL);
 
hfp->watch = g_dbus_add_signal_watch(connection, NULL, path,
BLUEZ_TRANSPORT_INTERFACE,
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v4 09/10] hfp_ag: Add media transport support

2012-04-06 Thread Frédéric Danis
---
 plugins/hfp_ag.c |   19 ++-
 1 files changed, 18 insertions(+), 1 deletions(-)

diff --git a/plugins/hfp_ag.c b/plugins/hfp_ag.c
index ea9c112..8500bff 100644
--- a/plugins/hfp_ag.c
+++ b/plugins/hfp_ag.c
@@ -37,7 +37,9 @@
 
 #define AGENT_PATH "/hfp_ag"
 #define VERSION_1_5 0x0105
-#define FEATURES   (HFP_AG_FEATURE_3WAY | HFP_AG_FEATURE_REJECT_CALL | \
+#define FEATURES   (HFP_AG_FEATURE_3WAY | HFP_AG_FEATURE_ECNR | \
+   HFP_AG_FEATURE_IN_BAND_RING_TONE | \
+   HFP_AG_FEATURE_REJECT_CALL | \
HFP_AG_FEATURE_ENHANCED_CALL_STATUS | \
HFP_AG_FEATURE_ENHANCED_CALL_CONTROL | \
HFP_AG_FEATURE_EXTENDED_RES_CODE)
@@ -50,6 +52,13 @@ static guint modemwatch_id;
 static GList *modems;
 static GHashTable *sim_hash = NULL;
 
+static gboolean client_event(GIOChannel *chan, GIOCondition cond, gpointer 
data)
+{
+   bluetooth_free_audio_management(data);
+
+   return FALSE;
+}
+
 static DBusMessage *hfp_ag_agent_new_connection(DBusConnection *conn,
DBusMessage *msg, void *data)
 {
@@ -60,6 +69,8 @@ static DBusMessage 
*hfp_ag_agent_new_connection(DBusConnection *conn,
guint16 features = 0;
struct ofono_emulator *em;
struct ofono_modem *modem;
+   void *audio;
+   GIOChannel *io;
 
fd = bluetooth_parse_newconnection_message(msg, &device, &uuid,
&version, &features, &path);
@@ -82,6 +93,12 @@ static DBusMessage 
*hfp_ag_agent_new_connection(DBusConnection *conn,
return __ofono_error_failed(msg);
 
ofono_emulator_register(em, fd);
+   audio = bluetooth_set_audio_management(em, path, features);
+
+   io = g_io_channel_unix_new(fd);
+   g_io_add_watch_full(io, G_PRIORITY_HIGH,
+   G_IO_HUP | G_IO_ERR | G_IO_NVAL, client_event,
+   audio, NULL);
 
return dbus_message_new_method_return(msg);
 }
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v4 07/10] bluetooth: Add AT+VGM support

2012-04-06 Thread Frédéric Danis
---
 plugins/bluetooth.c |   71 +++
 1 files changed, 71 insertions(+), 0 deletions(-)

diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index b90852d..3560440 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -79,6 +79,8 @@ struct hfp_data {
char *path;
guint16 r_features;
guint watch;
+   int mic_gain;
+   int mic_pending;
 };
 
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
@@ -268,6 +270,37 @@ fail:
};
 }
 
+static void emulator_vgm_cb(struct ofono_emulator *em,
+   struct ofono_emulator_request *req, void *userdata)
+{
+   struct hfp_data *hfp = userdata;
+   struct ofono_error result;
+   int val;
+
+   switch (ofono_emulator_request_get_type(req)) {
+   case OFONO_EMULATOR_REQUEST_TYPE_SET:
+   if (!ofono_emulator_request_next_number(req, &val))
+   goto fail;
+
+   if (val < 0 && val > 15)
+   goto fail;
+
+   if (hfp->mic_pending != -1)
+   ofono_error("Receiving AT+VGM while processing one");
+
+   hfp->mic_pending = val;
+   audio_transport_set_property(hfp, "MicrophoneGain",
+   DBUS_TYPE_UINT16, &val);
+   break;
+
+   default:
+fail:
+   result.error = 0;
+   result.type = OFONO_ERROR_TYPE_FAILURE;
+   ofono_emulator_send_final(em, &result);
+   };
+}
+
 static gboolean audio_property_changed(DBusConnection *connection,
DBusMessage *message, void *user_data)
 {
@@ -303,6 +336,41 @@ static gboolean audio_property_changed(DBusConnection 
*connection,
 
sprintf(buf, "+BSIR: %d", value);
ofono_emulator_send_unsolicited(hfp->em, buf);
+   } else if (g_str_equal(property, "MicrophoneGain") == TRUE) {
+   DBusMessageIter variant;
+   int value;
+
+   if (!(hfp->r_features & HFP_HF_FEATURE_REMOTE_VOLUME_CONTROL))
+   return TRUE;
+
+   if (!dbus_message_iter_next(&iter))
+   return TRUE;
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+   return TRUE;
+
+   dbus_message_iter_recurse(&iter, &variant);
+
+   if (dbus_message_iter_get_arg_type(&variant) !=
+   DBUS_TYPE_UINT16)
+   return TRUE;
+
+   dbus_message_iter_get_basic(&variant, &value);
+
+   /* Send unsolicited +VGM only if :
+*   - the value has changed
+*   - and this is not a side effect of AT+VGM
+* But, if we receive a value change while waiting for another
+* pending change, we may have to send +VGM for other changes
+* (multiple AT+VGM received) to keep mic gain in sync
+*/
+   if (hfp->mic_pending != value && hfp->mic_gain != value) {
+   sprintf(buf, "+VGM: %d", value);
+   ofono_emulator_send_unsolicited(hfp->em, buf);
+   hfp->mic_pending = -1;
+   } else if (hfp->mic_pending == value)
+   hfp->mic_pending = -1;
+   hfp->mic_gain = value;
}
 
return TRUE;
@@ -315,6 +383,7 @@ void bluetooth_free_audio_management(void *data)
DBG("");
 
ofono_emulator_remove_handler(hfp->em, "+NREC");
+   ofono_emulator_remove_handler(hfp->em, "+VGM");
 
g_dbus_remove_watch(connection, hfp->watch);
 
@@ -333,8 +402,10 @@ void *bluetooth_set_audio_management(void *em, const char 
*path,
hfp->em = em;
hfp->path = g_strdup(path);
hfp->r_features = features;
+   hfp->mic_pending = -1;
 
ofono_emulator_add_handler(em, "+NREC", emulator_nrec_cb, hfp, NULL);
+   ofono_emulator_add_handler(em, "+VGM", emulator_vgm_cb, hfp, NULL);
 
hfp->watch = g_dbus_add_signal_watch(connection, NULL, path,
BLUEZ_TRANSPORT_INTERFACE,
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v4 06/10] bluetooth: Add +BSIR support

2012-04-06 Thread Frédéric Danis
---
 plugins/bluetooth.c |   49 +
 1 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index b6328bc..b90852d 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -78,6 +78,7 @@ struct hfp_data {
struct ofono_emulator *em;
char *path;
guint16 r_features;
+   guint watch;
 };
 
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
@@ -267,6 +268,46 @@ fail:
};
 }
 
+static gboolean audio_property_changed(DBusConnection *connection,
+   DBusMessage *message, void *user_data)
+{
+   struct hfp_data *hfp = user_data;
+   const char *property;
+   char buf[10];
+   DBusMessageIter iter;
+
+   dbus_message_iter_init(message, &iter);
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+   return FALSE;
+
+   dbus_message_iter_get_basic(&iter, &property);
+
+   if (g_str_equal(property, "InbandRingtone") == TRUE) {
+   DBusMessageIter variant;
+   gboolean value;
+
+   if (!dbus_message_iter_next(&iter))
+   return TRUE;
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+   return TRUE;
+
+   dbus_message_iter_recurse(&iter, &variant);
+
+   if (dbus_message_iter_get_arg_type(&variant) !=
+   DBUS_TYPE_BOOLEAN)
+   return TRUE;
+
+   dbus_message_iter_get_basic(&variant, &value);
+
+   sprintf(buf, "+BSIR: %d", value);
+   ofono_emulator_send_unsolicited(hfp->em, buf);
+   }
+
+   return TRUE;
+}
+
 void bluetooth_free_audio_management(void *data)
 {
struct hfp_data *hfp = data;
@@ -275,6 +316,8 @@ void bluetooth_free_audio_management(void *data)
 
ofono_emulator_remove_handler(hfp->em, "+NREC");
 
+   g_dbus_remove_watch(connection, hfp->watch);
+
g_free(hfp->path);
g_free(hfp);
 }
@@ -293,6 +336,12 @@ void *bluetooth_set_audio_management(void *em, const char 
*path,
 
ofono_emulator_add_handler(em, "+NREC", emulator_nrec_cb, hfp, NULL);
 
+   hfp->watch = g_dbus_add_signal_watch(connection, NULL, path,
+   BLUEZ_TRANSPORT_INTERFACE,
+   "PropertyChanged",
+   audio_property_changed,
+   hfp, NULL);
+
return hfp;
 }
 
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v4 05/10] bluetooth: Add AT+NREC support

2012-04-06 Thread Frédéric Danis
---
 plugins/bluetooth.c |  142 +++
 1 files changed, 142 insertions(+), 0 deletions(-)

diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index 971e2c6..b6328bc 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -38,6 +38,7 @@
 
 #include 
 #include "bluetooth.h"
+#include "ofono.h"
 
 static DBusConnection *connection;
 static GHashTable *uuid_hash = NULL;
@@ -73,6 +74,12 @@ struct agent {
guint16 features;
 };
 
+struct hfp_data {
+   struct ofono_emulator *em;
+   char *path;
+   guint16 r_features;
+};
+
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
char *buf, int size)
 {
@@ -154,6 +161,141 @@ fail:
return err;
 }
 
+static void audio_transport_set_property_cb(DBusPendingCall *call,
+   gpointer user_data)
+{
+   struct ofono_emulator *em = user_data;
+   DBusMessage *reply;
+   struct DBusError derr;
+   struct ofono_error result;
+
+   reply = dbus_pending_call_steal_reply(call);
+
+   dbus_error_init(&derr);
+
+   if (dbus_set_error_from_message(&derr, reply)) {
+   ofono_error("MediaTransport.SetProperties replied an error: " \
+   "%s, %s", derr.name, derr.message);
+   dbus_error_free(&derr);
+   result.type = OFONO_ERROR_TYPE_FAILURE;
+   } else
+   result.type = OFONO_ERROR_TYPE_NO_ERROR;
+
+   result.error = 0;
+   ofono_emulator_send_final(em, &result);
+
+   dbus_message_unref(reply);
+}
+
+static void audio_transport_set_property(struct hfp_data *hfp, const char 
*name,
+   int type, const void *value)
+{
+   DBusMessage *msg;
+   DBusMessageIter iter, var;
+   const char *str_type;
+   DBusConnection *connection;
+   DBusPendingCall *c;
+
+   if (hfp->path == NULL)
+   return;
+
+   switch (type) {
+   case DBUS_TYPE_BOOLEAN:
+   str_type = DBUS_TYPE_BOOLEAN_AS_STRING;
+   break;
+
+   case DBUS_TYPE_UINT16:
+   str_type = DBUS_TYPE_UINT16_AS_STRING;
+   break;
+
+   default:
+   return;
+   }
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE, hfp->path,
+   BLUEZ_TRANSPORT_INTERFACE, "SetProperty");
+   if (msg == NULL)
+   return;
+
+   dbus_message_iter_init_append(msg, &iter);
+   dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
+
+   dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, str_type,
+   &var);
+   dbus_message_iter_append_basic(&var, type, value);
+   dbus_message_iter_close_container(&iter, &var);
+
+   connection = ofono_dbus_get_connection();
+
+   if (!dbus_connection_send_with_reply(connection, msg, &c, -1)) {
+   ofono_error("Sending SetProperty failed");
+   goto fail;
+   }
+
+   dbus_pending_call_set_notify(c, audio_transport_set_property_cb,
+   hfp->em, NULL);
+   dbus_pending_call_unref(c);
+
+fail:
+   dbus_message_unref(msg);
+}
+
+static void emulator_nrec_cb(struct ofono_emulator *em,
+   struct ofono_emulator_request *req, void *userdata)
+{
+   struct hfp_data *hfp = userdata;
+   struct ofono_error result;
+   int val;
+
+   switch (ofono_emulator_request_get_type(req)) {
+   case OFONO_EMULATOR_REQUEST_TYPE_SET:
+   if (!ofono_emulator_request_next_number(req, &val))
+   goto fail;
+
+   if (val != 0 && val != 1)
+   goto fail;
+
+   audio_transport_set_property(hfp, "NREC", DBUS_TYPE_BOOLEAN,
+   &val);
+   break;
+
+   default:
+fail:
+   result.error = 0;
+   result.type = OFONO_ERROR_TYPE_FAILURE;
+   ofono_emulator_send_final(em, &result);
+   };
+}
+
+void bluetooth_free_audio_management(void *data)
+{
+   struct hfp_data *hfp = data;
+
+   DBG("");
+
+   ofono_emulator_remove_handler(hfp->em, "+NREC");
+
+   g_free(hfp->path);
+   g_free(hfp);
+}
+
+void *bluetooth_set_audio_management(void *em, const char *path,
+   guint16 features)
+{
+   struct hfp_data *hfp;
+
+   DBG("");
+
+   hfp = g_new0(struct hfp_data, 1);
+   hfp->em = em;
+   hfp->path = g_strdup(path);
+   hfp->r_features = features;
+
+   ofono_emulator_add_handler(em, "+NREC", emulator_nrec_cb, hfp, NULL);
+
+   return hfp;
+}
+
 static void register_telephony_agent(const char *path, const char *handle,
   

[RFC v4 04/10] bluetooth: Add audio APIs for HFP AG

2012-04-06 Thread Frédéric Danis
---
 plugins/bluetooth.h |4 
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/plugins/bluetooth.h b/plugins/bluetooth.h
index f81fc99..41ce112 100644
--- a/plugins/bluetooth.h
+++ b/plugins/bluetooth.h
@@ -30,6 +30,7 @@
 #defineBLUEZ_SERVICE_INTERFACE BLUEZ_SERVICE ".Service"
 #defineBLUEZ_TELEPHONY_INTERFACE   BLUEZ_SERVICE ".Telephony"
 #defineBLUEZ_TELEPHONY_AGENT_INTERFACE BLUEZ_SERVICE ".TelephonyAgent"
+#defineBLUEZ_TRANSPORT_INTERFACE   BLUEZ_SERVICE ".MediaTransport"
 
 #define DBUS_TIMEOUT 15
 
@@ -85,6 +86,9 @@ int bluetooth_sap_client_register(struct bluetooth_sap_driver 
*sap,
struct ofono_modem *modem);
 void bluetooth_sap_client_unregister(struct ofono_modem *modem);
 
+void *bluetooth_set_audio_management(void *em, const char *path,
+   guint16 features);
+void bluetooth_free_audio_management(void *data);
 int bluetooth_parse_newconnection_message(DBusMessage *msg, const char 
**device,
const char **uuid, guint16 *version,
guint16 *features,
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v4 03/10] hfp_ag: Update to org.bluez.Telephony interface

2012-04-06 Thread Frédéric Danis
Bluez moves agent registration from a per device interface to
a per adapter interface.
Update hfp_ag modem emulator to reflect this change.
---
 plugins/hfp_ag.c |  126 --
 1 files changed, 56 insertions(+), 70 deletions(-)

diff --git a/plugins/hfp_ag.c b/plugins/hfp_ag.c
index c2d1d30..ea9c112 100644
--- a/plugins/hfp_ag.c
+++ b/plugins/hfp_ag.c
@@ -35,97 +35,83 @@
 
 #include "bluetooth.h"
 
-#define HFP_AG_CHANNEL 13
+#define AGENT_PATH "/hfp_ag"
+#define VERSION_1_5 0x0105
+#define FEATURES   (HFP_AG_FEATURE_3WAY | HFP_AG_FEATURE_REJECT_CALL | \
+   HFP_AG_FEATURE_ENHANCED_CALL_STATUS | \
+   HFP_AG_FEATURE_ENHANCED_CALL_CONTROL | \
+   HFP_AG_FEATURE_EXTENDED_RES_CODE)
+
+#ifndef DBUS_TYPE_UNIX_FD
+#define DBUS_TYPE_UNIX_FD -1
+#endif
 
-static struct server *server;
 static guint modemwatch_id;
 static GList *modems;
 static GHashTable *sim_hash = NULL;
 
-static const gchar *hfp_ag_record =
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"  \n"
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n";
-
-static void hfp_ag_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
+static DBusMessage *hfp_ag_agent_new_connection(DBusConnection *conn,
+   DBusMessage *msg, void *data)
 {
-   struct ofono_modem *modem;
-   struct ofono_emulator *em;
int fd;
+   const char *device, *uuid;
+   const char *path = NULL;
+   guint16 version = 0;
+   guint16 features = 0;
+   struct ofono_emulator *em;
+   struct ofono_modem *modem;
 
-   DBG("");
+   fd = bluetooth_parse_newconnection_message(msg, &device, &uuid,
+   &version, &features, &path);
+   if (fd < 0)
+   return __ofono_error_invalid_args(msg);
 
-   if (err) {
-   DBG("%s", err->message);
-   return;
-   }
+   DBG("New connection for %s on %s (version 0x%04X, features 0x%02X, " \
+   "media transport path: %s)",
+   device, uuid, version, features, path);
 
/* Pick the first voicecall capable modem */
modem = modems->data;
if (modem == NULL)
-   return;
+   return __ofono_error_failed(msg);
 
DBG("Picked modem %p for emulator", modem);
 
em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_HFP);
if (em == NULL)
-   return;
-
-   fd = g_io_channel_unix_get_fd(io);
-   g_io_channel_set_close_on_unref(io, FALSE);
+   return __ofono_error_failed(msg);
 
ofono_emulator_register(em, fd);
+
+   return dbus_message_new_method_return(msg);
 }
 
+static DBusMessage *hfp_ag_agent_release(DBusConnection *conn,
+   DBusMessage *msg, void *data)
+{
+   DBG("");
+
+   return dbus_message_new_method_return(msg);
+}
+
+static GDBusMethodTable agent_methods[] = {
+   { "NewConnection", "ha{sv}", "", hfp_ag_agent_new_connection,
+   G_DBUS_METHOD_FLAG_ASYNC },
+   { "Release", "", "", hfp_ag_agent_release },
+   { NULL, NULL, NULL, NULL }
+};
+
 static void sim_state_watch(enum ofono_sim_state new_state, void *data)
 {
struct ofono_modem *modem = data;
 
if (new_state != OFONO_SIM_STATE_READY) {
+   if (modems == NULL)
+   return;
+
modems = g_list_remove(modems, modem);
-   if (modems == NULL && server != NULL) {
-   bluetooth_unregister_server(server);
-   server = NULL;
-   }
+   if (modems == NULL)
+   bluetooth_unregister_telephony_agent(AGENT_PATH);
 
return;
}
@@ -138,8 +124,9 @@ static void sim_state_watch(enum ofono_sim_state new_state, 
void *data)
if (modems->next != NULL)
return;
 
-   server = bluetooth_register_server(HFP_AG_CHANNEL, hfp_ag_record,
-   hfp_ag_connect_cb, NULL);
+   bluetooth_register_telephony_agent(AGENT_PATH, HFP_AG_UUID,
+   VERSION_1_5, FEATURES,
+   agent_methods, NULL, NULL);
 }
 
 static gboolean sim_watch_remove(gpointer key, gpointer value,
@@ -192,6 +179,9 @@ static void call_modemwatch(struct ofono_modem *modem, void 
*user)
 
 static int hfp_ag_init(void)
 {
+   if (DBUS_TYPE_UNIX_FD < 0)
+   return -EBADF;
+
sim_hash = g_

[RFC v4 02/10] hfp_hf: Update to org.bluez.Telephony interface

2012-04-06 Thread Frédéric Danis
Bluez moves agent registration from a per device interface to
a per adapter interface.
Update hfp_hf modem to reflect this change.
---
 plugins/hfp_hf.c |  165 -
 1 files changed, 62 insertions(+), 103 deletions(-)

diff --git a/plugins/hfp_hf.c b/plugins/hfp_hf.c
index 48a734a..7c3747b 100644
--- a/plugins/hfp_hf.c
+++ b/plugins/hfp_hf.c
@@ -51,7 +51,7 @@
 
 #defineBLUEZ_GATEWAY_INTERFACE BLUEZ_SERVICE 
".HandsfreeGateway"
 
-#define HFP_AGENT_INTERFACE "org.bluez.HandsfreeAgent"
+#define HFP_AGENT_PATH "/hfp_hf"
 #define HFP_AGENT_ERROR_INTERFACE "org.bluez.Error"
 
 #ifndef DBUS_TYPE_UNIX_FD
@@ -66,7 +66,6 @@ struct hfp_data {
char *handsfree_path;
char *handsfree_address;
DBusMessage *slc_msg;
-   gboolean agent_registered;
DBusPendingCall *call;
 };
 
@@ -158,52 +157,6 @@ static int service_level_connection(struct ofono_modem 
*modem, int fd)
return -EINPROGRESS;
 }
 
-static DBusMessage *hfp_agent_new_connection(DBusConnection *conn,
-   DBusMessage *msg, void *data)
-{
-   int fd, err;
-   struct ofono_modem *modem = data;
-   struct hfp_data *hfp_data = ofono_modem_get_data(modem);
-   guint16 version;
-
-   if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UNIX_FD, &fd,
-   DBUS_TYPE_UINT16, &version, DBUS_TYPE_INVALID))
-   return __ofono_error_invalid_args(msg);
-
-   hfp_slc_info_init(&hfp_data->info, version);
-
-   err = service_level_connection(modem, fd);
-   if (err < 0 && err != -EINPROGRESS)
-   return __ofono_error_failed(msg);
-
-   hfp_data->slc_msg = msg;
-   dbus_message_ref(msg);
-
-   return NULL;
-}
-
-static DBusMessage *hfp_agent_release(DBusConnection *conn,
-   DBusMessage *msg, void *data)
-{
-   struct ofono_modem *modem = data;
-   struct hfp_data *hfp_data = ofono_modem_get_data(modem);
-   const char *obj_path = ofono_modem_get_path(modem);
-
-   g_dbus_unregister_interface(connection, obj_path, HFP_AGENT_INTERFACE);
-   hfp_data->agent_registered = FALSE;
-
-   ofono_modem_remove(modem);
-
-   return dbus_message_new_method_return(msg);
-}
-
-static GDBusMethodTable agent_methods[] = {
-   { "NewConnection", "hq", "", hfp_agent_new_connection,
-   G_DBUS_METHOD_FLAG_ASYNC },
-   { "Release", "", "", hfp_agent_release },
-   { NULL, NULL, NULL, NULL }
-};
-
 static int hfp_hf_probe(const char *device, const char *dev_addr,
const char *adapter_addr, const char *alias)
 {
@@ -295,77 +248,23 @@ static void hfp_hf_set_alias(const char *device, const 
char *alias)
ofono_modem_set_name(modem, alias);
 }
 
-static int hfp_register_ofono_handsfree(struct ofono_modem *modem)
-{
-   const char *obj_path = ofono_modem_get_path(modem);
-   struct hfp_data *data = ofono_modem_get_data(modem);
-   DBusMessage *msg;
-
-   DBG("Registering oFono Agent to bluetooth daemon");
-
-   msg = dbus_message_new_method_call(BLUEZ_SERVICE, data->handsfree_path,
-   BLUEZ_GATEWAY_INTERFACE, "RegisterAgent");
-   if (msg == NULL)
-   return -ENOMEM;
-
-   dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &obj_path,
-   DBUS_TYPE_INVALID);
-
-   g_dbus_send_message(connection, msg);
-   return 0;
-}
-
-static int hfp_unregister_ofono_handsfree(struct ofono_modem *modem)
-{
-   const char *obj_path = ofono_modem_get_path(modem);
-   struct hfp_data *data = ofono_modem_get_data(modem);
-   DBusMessage *msg;
-
-   DBG("Unregistering oFono Agent from bluetooth daemon");
-
-   msg = dbus_message_new_method_call(BLUEZ_SERVICE, data->handsfree_path,
-   BLUEZ_GATEWAY_INTERFACE, "UnregisterAgent");
-   if (msg == NULL)
-   return -ENOMEM;
-
-   dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &obj_path,
-   DBUS_TYPE_INVALID);
-
-   g_dbus_send_message(connection, msg);
-   return 0;
-}
-
 static int hfp_probe(struct ofono_modem *modem)
 {
-   const char *obj_path = ofono_modem_get_path(modem);
struct hfp_data *data = ofono_modem_get_data(modem);
 
if (data == NULL)
return -EINVAL;
 
-   g_dbus_register_interface(connection, obj_path, HFP_AGENT_INTERFACE,
-   agent_methods, NULL, NULL, modem, NULL);
-
-   data->agent_registered = TRUE;
-
-   if (hfp_register_ofono_handsfree(modem) != 0)
-   return -EINVAL;
-
return 0;
 }
 
 static void hfp_remove(struct ofono_modem *modem)
 {
struct hfp_data *data = ofono_modem_get_data(modem);
-   const char *obj_path = ofono_modem_get_path(modem);
 
if (data->call != NULL)

[RFC v4 01/10] bluetooth: Add org.bluez.Telephony helpers

2012-04-06 Thread Frédéric Danis
Add function to register/unregister Telephony agent to BlueZ
---
 plugins/bluetooth.c |  198 +++
 plugins/bluetooth.h |   14 
 2 files changed, 212 insertions(+), 0 deletions(-)

diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index dbf79eb..971e2c6 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -44,6 +44,7 @@ static GHashTable *uuid_hash = NULL;
 static GHashTable *adapter_address_hash = NULL;
 static gint bluetooth_refcount;
 static GSList *server_list = NULL;
+static GSList *telephony_list = NULL;
 static const char *adapter_any_name = "any";
 static char *adapter_any_path;
 
@@ -65,6 +66,13 @@ struct cb_data {
GIOChannel *io;
 };
 
+struct agent {
+   char *path;
+   char *uuid;
+   guint16 version;
+   guint16 features;
+};
+
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
char *buf, int size)
 {
@@ -146,6 +154,60 @@ fail:
return err;
 }
 
+static void register_telephony_agent(const char *path, const char *handle,
+   struct agent *agent)
+{
+   DBusMessage *msg;
+   DBusMessageIter iter, dict;
+
+   DBG("Registering oFono Agent for %s to %s", agent->uuid, path);
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE, path,
+   BLUEZ_TELEPHONY_INTERFACE, "RegisterAgent");
+   if (msg == NULL)
+   return;
+
+   dbus_message_iter_init_append(msg, &iter);
+
+   dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+   &agent->path);
+
+   dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+   DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+   DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+   DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+   ofono_dbus_dict_append(&dict, "UUID", DBUS_TYPE_STRING, &agent->uuid);
+
+   ofono_dbus_dict_append(&dict, "Version", DBUS_TYPE_UINT16,
+   &agent->version);
+   ofono_dbus_dict_append(&dict, "Features", DBUS_TYPE_UINT16,
+   &agent->features);
+
+   dbus_message_iter_close_container(&iter, &dict);
+
+   g_dbus_send_message(connection, msg);
+}
+
+static void unregister_telephony_agent(const char *path, const char *handle,
+   struct agent *agent)
+{
+   DBusMessage *msg;
+
+   DBG("Unregistering oFono Agent for %s from %s", agent->uuid, path);
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE, path,
+   BLUEZ_TELEPHONY_INTERFACE,
+   "UnregisterAgent");
+   if (msg == NULL)
+   return;
+
+   dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &agent->path,
+   DBUS_TYPE_INVALID);
+
+   g_dbus_send_message(connection, msg);
+}
+
 typedef void (*PropertyHandler)(DBusMessageIter *iter, gpointer user_data);
 
 struct property_handler {
@@ -455,6 +517,9 @@ static void adapter_properties_cb(DBusPendingCall *call, 
gpointer user_data)
g_free, -1, DBUS_TYPE_INVALID);
}
 
+   for (l = telephony_list; l; l = l->next)
+   register_telephony_agent(path, NULL, l->data);
+
 done:
g_slist_free(device_list);
dbus_message_unref(reply);
@@ -982,5 +1047,138 @@ void bluetooth_unregister_server(struct server *server)
bluetooth_unref();
 }
 
+int bluetooth_parse_newconnection_message(DBusMessage *msg, const char 
**device,
+   const char **uuid, guint16 *version,
+   guint16 *features,
+   const char **transport_path)
+{
+   DBusMessageIter args, props;
+   int fd;
+   gboolean has_device = FALSE;
+   gboolean has_uuid = FALSE;
+
+   dbus_message_iter_init(msg, &args);
+
+   if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_UNIX_FD)
+   return -EINVAL;
+
+   dbus_message_iter_get_basic(&args, &fd);
+   dbus_message_iter_next(&args);
+
+   dbus_message_iter_recurse(&args, &props);
+   if (dbus_message_iter_get_arg_type(&props) != DBUS_TYPE_DICT_ENTRY)
+   return -EINVAL;
+
+   while (dbus_message_iter_get_arg_type(&props) == DBUS_TYPE_DICT_ENTRY) {
+   const char *key;
+   DBusMessageIter value, entry;
+   int var;
+
+   dbus_message_iter_recurse(&props, &entry);
+   dbus_message_iter_get_basic(&entry, &key);
+
+   dbus_message_iter_next(&entry);
+   dbus_message_iter_recurse(&entry, &value);
+
+   var = dbus_message_iter

[RFC v4 00/10] org.bluez.Telephony interface integration

2012-04-06 Thread Frédéric Danis
Those patches integrates the future org.bluez.Telephony interface into
oFono for HFP HF and HFP AG plugins.

For HFP AG plugin, the bluetooth rfcomm server is replaced by a
Telephony Agent registered to org.bluez.Telephony.
For HFP HF plugin, RegisterAgent call of org.bluez.HandsfreeGateway is
replaced by the one of org.bluez.Telephony

Since latest RFC :
- Patche 1
  move agent registration from adapter_added() to adapter_properties_cb()
- Patches 4 to 10:
  Rewrote support of AT+NREC, AT+VGM, +VGM, AT+VGS, +VGS and +BSIR into
  bluetooth plugin

Frédéric Danis (10):
  bluetooth: Add org.bluez.Telephony helpers
  hfp_hf: Update to org.bluez.Telephony interface
  hfp_ag: Update to org.bluez.Telephony interface
  bluetooth: Add audio APIs for HFP AG
  bluetooth: Add AT+NREC support
  bluetooth: Add +BSIR support
  bluetooth: Add AT+VGM support
  bluetooth: Add AT+VGS support
  hfp_ag: Add media transport support
  emulator: Update supported features

 plugins/bluetooth.c |  531 +++
 plugins/bluetooth.h |   18 ++
 plugins/hfp_ag.c|  143 +++---
 plugins/hfp_hf.c|  165 ++--
 src/emulator.c  |2 +
 5 files changed, 686 insertions(+), 173 deletions(-)

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v3 12/12] hfp_ag: Update supported features

2012-04-02 Thread Frédéric Danis
Add ECNR (Echo Cancelation/Noise Reduction) and Inband Ringtone
capabilities to supported features in HFP AG SDP record
---
 plugins/hfp_ag.c |4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/plugins/hfp_ag.c b/plugins/hfp_ag.c
index c12068a..52a8f83 100644
--- a/plugins/hfp_ag.c
+++ b/plugins/hfp_ag.c
@@ -37,7 +37,9 @@
 
 #define AGENT_PATH "/hfp_ag"
 #define VERSION_1_5 0x0105
-#define FEATURES   (HFP_AG_FEATURE_3WAY | HFP_AG_FEATURE_REJECT_CALL | \
+#define FEATURES   (HFP_AG_FEATURE_3WAY | HFP_AG_FEATURE_ECNR | \
+   HFP_AG_FEATURE_IN_BAND_RING_TONE | \
+   HFP_AG_FEATURE_REJECT_CALL | \
HFP_AG_FEATURE_ENHANCED_CALL_STATUS | \
HFP_AG_FEATURE_ENHANCED_CALL_CONTROL | \
HFP_AG_FEATURE_EXTENDED_RES_CODE)
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v3 11/12] emulator: Add AT+VGS support

2012-04-02 Thread Frédéric Danis
---
 src/emulator.c |   81 
 1 files changed, 81 insertions(+), 0 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index a976a13..0ae86e0 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -57,6 +57,8 @@ struct ofono_emulator {
guint audio_watch;
int mic_gain;
int mic_pending;
+   int sp_gain;
+   int sp_pending;
 };
 
 struct indicator {
@@ -992,6 +994,48 @@ fail:
};
 }
 
+static void vgs_cb(GAtServer *server, GAtServerRequestType type,
+   GAtResult *result, gpointer user_data)
+{
+   struct ofono_emulator *em = user_data;
+   GAtResultIter iter;
+   int val;
+
+   if (em->slc == FALSE)
+   goto fail;
+
+   switch (type) {
+   case G_AT_SERVER_REQUEST_TYPE_SET:
+   if (em->audio_transport == NULL)
+   goto fail;
+
+   g_at_result_iter_init(&iter, result);
+   g_at_result_iter_next(&iter, "");
+
+   if (!g_at_result_iter_next_number(&iter, &val))
+   goto fail;
+
+   if (val < 0 || val > 15)
+   goto fail;
+
+   /* check this is last parameter */
+   if (g_at_result_iter_skip_next(&iter))
+   goto fail;
+
+   if (em->sp_pending != -1)
+   ofono_error("Receiving AT+VGS while processing one");
+
+   em->sp_pending = val;
+   audio_transport_set_property(server, em->audio_transport,
+   "SpeakerGain", DBUS_TYPE_UINT16, &val);
+   break;
+
+   default:
+fail:
+   g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
+   };
+}
+
 static void emulator_add_indicator(struct ofono_emulator *em, const char* name,
int min, int max, int dflt,
gboolean mandatory)
@@ -1096,6 +1140,7 @@ void ofono_emulator_register(struct ofono_emulator *em, 
int fd)
g_at_server_register(em->server, "+BIA", bia_cb, em, NULL);
g_at_server_register(em->server, "+NREC", nrec_cb, em, NULL);
g_at_server_register(em->server, "+VGM", vgm_cb, em, NULL);
+   g_at_server_register(em->server, "+VGS", vgs_cb, em, NULL);
}
 
__ofono_atom_register(em->atom, emulator_unregister);
@@ -1161,6 +1206,7 @@ struct ofono_emulator *ofono_emulator_create(struct 
ofono_modem *modem,
em->events_mode = 3;/* default mode is forwarding events */
em->cmee_mode = 0;  /* CME ERROR disabled by default */
em->mic_pending = -1;
+   em->sp_pending = -1;
 
em->atom = __ofono_modem_add_atom_offline(modem, atom_t,
emulator_remove, em);
@@ -1243,6 +1289,41 @@ static gboolean audio_property_changed(DBusConnection 
*connection,
} else if (em->mic_pending == value)
em->mic_pending = -1;
em->mic_gain = value;
+   } else if (g_str_equal(property, "SpeakerGain") == TRUE) {
+   DBusMessageIter variant;
+   int value;
+
+   if (!(em->r_features & HFP_HF_FEATURE_REMOTE_VOLUME_CONTROL))
+   return TRUE;
+
+   if (!dbus_message_iter_next(&iter))
+   return TRUE;
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+   return TRUE;
+
+   dbus_message_iter_recurse(&iter, &variant);
+
+   if (dbus_message_iter_get_arg_type(&variant) !=
+   DBUS_TYPE_UINT16)
+   return TRUE;
+
+   dbus_message_iter_get_basic(&variant, &value);
+
+   /* Send unsolicited +VGS only if :
+*   - the value has changed
+*   - and this is not a side effect of AT+VGS
+* But, if we receive a value change while waiting for another
+* pending change, we may have to send +VGS for other changes
+* (multiple AT+VGS received) to keep speaker gain in sync
+*/
+   if (em->sp_pending != value && em->sp_gain != value) {
+   sprintf(buf, "+VGS: %d", value);
+   g_at_server_send_unsolicited(em->server, buf);
+   em->sp_pending = -1;
+   } else if (em->sp_pending == value)
+   em->sp_pending = -1;
+   em->sp_gain = value;
}
 
return TRUE;
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v3 09/12] emulator: Add +BSIR support

2012-04-02 Thread Frédéric Danis
---
 src/emulator.c |   58 
 1 files changed, 58 insertions(+), 0 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index c5ec105..0760c79 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -54,6 +54,7 @@ struct ofono_emulator {
gboolean ccwa;
int pns_id;
char *audio_transport;
+   guint audio_watch;
 };
 
 struct indicator {
@@ -1071,9 +1072,15 @@ void ofono_emulator_register(struct ofono_emulator *em, 
int fd)
 static void emulator_remove(struct ofono_atom *atom)
 {
struct ofono_emulator *em = __ofono_atom_get_data(atom);
+   DBusConnection *connection;
 
DBG("atom: %p", atom);
 
+   connection = ofono_dbus_get_connection();
+
+   if (em->audio_watch)
+   g_dbus_remove_watch(connection, em->audio_watch);
+
g_free(em->audio_transport);
g_free(em);
 }
@@ -1101,6 +1108,7 @@ struct ofono_emulator *ofono_emulator_create(struct 
ofono_modem *modem,
em->type = type;
em->l_features |= HFP_AG_FEATURE_3WAY;
em->l_features |= HFP_AG_FEATURE_ECNR;
+   em->l_features |= HFP_AG_FEATURE_IN_BAND_RING_TONE;
em->l_features |= HFP_AG_FEATURE_REJECT_CALL;
em->l_features |= HFP_AG_FEATURE_ENHANCED_CALL_STATUS;
em->l_features |= HFP_AG_FEATURE_ENHANCED_CALL_CONTROL;
@@ -1119,10 +1127,60 @@ void ofono_emulator_remove(struct ofono_emulator *em)
__ofono_atom_free(em->atom);
 }
 
+static gboolean audio_property_changed(DBusConnection *connection,
+   DBusMessage *message, void *user_data)
+{
+   struct ofono_emulator *em = user_data;
+   const char *property;
+   char buf[10];
+   DBusMessageIter iter;
+
+   dbus_message_iter_init(message, &iter);
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+   return FALSE;
+
+   dbus_message_iter_get_basic(&iter, &property);
+
+   if (g_str_equal(property, "InbandRingtone") == TRUE) {
+   DBusMessageIter variant;
+   gboolean value;
+
+   if (!dbus_message_iter_next(&iter))
+   return TRUE;
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+   return TRUE;
+
+   dbus_message_iter_recurse(&iter, &variant);
+
+   if (dbus_message_iter_get_arg_type(&variant) !=
+   DBUS_TYPE_BOOLEAN)
+   return TRUE;
+
+   dbus_message_iter_get_basic(&variant, &value);
+
+   sprintf(buf, "+BSIR: %d", value);
+   g_at_server_send_unsolicited(em->server, buf);
+   }
+
+   return TRUE;
+}
+
 void ofono_emulator_set_audio_transport(struct ofono_emulator *em,
const char *path)
 {
+   DBusConnection *connection;
+
em->audio_transport = g_strdup(path);
+
+   connection = ofono_dbus_get_connection();
+
+   em->audio_watch = g_dbus_add_signal_watch(connection, NULL, path,
+   BLUEZ_TRANSPORT_INTERFACE,
+   "PropertyChanged",
+   audio_property_changed, em,
+   NULL);
 }
 
 void ofono_emulator_send_final(struct ofono_emulator *em,
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v3 08/12] emulator: Add AT+NREC support

2012-04-02 Thread Frédéric Danis
---
 src/emulator.c |  120 
 1 files changed, 120 insertions(+), 0 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index dc3c10d..c5ec105 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -33,6 +33,7 @@
 #include "common.h"
 #include "gatserver.h"
 #include "gatppp.h"
+#include "../plugins/bluetooth.h"
 
 #define RING_TIMEOUT 3
 
@@ -312,6 +313,85 @@ error:
}
 }
 
+static void audio_transport_set_property_cb(DBusPendingCall *call,
+   gpointer user_data)
+{
+   GAtServer *server = user_data;
+   DBusMessage *reply;
+   struct DBusError derr;
+   GAtServerResult result;
+
+   reply = dbus_pending_call_steal_reply(call);
+
+   dbus_error_init(&derr);
+
+   if (dbus_set_error_from_message(&derr, reply)) {
+   ofono_error("MediaTransport.SetProperties replied an error: " \
+   "%s, %s", derr.name, derr.message);
+   dbus_error_free(&derr);
+   result = G_AT_SERVER_RESULT_ERROR;
+   } else
+   result = G_AT_SERVER_RESULT_OK;
+
+   g_at_server_send_final(server, result);
+
+   dbus_message_unref(reply);
+}
+
+static void audio_transport_set_property(GAtServer *server, const char *path,
+   const char *name, int type,
+   const void *value)
+{
+   DBusMessage *msg;
+   DBusMessageIter iter, var;
+   const char *str_type;
+   DBusConnection *connection;
+   DBusPendingCall *c;
+
+   if (path == NULL)
+   return;
+
+   switch (type) {
+   case DBUS_TYPE_BOOLEAN:
+   str_type = DBUS_TYPE_BOOLEAN_AS_STRING;
+   break;
+
+   case DBUS_TYPE_UINT16:
+   str_type = DBUS_TYPE_UINT16_AS_STRING;
+   break;
+
+   default:
+   return;
+   }
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE, path,
+   BLUEZ_TRANSPORT_INTERFACE, "SetProperty");
+   if (msg == NULL)
+   return;
+
+   dbus_message_iter_init_append(msg, &iter);
+   dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
+
+   dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, str_type,
+   &var);
+   dbus_message_iter_append_basic(&var, type, value);
+   dbus_message_iter_close_container(&iter, &var);
+
+   connection = ofono_dbus_get_connection();
+
+   if (!dbus_connection_send_with_reply(connection, msg, &c, -1)) {
+   ofono_error("Sending SetProperty failed");
+   goto fail;
+   }
+
+   dbus_pending_call_set_notify(c, audio_transport_set_property_cb, server,
+   NULL);
+   dbus_pending_call_unref(c);
+
+fail:
+   dbus_message_unref(msg);
+}
+
 static struct indicator *find_indicator(struct ofono_emulator *em,
const char *name, int *index)
 {
@@ -829,6 +909,44 @@ fail:
}
 }
 
+static void nrec_cb(GAtServer *server, GAtServerRequestType type,
+   GAtResult *result, gpointer user_data)
+{
+   struct ofono_emulator *em = user_data;
+   GAtResultIter iter;
+   int val;
+
+   if (em->slc == FALSE)
+   goto fail;
+
+   switch (type) {
+   case G_AT_SERVER_REQUEST_TYPE_SET:
+   if (em->audio_transport == NULL)
+   goto fail;
+
+   g_at_result_iter_init(&iter, result);
+   g_at_result_iter_next(&iter, "");
+
+   if (!g_at_result_iter_next_number(&iter, &val))
+   goto fail;
+
+   if (val != 0 && val != 1)
+   goto fail;
+
+   /* check this is last parameter */
+   if (g_at_result_iter_skip_next(&iter))
+   goto fail;
+
+   audio_transport_set_property(server, em->audio_transport,
+   "NREC", DBUS_TYPE_BOOLEAN, &val);
+   break;
+
+   default:
+fail:
+   g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
+   };
+}
+
 static void emulator_add_indicator(struct ofono_emulator *em, const char* name,
int min, int max, int dflt,
gboolean mandatory)
@@ -931,6 +1049,7 @@ void ofono_emulator_register(struct ofono_emulator *em, 
int fd)
g_at_server_register(em->server, "+CCWA", ccwa_cb, em, NULL);
g_at_server_register(em->server, "+CMEE", cmee_cb, em, NULL);
g_at_server_register(em->server, "+BIA", bia_cb, em, NULL);
+   g_at_server_register(em->server, "+NREC", nrec_cb, em, NULL);
}
 
__ofono_

[RFC v3 07/12] hfp_ag: Add media transport support

2012-04-02 Thread Frédéric Danis
---
 plugins/hfp_ag.c |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/plugins/hfp_ag.c b/plugins/hfp_ag.c
index ea9c112..c12068a 100644
--- a/plugins/hfp_ag.c
+++ b/plugins/hfp_ag.c
@@ -82,6 +82,7 @@ static DBusMessage 
*hfp_ag_agent_new_connection(DBusConnection *conn,
return __ofono_error_failed(msg);
 
ofono_emulator_register(em, fd);
+   ofono_emulator_set_audio_transport(em, path);
 
return dbus_message_new_method_return(msg);
 }
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v3 06/12] emulator: Add audio transport set

2012-04-02 Thread Frédéric Danis
---
 src/emulator.c |8 
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index e7c7d41..dc3c10d 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -52,6 +52,7 @@ struct ofono_emulator {
gboolean clip;
gboolean ccwa;
int pns_id;
+   char *audio_transport;
 };
 
 struct indicator {
@@ -954,6 +955,7 @@ static void emulator_remove(struct ofono_atom *atom)
 
DBG("atom: %p", atom);
 
+   g_free(em->audio_transport);
g_free(em);
 }
 
@@ -997,6 +999,12 @@ void ofono_emulator_remove(struct ofono_emulator *em)
__ofono_atom_free(em->atom);
 }
 
+void ofono_emulator_set_audio_transport(struct ofono_emulator *em,
+   const char *path)
+{
+   em->audio_transport = g_strdup(path);
+}
+
 void ofono_emulator_send_final(struct ofono_emulator *em,
const struct ofono_error *final)
 {
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v3 10/12] emulator: Add AT+VGM support

2012-04-02 Thread Frédéric Danis
---
 src/emulator.c |   81 
 1 files changed, 81 insertions(+), 0 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index 0760c79..a976a13 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -55,6 +55,8 @@ struct ofono_emulator {
int pns_id;
char *audio_transport;
guint audio_watch;
+   int mic_gain;
+   int mic_pending;
 };
 
 struct indicator {
@@ -948,6 +950,48 @@ fail:
};
 }
 
+static void vgm_cb(GAtServer *server, GAtServerRequestType type,
+   GAtResult *result, gpointer user_data)
+{
+   struct ofono_emulator *em = user_data;
+   GAtResultIter iter;
+   int val;
+
+   if (em->slc == FALSE)
+   goto fail;
+
+   switch (type) {
+   case G_AT_SERVER_REQUEST_TYPE_SET:
+   if (em->audio_transport == NULL)
+   goto fail;
+
+   g_at_result_iter_init(&iter, result);
+   g_at_result_iter_next(&iter, "");
+
+   if (!g_at_result_iter_next_number(&iter, &val))
+   goto fail;
+
+   if (val < 0 || val > 15)
+   goto fail;
+
+   /* check this is last parameter */
+   if (g_at_result_iter_skip_next(&iter))
+   goto fail;
+
+   if (em->mic_pending != -1)
+   ofono_error("Receiving AT+VGM while processing one");
+
+   em->mic_pending = val;
+   audio_transport_set_property(server, em->audio_transport,
+   "MicrophoneGain", DBUS_TYPE_UINT16, &val);
+   break;
+
+   default:
+fail:
+   g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
+   };
+}
+
 static void emulator_add_indicator(struct ofono_emulator *em, const char* name,
int min, int max, int dflt,
gboolean mandatory)
@@ -1051,6 +1095,7 @@ void ofono_emulator_register(struct ofono_emulator *em, 
int fd)
g_at_server_register(em->server, "+CMEE", cmee_cb, em, NULL);
g_at_server_register(em->server, "+BIA", bia_cb, em, NULL);
g_at_server_register(em->server, "+NREC", nrec_cb, em, NULL);
+   g_at_server_register(em->server, "+VGM", vgm_cb, em, NULL);
}
 
__ofono_atom_register(em->atom, emulator_unregister);
@@ -1115,6 +1160,7 @@ struct ofono_emulator *ofono_emulator_create(struct 
ofono_modem *modem,
em->l_features |= HFP_AG_FEATURE_EXTENDED_RES_CODE;
em->events_mode = 3;/* default mode is forwarding events */
em->cmee_mode = 0;  /* CME ERROR disabled by default */
+   em->mic_pending = -1;
 
em->atom = __ofono_modem_add_atom_offline(modem, atom_t,
emulator_remove, em);
@@ -1162,6 +1208,41 @@ static gboolean audio_property_changed(DBusConnection 
*connection,
 
sprintf(buf, "+BSIR: %d", value);
g_at_server_send_unsolicited(em->server, buf);
+   } else if (g_str_equal(property, "MicrophoneGain") == TRUE) {
+   DBusMessageIter variant;
+   int value;
+
+   if (!(em->r_features & HFP_HF_FEATURE_REMOTE_VOLUME_CONTROL))
+   return TRUE;
+
+   if (!dbus_message_iter_next(&iter))
+   return TRUE;
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+   return TRUE;
+
+   dbus_message_iter_recurse(&iter, &variant);
+
+   if (dbus_message_iter_get_arg_type(&variant) !=
+   DBUS_TYPE_UINT16)
+   return TRUE;
+
+   dbus_message_iter_get_basic(&variant, &value);
+
+   /* Send unsolicited +VGM only if :
+*   - the value has changed
+*   - and this is not a side effect of AT+VGM
+* But, if we receive a value change while waiting for another
+* pending change, we may have to send +VGM for other changes
+* (multiple AT+VGM received) to keep mic gain in sync
+*/
+   if (em->mic_pending != value && em->mic_gain != value) {
+   sprintf(buf, "+VGM: %d", value);
+   g_at_server_send_unsolicited(em->server, buf);
+   em->mic_pending = -1;
+   } else if (em->mic_pending == value)
+   em->mic_pending = -1;
+   em->mic_gain = value;
}
 
return TRUE;
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v3 05/12] include: Add audio transport set API

2012-04-02 Thread Frédéric Danis
---
 include/emulator.h |3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/include/emulator.h b/include/emulator.h
index 5cd894b..4b78667 100644
--- a/include/emulator.h
+++ b/include/emulator.h
@@ -72,6 +72,9 @@ struct ofono_emulator *ofono_emulator_create(struct 
ofono_modem *modem,
 
 void ofono_emulator_register(struct ofono_emulator *em, int fd);
 
+void ofono_emulator_set_audio_transport(struct ofono_emulator *em,
+   const char *path);
+
 void ofono_emulator_remove(struct ofono_emulator *em);
 
 void ofono_emulator_send_final(struct ofono_emulator *em,
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v3 04/12] bluetooth: Add org.bluez.MediaTransport interface

2012-04-02 Thread Frédéric Danis
---
 plugins/bluetooth.h |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/plugins/bluetooth.h b/plugins/bluetooth.h
index f81fc99..ee3c71e 100644
--- a/plugins/bluetooth.h
+++ b/plugins/bluetooth.h
@@ -30,6 +30,7 @@
 #defineBLUEZ_SERVICE_INTERFACE BLUEZ_SERVICE ".Service"
 #defineBLUEZ_TELEPHONY_INTERFACE   BLUEZ_SERVICE ".Telephony"
 #defineBLUEZ_TELEPHONY_AGENT_INTERFACE BLUEZ_SERVICE ".TelephonyAgent"
+#defineBLUEZ_TRANSPORT_INTERFACE   BLUEZ_SERVICE ".MediaTransport"
 
 #define DBUS_TIMEOUT 15
 
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v3 03/12] hfp_ag: Update to org.bluez.Telephony interface

2012-04-02 Thread Frédéric Danis
Bluez moves agent registration from a per device interface to
a per adapter interface.
Update hfp_ag modem emulator to reflect this change.
---
 plugins/hfp_ag.c |  126 --
 1 files changed, 56 insertions(+), 70 deletions(-)

diff --git a/plugins/hfp_ag.c b/plugins/hfp_ag.c
index c2d1d30..ea9c112 100644
--- a/plugins/hfp_ag.c
+++ b/plugins/hfp_ag.c
@@ -35,97 +35,83 @@
 
 #include "bluetooth.h"
 
-#define HFP_AG_CHANNEL 13
+#define AGENT_PATH "/hfp_ag"
+#define VERSION_1_5 0x0105
+#define FEATURES   (HFP_AG_FEATURE_3WAY | HFP_AG_FEATURE_REJECT_CALL | \
+   HFP_AG_FEATURE_ENHANCED_CALL_STATUS | \
+   HFP_AG_FEATURE_ENHANCED_CALL_CONTROL | \
+   HFP_AG_FEATURE_EXTENDED_RES_CODE)
+
+#ifndef DBUS_TYPE_UNIX_FD
+#define DBUS_TYPE_UNIX_FD -1
+#endif
 
-static struct server *server;
 static guint modemwatch_id;
 static GList *modems;
 static GHashTable *sim_hash = NULL;
 
-static const gchar *hfp_ag_record =
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"  \n"
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n";
-
-static void hfp_ag_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
+static DBusMessage *hfp_ag_agent_new_connection(DBusConnection *conn,
+   DBusMessage *msg, void *data)
 {
-   struct ofono_modem *modem;
-   struct ofono_emulator *em;
int fd;
+   const char *device, *uuid;
+   const char *path = NULL;
+   guint16 version = 0;
+   guint16 features = 0;
+   struct ofono_emulator *em;
+   struct ofono_modem *modem;
 
-   DBG("");
+   fd = bluetooth_parse_newconnection_message(msg, &device, &uuid,
+   &version, &features, &path);
+   if (fd < 0)
+   return __ofono_error_invalid_args(msg);
 
-   if (err) {
-   DBG("%s", err->message);
-   return;
-   }
+   DBG("New connection for %s on %s (version 0x%04X, features 0x%02X, " \
+   "media transport path: %s)",
+   device, uuid, version, features, path);
 
/* Pick the first voicecall capable modem */
modem = modems->data;
if (modem == NULL)
-   return;
+   return __ofono_error_failed(msg);
 
DBG("Picked modem %p for emulator", modem);
 
em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_HFP);
if (em == NULL)
-   return;
-
-   fd = g_io_channel_unix_get_fd(io);
-   g_io_channel_set_close_on_unref(io, FALSE);
+   return __ofono_error_failed(msg);
 
ofono_emulator_register(em, fd);
+
+   return dbus_message_new_method_return(msg);
 }
 
+static DBusMessage *hfp_ag_agent_release(DBusConnection *conn,
+   DBusMessage *msg, void *data)
+{
+   DBG("");
+
+   return dbus_message_new_method_return(msg);
+}
+
+static GDBusMethodTable agent_methods[] = {
+   { "NewConnection", "ha{sv}", "", hfp_ag_agent_new_connection,
+   G_DBUS_METHOD_FLAG_ASYNC },
+   { "Release", "", "", hfp_ag_agent_release },
+   { NULL, NULL, NULL, NULL }
+};
+
 static void sim_state_watch(enum ofono_sim_state new_state, void *data)
 {
struct ofono_modem *modem = data;
 
if (new_state != OFONO_SIM_STATE_READY) {
+   if (modems == NULL)
+   return;
+
modems = g_list_remove(modems, modem);
-   if (modems == NULL && server != NULL) {
-   bluetooth_unregister_server(server);
-   server = NULL;
-   }
+   if (modems == NULL)
+   bluetooth_unregister_telephony_agent(AGENT_PATH);
 
return;
}
@@ -138,8 +124,9 @@ static void sim_state_watch(enum ofono_sim_state new_state, 
void *data)
if (modems->next != NULL)
return;
 
-   server = bluetooth_register_server(HFP_AG_CHANNEL, hfp_ag_record,
-   hfp_ag_connect_cb, NULL);
+   bluetooth_register_telephony_agent(AGENT_PATH, HFP_AG_UUID,
+   VERSION_1_5, FEATURES,
+   agent_methods, NULL, NULL);
 }
 
 static gboolean sim_watch_remove(gpointer key, gpointer value,
@@ -192,6 +179,9 @@ static void call_modemwatch(struct ofono_modem *modem, void 
*user)
 
 static int hfp_ag_init(void)
 {
+   if (DBUS_TYPE_UNIX_FD < 0)
+   return -EBADF;
+
sim_hash = g_

[RFC v3 02/12] hfp_hf: Update to org.bluez.Telephony interface

2012-04-02 Thread Frédéric Danis
Bluez moves agent registration from a per device interface to
a per adapter interface.
Update hfp_hf modem to reflect this change.
---
 plugins/hfp_hf.c |  165 -
 1 files changed, 62 insertions(+), 103 deletions(-)

diff --git a/plugins/hfp_hf.c b/plugins/hfp_hf.c
index 48a734a..7c3747b 100644
--- a/plugins/hfp_hf.c
+++ b/plugins/hfp_hf.c
@@ -51,7 +51,7 @@
 
 #defineBLUEZ_GATEWAY_INTERFACE BLUEZ_SERVICE 
".HandsfreeGateway"
 
-#define HFP_AGENT_INTERFACE "org.bluez.HandsfreeAgent"
+#define HFP_AGENT_PATH "/hfp_hf"
 #define HFP_AGENT_ERROR_INTERFACE "org.bluez.Error"
 
 #ifndef DBUS_TYPE_UNIX_FD
@@ -66,7 +66,6 @@ struct hfp_data {
char *handsfree_path;
char *handsfree_address;
DBusMessage *slc_msg;
-   gboolean agent_registered;
DBusPendingCall *call;
 };
 
@@ -158,52 +157,6 @@ static int service_level_connection(struct ofono_modem 
*modem, int fd)
return -EINPROGRESS;
 }
 
-static DBusMessage *hfp_agent_new_connection(DBusConnection *conn,
-   DBusMessage *msg, void *data)
-{
-   int fd, err;
-   struct ofono_modem *modem = data;
-   struct hfp_data *hfp_data = ofono_modem_get_data(modem);
-   guint16 version;
-
-   if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UNIX_FD, &fd,
-   DBUS_TYPE_UINT16, &version, DBUS_TYPE_INVALID))
-   return __ofono_error_invalid_args(msg);
-
-   hfp_slc_info_init(&hfp_data->info, version);
-
-   err = service_level_connection(modem, fd);
-   if (err < 0 && err != -EINPROGRESS)
-   return __ofono_error_failed(msg);
-
-   hfp_data->slc_msg = msg;
-   dbus_message_ref(msg);
-
-   return NULL;
-}
-
-static DBusMessage *hfp_agent_release(DBusConnection *conn,
-   DBusMessage *msg, void *data)
-{
-   struct ofono_modem *modem = data;
-   struct hfp_data *hfp_data = ofono_modem_get_data(modem);
-   const char *obj_path = ofono_modem_get_path(modem);
-
-   g_dbus_unregister_interface(connection, obj_path, HFP_AGENT_INTERFACE);
-   hfp_data->agent_registered = FALSE;
-
-   ofono_modem_remove(modem);
-
-   return dbus_message_new_method_return(msg);
-}
-
-static GDBusMethodTable agent_methods[] = {
-   { "NewConnection", "hq", "", hfp_agent_new_connection,
-   G_DBUS_METHOD_FLAG_ASYNC },
-   { "Release", "", "", hfp_agent_release },
-   { NULL, NULL, NULL, NULL }
-};
-
 static int hfp_hf_probe(const char *device, const char *dev_addr,
const char *adapter_addr, const char *alias)
 {
@@ -295,77 +248,23 @@ static void hfp_hf_set_alias(const char *device, const 
char *alias)
ofono_modem_set_name(modem, alias);
 }
 
-static int hfp_register_ofono_handsfree(struct ofono_modem *modem)
-{
-   const char *obj_path = ofono_modem_get_path(modem);
-   struct hfp_data *data = ofono_modem_get_data(modem);
-   DBusMessage *msg;
-
-   DBG("Registering oFono Agent to bluetooth daemon");
-
-   msg = dbus_message_new_method_call(BLUEZ_SERVICE, data->handsfree_path,
-   BLUEZ_GATEWAY_INTERFACE, "RegisterAgent");
-   if (msg == NULL)
-   return -ENOMEM;
-
-   dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &obj_path,
-   DBUS_TYPE_INVALID);
-
-   g_dbus_send_message(connection, msg);
-   return 0;
-}
-
-static int hfp_unregister_ofono_handsfree(struct ofono_modem *modem)
-{
-   const char *obj_path = ofono_modem_get_path(modem);
-   struct hfp_data *data = ofono_modem_get_data(modem);
-   DBusMessage *msg;
-
-   DBG("Unregistering oFono Agent from bluetooth daemon");
-
-   msg = dbus_message_new_method_call(BLUEZ_SERVICE, data->handsfree_path,
-   BLUEZ_GATEWAY_INTERFACE, "UnregisterAgent");
-   if (msg == NULL)
-   return -ENOMEM;
-
-   dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &obj_path,
-   DBUS_TYPE_INVALID);
-
-   g_dbus_send_message(connection, msg);
-   return 0;
-}
-
 static int hfp_probe(struct ofono_modem *modem)
 {
-   const char *obj_path = ofono_modem_get_path(modem);
struct hfp_data *data = ofono_modem_get_data(modem);
 
if (data == NULL)
return -EINVAL;
 
-   g_dbus_register_interface(connection, obj_path, HFP_AGENT_INTERFACE,
-   agent_methods, NULL, NULL, modem, NULL);
-
-   data->agent_registered = TRUE;
-
-   if (hfp_register_ofono_handsfree(modem) != 0)
-   return -EINVAL;
-
return 0;
 }
 
 static void hfp_remove(struct ofono_modem *modem)
 {
struct hfp_data *data = ofono_modem_get_data(modem);
-   const char *obj_path = ofono_modem_get_path(modem);
 
if (data->call != NULL)

[RFC v3 00/12] org.bluez.Telephony interface integration

2012-04-02 Thread Frédéric Danis
Those patches integrates the future org.bluez.Telephony interface into
oFono for HFP HF and HFP AG plugins.

For HFP AG plugin, the bluetooth rfcomm server is replaced by a
Telephony Agent registered to org.bluez.Telephony.
For HFP HF plugin, RegisterAgent call of org.bluez.HandsfreeGateway is
replaced by the one of org.bluez.Telephony

Since latest RFC :
- Patch 9:
  - Fix PropertyChanged callback for InbandRingtone
RFC v2:
- add support of org.bluez.MediaTransport interface in emulator.
  This allows support of audio related functions with the new
  architecture.
- add support for AT+NREC command
- add support of In-band ring tone (+BSIR event)
- add support of volume management (AT+VGS and AT+VGM commands,
  +VGS and +VGM events)

Any comments appreciated.

Frédéric Danis (12):
  bluetooth: Add org.bluez.Telephony helpers
  hfp_hf: Update to org.bluez.Telephony interface
  hfp_ag: Update to org.bluez.Telephony interface
  bluetooth: Add org.bluez.MediaTransport interface
  include: Add audio transport set API
  emulator: Add audio transport set
  hfp_ag: Add media transport support
  emulator: Add AT+NREC support
  emulator: Add +BSIR support
  emulator: Add AT+VGM support
  emulator: Add AT+VGS support
  hfp_ag: Update supported features

 include/emulator.h  |3 +
 plugins/bluetooth.c |  199 +
 plugins/bluetooth.h |   15 +++
 plugins/hfp_ag.c|  129 +--
 plugins/hfp_hf.c|  165 +---
 src/emulator.c  |  348 +++
 6 files changed, 686 insertions(+), 173 deletions(-)

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v3 01/12] bluetooth: Add org.bluez.Telephony helpers

2012-04-02 Thread Frédéric Danis
Add function to register/unregister Telephony agent to BlueZ
---
 plugins/bluetooth.c |  199 +++
 plugins/bluetooth.h |   14 
 2 files changed, 213 insertions(+), 0 deletions(-)

diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index dbf79eb..0bde1a5 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -44,6 +44,7 @@ static GHashTable *uuid_hash = NULL;
 static GHashTable *adapter_address_hash = NULL;
 static gint bluetooth_refcount;
 static GSList *server_list = NULL;
+static GSList *telephony_list = NULL;
 static const char *adapter_any_name = "any";
 static char *adapter_any_path;
 
@@ -65,6 +66,13 @@ struct cb_data {
GIOChannel *io;
 };
 
+struct agent {
+   char *path;
+   char *uuid;
+   guint16 version;
+   guint16 features;
+};
+
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
char *buf, int size)
 {
@@ -146,6 +154,60 @@ fail:
return err;
 }
 
+static void register_telephony_agent(const char *path, const char *handle,
+   struct agent *agent)
+{
+   DBusMessage *msg;
+   DBusMessageIter iter, dict;
+
+   DBG("Registering oFono Agent for %s to %s", agent->uuid, path);
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE, path,
+   BLUEZ_TELEPHONY_INTERFACE, "RegisterAgent");
+   if (msg == NULL)
+   return;
+
+   dbus_message_iter_init_append(msg, &iter);
+
+   dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+   &agent->path);
+
+   dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+   DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+   DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+   DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+   ofono_dbus_dict_append(&dict, "UUID", DBUS_TYPE_STRING, &agent->uuid);
+
+   ofono_dbus_dict_append(&dict, "Version", DBUS_TYPE_UINT16,
+   &agent->version);
+   ofono_dbus_dict_append(&dict, "Features", DBUS_TYPE_UINT16,
+   &agent->features);
+
+   dbus_message_iter_close_container(&iter, &dict);
+
+   g_dbus_send_message(connection, msg);
+}
+
+static void unregister_telephony_agent(const char *path, const char *handle,
+   struct agent *agent)
+{
+   DBusMessage *msg;
+
+   DBG("Unregistering oFono Agent for %s from %s", agent->uuid, path);
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE, path,
+   BLUEZ_TELEPHONY_INTERFACE,
+   "UnregisterAgent");
+   if (msg == NULL)
+   return;
+
+   dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &agent->path,
+   DBUS_TYPE_INVALID);
+
+   g_dbus_send_message(connection, msg);
+}
+
 typedef void (*PropertyHandler)(DBusMessageIter *iter, gpointer user_data);
 
 struct property_handler {
@@ -702,6 +764,7 @@ static gboolean adapter_added(DBusConnection *connection, 
DBusMessage *message,
void *user_data)
 {
const char *path;
+   GSList *l;
 
dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_INVALID);
@@ -710,6 +773,9 @@ static gboolean adapter_added(DBusConnection *connection, 
DBusMessage *message,
"GetProperties", NULL, adapter_properties_cb,
g_strdup(path), g_free, -1, DBUS_TYPE_INVALID);
 
+   for (l = telephony_list; l; l = l->next)
+   register_telephony_agent(path, NULL, l->data);
+
return TRUE;
 }
 
@@ -982,5 +1048,138 @@ void bluetooth_unregister_server(struct server *server)
bluetooth_unref();
 }
 
+int bluetooth_parse_newconnection_message(DBusMessage *msg, const char 
**device,
+   const char **uuid, guint16 *version,
+   guint16 *features,
+   const char **transport_path)
+{
+   DBusMessageIter args, props;
+   int fd;
+   gboolean has_device = FALSE;
+   gboolean has_uuid = FALSE;
+
+   dbus_message_iter_init(msg, &args);
+
+   if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_UNIX_FD)
+   return -EINVAL;
+
+   dbus_message_iter_get_basic(&args, &fd);
+   dbus_message_iter_next(&args);
+
+   dbus_message_iter_recurse(&args, &props);
+   if (dbus_message_iter_get_arg_type(&props) != DBUS_TYPE_DICT_ENTRY)
+   return -EINVAL;
+
+   while (dbus_message_iter_get_arg_type(&props) == DBUS_TYPE_DICT_ENTRY) {
+   const char *key;
+ 

[RFC v2 11/12] emulator: Add AT+VGS support

2012-03-26 Thread Frédéric Danis
---
 src/emulator.c |   81 
 1 files changed, 81 insertions(+), 0 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index 8c5a89a..8ad0e90 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -57,6 +57,8 @@ struct ofono_emulator {
guint audio_watch;
int mic_gain;
int mic_pending;
+   int sp_gain;
+   int sp_pending;
 };
 
 struct indicator {
@@ -992,6 +994,48 @@ fail:
};
 }
 
+static void vgs_cb(GAtServer *server, GAtServerRequestType type,
+   GAtResult *result, gpointer user_data)
+{
+   struct ofono_emulator *em = user_data;
+   GAtResultIter iter;
+   int val;
+
+   if (em->slc == FALSE)
+   goto fail;
+
+   switch (type) {
+   case G_AT_SERVER_REQUEST_TYPE_SET:
+   if (em->audio_transport == NULL)
+   goto fail;
+
+   g_at_result_iter_init(&iter, result);
+   g_at_result_iter_next(&iter, "");
+
+   if (!g_at_result_iter_next_number(&iter, &val))
+   goto fail;
+
+   if (val < 0 || val > 15)
+   goto fail;
+
+   /* check this is last parameter */
+   if (g_at_result_iter_skip_next(&iter))
+   goto fail;
+
+   if (em->sp_pending != -1)
+   ofono_error("Receiving AT+VGS while processing one");
+
+   em->sp_pending = val;
+   audio_transport_set_property(server, em->audio_transport,
+   "SpeakerGain", DBUS_TYPE_UINT16, &val);
+   break;
+
+   default:
+fail:
+   g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
+   };
+}
+
 static void emulator_add_indicator(struct ofono_emulator *em, const char* name,
int min, int max, int dflt,
gboolean mandatory)
@@ -1096,6 +1140,7 @@ void ofono_emulator_register(struct ofono_emulator *em, 
int fd)
g_at_server_register(em->server, "+BIA", bia_cb, em, NULL);
g_at_server_register(em->server, "+NREC", nrec_cb, em, NULL);
g_at_server_register(em->server, "+VGM", vgm_cb, em, NULL);
+   g_at_server_register(em->server, "+VGS", vgs_cb, em, NULL);
}
 
__ofono_atom_register(em->atom, emulator_unregister);
@@ -1161,6 +1206,7 @@ struct ofono_emulator *ofono_emulator_create(struct 
ofono_modem *modem,
em->events_mode = 3;/* default mode is forwarding events */
em->cmee_mode = 0;  /* CME ERROR disabled by default */
em->mic_pending = -1;
+   em->sp_pending = -1;
 
em->atom = __ofono_modem_add_atom_offline(modem, atom_t,
emulator_remove, em);
@@ -1243,6 +1289,41 @@ static gboolean audio_property_changed(DBusConnection 
*connection,
} else if (em->mic_pending == value)
em->mic_pending = -1;
em->mic_gain = value;
+   } else if (g_str_equal(property, "SpeakerGain") == TRUE) {
+   DBusMessageIter variant;
+   int value;
+
+   if (!(em->r_features & HFP_HF_FEATURE_REMOTE_VOLUME_CONTROL))
+   return TRUE;
+
+   if (!dbus_message_iter_next(&iter))
+   return TRUE;
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+   return TRUE;
+
+   dbus_message_iter_recurse(&iter, &variant);
+
+   if (dbus_message_iter_get_arg_type(&variant) !=
+   DBUS_TYPE_UINT16)
+   return TRUE;
+
+   dbus_message_iter_get_basic(&variant, &value);
+
+   /* Send unsolicited +VGS only if :
+*   - the value has changed
+*   - and this is not a side effect of AT+VGS
+* But, if we receive a value change while waiting for another
+* pending change, we may have to send +VGS for other changes
+* (multiple AT+VGS received) to keep speaker gain in sync
+*/
+   if (em->sp_pending != value && em->sp_gain != value) {
+   sprintf(buf, "+VGS: %d", value);
+   g_at_server_send_unsolicited(em->server, buf);
+   em->sp_pending = -1;
+   } else if (em->sp_pending == value)
+   em->sp_pending = -1;
+   em->sp_gain = value;
}
 
return TRUE;
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v2 12/12] hfp_ag: Update supported features

2012-03-26 Thread Frédéric Danis
Add ECNR (Echo Cancelation/Noise Reduction) and Inband Ringtone
capabilities to supported features in HFP AG SDP record
---
 plugins/hfp_ag.c |4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/plugins/hfp_ag.c b/plugins/hfp_ag.c
index c12068a..52a8f83 100644
--- a/plugins/hfp_ag.c
+++ b/plugins/hfp_ag.c
@@ -37,7 +37,9 @@
 
 #define AGENT_PATH "/hfp_ag"
 #define VERSION_1_5 0x0105
-#define FEATURES   (HFP_AG_FEATURE_3WAY | HFP_AG_FEATURE_REJECT_CALL | \
+#define FEATURES   (HFP_AG_FEATURE_3WAY | HFP_AG_FEATURE_ECNR | \
+   HFP_AG_FEATURE_IN_BAND_RING_TONE | \
+   HFP_AG_FEATURE_REJECT_CALL | \
HFP_AG_FEATURE_ENHANCED_CALL_STATUS | \
HFP_AG_FEATURE_ENHANCED_CALL_CONTROL | \
HFP_AG_FEATURE_EXTENDED_RES_CODE)
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v2 10/12] emulator: Add AT+VGM support

2012-03-26 Thread Frédéric Danis
---
 src/emulator.c |   81 
 1 files changed, 81 insertions(+), 0 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index 08f63ee..8c5a89a 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -55,6 +55,8 @@ struct ofono_emulator {
int pns_id;
char *audio_transport;
guint audio_watch;
+   int mic_gain;
+   int mic_pending;
 };
 
 struct indicator {
@@ -948,6 +950,48 @@ fail:
};
 }
 
+static void vgm_cb(GAtServer *server, GAtServerRequestType type,
+   GAtResult *result, gpointer user_data)
+{
+   struct ofono_emulator *em = user_data;
+   GAtResultIter iter;
+   int val;
+
+   if (em->slc == FALSE)
+   goto fail;
+
+   switch (type) {
+   case G_AT_SERVER_REQUEST_TYPE_SET:
+   if (em->audio_transport == NULL)
+   goto fail;
+
+   g_at_result_iter_init(&iter, result);
+   g_at_result_iter_next(&iter, "");
+
+   if (!g_at_result_iter_next_number(&iter, &val))
+   goto fail;
+
+   if (val < 0 || val > 15)
+   goto fail;
+
+   /* check this is last parameter */
+   if (g_at_result_iter_skip_next(&iter))
+   goto fail;
+
+   if (em->mic_pending != -1)
+   ofono_error("Receiving AT+VGM while processing one");
+
+   em->mic_pending = val;
+   audio_transport_set_property(server, em->audio_transport,
+   "MicrophoneGain", DBUS_TYPE_UINT16, &val);
+   break;
+
+   default:
+fail:
+   g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
+   };
+}
+
 static void emulator_add_indicator(struct ofono_emulator *em, const char* name,
int min, int max, int dflt,
gboolean mandatory)
@@ -1051,6 +1095,7 @@ void ofono_emulator_register(struct ofono_emulator *em, 
int fd)
g_at_server_register(em->server, "+CMEE", cmee_cb, em, NULL);
g_at_server_register(em->server, "+BIA", bia_cb, em, NULL);
g_at_server_register(em->server, "+NREC", nrec_cb, em, NULL);
+   g_at_server_register(em->server, "+VGM", vgm_cb, em, NULL);
}
 
__ofono_atom_register(em->atom, emulator_unregister);
@@ -1115,6 +1160,7 @@ struct ofono_emulator *ofono_emulator_create(struct 
ofono_modem *modem,
em->l_features |= HFP_AG_FEATURE_EXTENDED_RES_CODE;
em->events_mode = 3;/* default mode is forwarding events */
em->cmee_mode = 0;  /* CME ERROR disabled by default */
+   em->mic_pending = -1;
 
em->atom = __ofono_modem_add_atom_offline(modem, atom_t,
emulator_remove, em);
@@ -1162,6 +1208,41 @@ static gboolean audio_property_changed(DBusConnection 
*connection,
 
sprintf(buf, "+BSIR: %d", value);
g_at_server_send_unsolicited(em->server, buf);
+   } else if (g_str_equal(property, "MicrophoneGain") == TRUE) {
+   DBusMessageIter variant;
+   int value;
+
+   if (!(em->r_features & HFP_HF_FEATURE_REMOTE_VOLUME_CONTROL))
+   return TRUE;
+
+   if (!dbus_message_iter_next(&iter))
+   return TRUE;
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+   return TRUE;
+
+   dbus_message_iter_recurse(&iter, &variant);
+
+   if (dbus_message_iter_get_arg_type(&variant) !=
+   DBUS_TYPE_UINT16)
+   return TRUE;
+
+   dbus_message_iter_get_basic(&variant, &value);
+
+   /* Send unsolicited +VGM only if :
+*   - the value has changed
+*   - and this is not a side effect of AT+VGM
+* But, if we receive a value change while waiting for another
+* pending change, we may have to send +VGM for other changes
+* (multiple AT+VGM received) to keep mic gain in sync
+*/
+   if (em->mic_pending != value && em->mic_gain != value) {
+   sprintf(buf, "+VGM: %d", value);
+   g_at_server_send_unsolicited(em->server, buf);
+   em->mic_pending = -1;
+   } else if (em->mic_pending == value)
+   em->mic_pending = -1;
+   em->mic_gain = value;
}
 
return TRUE;
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v2 09/12] emulator: Add +BSIR support

2012-03-26 Thread Frédéric Danis
---
 src/emulator.c |   58 
 1 files changed, 58 insertions(+), 0 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index c5ec105..08f63ee 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -54,6 +54,7 @@ struct ofono_emulator {
gboolean ccwa;
int pns_id;
char *audio_transport;
+   guint audio_watch;
 };
 
 struct indicator {
@@ -1071,9 +1072,15 @@ void ofono_emulator_register(struct ofono_emulator *em, 
int fd)
 static void emulator_remove(struct ofono_atom *atom)
 {
struct ofono_emulator *em = __ofono_atom_get_data(atom);
+   DBusConnection *connection;
 
DBG("atom: %p", atom);
 
+   connection = ofono_dbus_get_connection();
+
+   if (em->audio_watch)
+   g_dbus_remove_watch(connection, em->audio_watch);
+
g_free(em->audio_transport);
g_free(em);
 }
@@ -1101,6 +1108,7 @@ struct ofono_emulator *ofono_emulator_create(struct 
ofono_modem *modem,
em->type = type;
em->l_features |= HFP_AG_FEATURE_3WAY;
em->l_features |= HFP_AG_FEATURE_ECNR;
+   em->l_features |= HFP_AG_FEATURE_IN_BAND_RING_TONE;
em->l_features |= HFP_AG_FEATURE_REJECT_CALL;
em->l_features |= HFP_AG_FEATURE_ENHANCED_CALL_STATUS;
em->l_features |= HFP_AG_FEATURE_ENHANCED_CALL_CONTROL;
@@ -1119,10 +1127,60 @@ void ofono_emulator_remove(struct ofono_emulator *em)
__ofono_atom_free(em->atom);
 }
 
+static gboolean audio_property_changed(DBusConnection *connection,
+   DBusMessage *message, void *user_data)
+{
+   struct ofono_emulator *em = user_data;
+   const char *property;
+   char buf[10];
+   DBusMessageIter iter;
+
+   dbus_message_iter_init(message, &iter);
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+   return FALSE;
+
+   dbus_message_iter_get_basic(&iter, &property);
+
+   if (g_str_equal(property, "InbandRingtone") == TRUE) {
+   DBusMessageIter variant;
+   gboolean value;
+
+   if (!dbus_message_iter_next(&iter))
+   return TRUE;
+
+   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+   return TRUE;
+
+   dbus_message_iter_recurse(&iter, &variant);
+
+   if (dbus_message_iter_get_arg_type(&variant) !=
+   DBUS_TYPE_BOOLEAN)
+   return TRUE;
+
+   dbus_message_iter_get_basic(&iter, &value);
+
+   sprintf(buf, "+BSIR: %d", value);
+   g_at_server_send_unsolicited(em->server, buf);
+   }
+
+   return TRUE;
+}
+
 void ofono_emulator_set_audio_transport(struct ofono_emulator *em,
const char *path)
 {
+   DBusConnection *connection;
+
em->audio_transport = g_strdup(path);
+
+   connection = ofono_dbus_get_connection();
+
+   em->audio_watch = g_dbus_add_signal_watch(connection, NULL, path,
+   BLUEZ_TRANSPORT_INTERFACE,
+   "PropertyChanged",
+   audio_property_changed, em,
+   NULL);
 }
 
 void ofono_emulator_send_final(struct ofono_emulator *em,
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v2 08/12] emulator: Add AT+NREC support

2012-03-26 Thread Frédéric Danis
---
 src/emulator.c |  120 
 1 files changed, 120 insertions(+), 0 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index dc3c10d..c5ec105 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -33,6 +33,7 @@
 #include "common.h"
 #include "gatserver.h"
 #include "gatppp.h"
+#include "../plugins/bluetooth.h"
 
 #define RING_TIMEOUT 3
 
@@ -312,6 +313,85 @@ error:
}
 }
 
+static void audio_transport_set_property_cb(DBusPendingCall *call,
+   gpointer user_data)
+{
+   GAtServer *server = user_data;
+   DBusMessage *reply;
+   struct DBusError derr;
+   GAtServerResult result;
+
+   reply = dbus_pending_call_steal_reply(call);
+
+   dbus_error_init(&derr);
+
+   if (dbus_set_error_from_message(&derr, reply)) {
+   ofono_error("MediaTransport.SetProperties replied an error: " \
+   "%s, %s", derr.name, derr.message);
+   dbus_error_free(&derr);
+   result = G_AT_SERVER_RESULT_ERROR;
+   } else
+   result = G_AT_SERVER_RESULT_OK;
+
+   g_at_server_send_final(server, result);
+
+   dbus_message_unref(reply);
+}
+
+static void audio_transport_set_property(GAtServer *server, const char *path,
+   const char *name, int type,
+   const void *value)
+{
+   DBusMessage *msg;
+   DBusMessageIter iter, var;
+   const char *str_type;
+   DBusConnection *connection;
+   DBusPendingCall *c;
+
+   if (path == NULL)
+   return;
+
+   switch (type) {
+   case DBUS_TYPE_BOOLEAN:
+   str_type = DBUS_TYPE_BOOLEAN_AS_STRING;
+   break;
+
+   case DBUS_TYPE_UINT16:
+   str_type = DBUS_TYPE_UINT16_AS_STRING;
+   break;
+
+   default:
+   return;
+   }
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE, path,
+   BLUEZ_TRANSPORT_INTERFACE, "SetProperty");
+   if (msg == NULL)
+   return;
+
+   dbus_message_iter_init_append(msg, &iter);
+   dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
+
+   dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, str_type,
+   &var);
+   dbus_message_iter_append_basic(&var, type, value);
+   dbus_message_iter_close_container(&iter, &var);
+
+   connection = ofono_dbus_get_connection();
+
+   if (!dbus_connection_send_with_reply(connection, msg, &c, -1)) {
+   ofono_error("Sending SetProperty failed");
+   goto fail;
+   }
+
+   dbus_pending_call_set_notify(c, audio_transport_set_property_cb, server,
+   NULL);
+   dbus_pending_call_unref(c);
+
+fail:
+   dbus_message_unref(msg);
+}
+
 static struct indicator *find_indicator(struct ofono_emulator *em,
const char *name, int *index)
 {
@@ -829,6 +909,44 @@ fail:
}
 }
 
+static void nrec_cb(GAtServer *server, GAtServerRequestType type,
+   GAtResult *result, gpointer user_data)
+{
+   struct ofono_emulator *em = user_data;
+   GAtResultIter iter;
+   int val;
+
+   if (em->slc == FALSE)
+   goto fail;
+
+   switch (type) {
+   case G_AT_SERVER_REQUEST_TYPE_SET:
+   if (em->audio_transport == NULL)
+   goto fail;
+
+   g_at_result_iter_init(&iter, result);
+   g_at_result_iter_next(&iter, "");
+
+   if (!g_at_result_iter_next_number(&iter, &val))
+   goto fail;
+
+   if (val != 0 && val != 1)
+   goto fail;
+
+   /* check this is last parameter */
+   if (g_at_result_iter_skip_next(&iter))
+   goto fail;
+
+   audio_transport_set_property(server, em->audio_transport,
+   "NREC", DBUS_TYPE_BOOLEAN, &val);
+   break;
+
+   default:
+fail:
+   g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
+   };
+}
+
 static void emulator_add_indicator(struct ofono_emulator *em, const char* name,
int min, int max, int dflt,
gboolean mandatory)
@@ -931,6 +1049,7 @@ void ofono_emulator_register(struct ofono_emulator *em, 
int fd)
g_at_server_register(em->server, "+CCWA", ccwa_cb, em, NULL);
g_at_server_register(em->server, "+CMEE", cmee_cb, em, NULL);
g_at_server_register(em->server, "+BIA", bia_cb, em, NULL);
+   g_at_server_register(em->server, "+NREC", nrec_cb, em, NULL);
}
 
__ofono_

[RFC v2 07/12] hfp_ag: Add media transport support

2012-03-26 Thread Frédéric Danis
---
 plugins/hfp_ag.c |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/plugins/hfp_ag.c b/plugins/hfp_ag.c
index ea9c112..c12068a 100644
--- a/plugins/hfp_ag.c
+++ b/plugins/hfp_ag.c
@@ -82,6 +82,7 @@ static DBusMessage 
*hfp_ag_agent_new_connection(DBusConnection *conn,
return __ofono_error_failed(msg);
 
ofono_emulator_register(em, fd);
+   ofono_emulator_set_audio_transport(em, path);
 
return dbus_message_new_method_return(msg);
 }
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v2 06/12] emulator: Add audio transport set

2012-03-26 Thread Frédéric Danis
---
 src/emulator.c |8 
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index e7c7d41..dc3c10d 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -52,6 +52,7 @@ struct ofono_emulator {
gboolean clip;
gboolean ccwa;
int pns_id;
+   char *audio_transport;
 };
 
 struct indicator {
@@ -954,6 +955,7 @@ static void emulator_remove(struct ofono_atom *atom)
 
DBG("atom: %p", atom);
 
+   g_free(em->audio_transport);
g_free(em);
 }
 
@@ -997,6 +999,12 @@ void ofono_emulator_remove(struct ofono_emulator *em)
__ofono_atom_free(em->atom);
 }
 
+void ofono_emulator_set_audio_transport(struct ofono_emulator *em,
+   const char *path)
+{
+   em->audio_transport = g_strdup(path);
+}
+
 void ofono_emulator_send_final(struct ofono_emulator *em,
const struct ofono_error *final)
 {
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v2 05/12] include: Add audio transport set API

2012-03-26 Thread Frédéric Danis
---
 include/emulator.h |3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/include/emulator.h b/include/emulator.h
index 5cd894b..4b78667 100644
--- a/include/emulator.h
+++ b/include/emulator.h
@@ -72,6 +72,9 @@ struct ofono_emulator *ofono_emulator_create(struct 
ofono_modem *modem,
 
 void ofono_emulator_register(struct ofono_emulator *em, int fd);
 
+void ofono_emulator_set_audio_transport(struct ofono_emulator *em,
+   const char *path);
+
 void ofono_emulator_remove(struct ofono_emulator *em);
 
 void ofono_emulator_send_final(struct ofono_emulator *em,
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v2 04/12] bluetooth: Add org.bluez.MediaTransport interface

2012-03-26 Thread Frédéric Danis
---
 plugins/bluetooth.h |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/plugins/bluetooth.h b/plugins/bluetooth.h
index f81fc99..ee3c71e 100644
--- a/plugins/bluetooth.h
+++ b/plugins/bluetooth.h
@@ -30,6 +30,7 @@
 #defineBLUEZ_SERVICE_INTERFACE BLUEZ_SERVICE ".Service"
 #defineBLUEZ_TELEPHONY_INTERFACE   BLUEZ_SERVICE ".Telephony"
 #defineBLUEZ_TELEPHONY_AGENT_INTERFACE BLUEZ_SERVICE ".TelephonyAgent"
+#defineBLUEZ_TRANSPORT_INTERFACE   BLUEZ_SERVICE ".MediaTransport"
 
 #define DBUS_TIMEOUT 15
 
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC v2 03/12] hfp_ag: Update to org.bluez.Telephony interface

2012-03-26 Thread Frédéric Danis
Bluez moves agent registration from a per device interface to
a per adapter interface.
Update hfp_ag modem emulator to reflect this change.
---
 plugins/hfp_ag.c |  126 --
 1 files changed, 56 insertions(+), 70 deletions(-)

diff --git a/plugins/hfp_ag.c b/plugins/hfp_ag.c
index c2d1d30..ea9c112 100644
--- a/plugins/hfp_ag.c
+++ b/plugins/hfp_ag.c
@@ -35,97 +35,83 @@
 
 #include "bluetooth.h"
 
-#define HFP_AG_CHANNEL 13
+#define AGENT_PATH "/hfp_ag"
+#define VERSION_1_5 0x0105
+#define FEATURES   (HFP_AG_FEATURE_3WAY | HFP_AG_FEATURE_REJECT_CALL | \
+   HFP_AG_FEATURE_ENHANCED_CALL_STATUS | \
+   HFP_AG_FEATURE_ENHANCED_CALL_CONTROL | \
+   HFP_AG_FEATURE_EXTENDED_RES_CODE)
+
+#ifndef DBUS_TYPE_UNIX_FD
+#define DBUS_TYPE_UNIX_FD -1
+#endif
 
-static struct server *server;
 static guint modemwatch_id;
 static GList *modems;
 static GHashTable *sim_hash = NULL;
 
-static const gchar *hfp_ag_record =
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"  \n"
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n";
-
-static void hfp_ag_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
+static DBusMessage *hfp_ag_agent_new_connection(DBusConnection *conn,
+   DBusMessage *msg, void *data)
 {
-   struct ofono_modem *modem;
-   struct ofono_emulator *em;
int fd;
+   const char *device, *uuid;
+   const char *path = NULL;
+   guint16 version = 0;
+   guint16 features = 0;
+   struct ofono_emulator *em;
+   struct ofono_modem *modem;
 
-   DBG("");
+   fd = bluetooth_parse_newconnection_message(msg, &device, &uuid,
+   &version, &features, &path);
+   if (fd < 0)
+   return __ofono_error_invalid_args(msg);
 
-   if (err) {
-   DBG("%s", err->message);
-   return;
-   }
+   DBG("New connection for %s on %s (version 0x%04X, features 0x%02X, " \
+   "media transport path: %s)",
+   device, uuid, version, features, path);
 
/* Pick the first voicecall capable modem */
modem = modems->data;
if (modem == NULL)
-   return;
+   return __ofono_error_failed(msg);
 
DBG("Picked modem %p for emulator", modem);
 
em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_HFP);
if (em == NULL)
-   return;
-
-   fd = g_io_channel_unix_get_fd(io);
-   g_io_channel_set_close_on_unref(io, FALSE);
+   return __ofono_error_failed(msg);
 
ofono_emulator_register(em, fd);
+
+   return dbus_message_new_method_return(msg);
 }
 
+static DBusMessage *hfp_ag_agent_release(DBusConnection *conn,
+   DBusMessage *msg, void *data)
+{
+   DBG("");
+
+   return dbus_message_new_method_return(msg);
+}
+
+static GDBusMethodTable agent_methods[] = {
+   { "NewConnection", "ha{sv}", "", hfp_ag_agent_new_connection,
+   G_DBUS_METHOD_FLAG_ASYNC },
+   { "Release", "", "", hfp_ag_agent_release },
+   { NULL, NULL, NULL, NULL }
+};
+
 static void sim_state_watch(enum ofono_sim_state new_state, void *data)
 {
struct ofono_modem *modem = data;
 
if (new_state != OFONO_SIM_STATE_READY) {
+   if (modems == NULL)
+   return;
+
modems = g_list_remove(modems, modem);
-   if (modems == NULL && server != NULL) {
-   bluetooth_unregister_server(server);
-   server = NULL;
-   }
+   if (modems == NULL)
+   bluetooth_unregister_telephony_agent(AGENT_PATH);
 
return;
}
@@ -138,8 +124,9 @@ static void sim_state_watch(enum ofono_sim_state new_state, 
void *data)
if (modems->next != NULL)
return;
 
-   server = bluetooth_register_server(HFP_AG_CHANNEL, hfp_ag_record,
-   hfp_ag_connect_cb, NULL);
+   bluetooth_register_telephony_agent(AGENT_PATH, HFP_AG_UUID,
+   VERSION_1_5, FEATURES,
+   agent_methods, NULL, NULL);
 }
 
 static gboolean sim_watch_remove(gpointer key, gpointer value,
@@ -192,6 +179,9 @@ static void call_modemwatch(struct ofono_modem *modem, void 
*user)
 
 static int hfp_ag_init(void)
 {
+   if (DBUS_TYPE_UNIX_FD < 0)
+   return -EBADF;
+
sim_hash = g_

[RFC v2 02/12] hfp_hf: Update to org.bluez.Telephony interface

2012-03-26 Thread Frédéric Danis
Bluez moves agent registration from a per device interface to
a per adapter interface.
Update hfp_hf modem to reflect this change.
---
 plugins/hfp_hf.c |  165 -
 1 files changed, 62 insertions(+), 103 deletions(-)

diff --git a/plugins/hfp_hf.c b/plugins/hfp_hf.c
index 48a734a..7c3747b 100644
--- a/plugins/hfp_hf.c
+++ b/plugins/hfp_hf.c
@@ -51,7 +51,7 @@
 
 #defineBLUEZ_GATEWAY_INTERFACE BLUEZ_SERVICE 
".HandsfreeGateway"
 
-#define HFP_AGENT_INTERFACE "org.bluez.HandsfreeAgent"
+#define HFP_AGENT_PATH "/hfp_hf"
 #define HFP_AGENT_ERROR_INTERFACE "org.bluez.Error"
 
 #ifndef DBUS_TYPE_UNIX_FD
@@ -66,7 +66,6 @@ struct hfp_data {
char *handsfree_path;
char *handsfree_address;
DBusMessage *slc_msg;
-   gboolean agent_registered;
DBusPendingCall *call;
 };
 
@@ -158,52 +157,6 @@ static int service_level_connection(struct ofono_modem 
*modem, int fd)
return -EINPROGRESS;
 }
 
-static DBusMessage *hfp_agent_new_connection(DBusConnection *conn,
-   DBusMessage *msg, void *data)
-{
-   int fd, err;
-   struct ofono_modem *modem = data;
-   struct hfp_data *hfp_data = ofono_modem_get_data(modem);
-   guint16 version;
-
-   if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UNIX_FD, &fd,
-   DBUS_TYPE_UINT16, &version, DBUS_TYPE_INVALID))
-   return __ofono_error_invalid_args(msg);
-
-   hfp_slc_info_init(&hfp_data->info, version);
-
-   err = service_level_connection(modem, fd);
-   if (err < 0 && err != -EINPROGRESS)
-   return __ofono_error_failed(msg);
-
-   hfp_data->slc_msg = msg;
-   dbus_message_ref(msg);
-
-   return NULL;
-}
-
-static DBusMessage *hfp_agent_release(DBusConnection *conn,
-   DBusMessage *msg, void *data)
-{
-   struct ofono_modem *modem = data;
-   struct hfp_data *hfp_data = ofono_modem_get_data(modem);
-   const char *obj_path = ofono_modem_get_path(modem);
-
-   g_dbus_unregister_interface(connection, obj_path, HFP_AGENT_INTERFACE);
-   hfp_data->agent_registered = FALSE;
-
-   ofono_modem_remove(modem);
-
-   return dbus_message_new_method_return(msg);
-}
-
-static GDBusMethodTable agent_methods[] = {
-   { "NewConnection", "hq", "", hfp_agent_new_connection,
-   G_DBUS_METHOD_FLAG_ASYNC },
-   { "Release", "", "", hfp_agent_release },
-   { NULL, NULL, NULL, NULL }
-};
-
 static int hfp_hf_probe(const char *device, const char *dev_addr,
const char *adapter_addr, const char *alias)
 {
@@ -295,77 +248,23 @@ static void hfp_hf_set_alias(const char *device, const 
char *alias)
ofono_modem_set_name(modem, alias);
 }
 
-static int hfp_register_ofono_handsfree(struct ofono_modem *modem)
-{
-   const char *obj_path = ofono_modem_get_path(modem);
-   struct hfp_data *data = ofono_modem_get_data(modem);
-   DBusMessage *msg;
-
-   DBG("Registering oFono Agent to bluetooth daemon");
-
-   msg = dbus_message_new_method_call(BLUEZ_SERVICE, data->handsfree_path,
-   BLUEZ_GATEWAY_INTERFACE, "RegisterAgent");
-   if (msg == NULL)
-   return -ENOMEM;
-
-   dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &obj_path,
-   DBUS_TYPE_INVALID);
-
-   g_dbus_send_message(connection, msg);
-   return 0;
-}
-
-static int hfp_unregister_ofono_handsfree(struct ofono_modem *modem)
-{
-   const char *obj_path = ofono_modem_get_path(modem);
-   struct hfp_data *data = ofono_modem_get_data(modem);
-   DBusMessage *msg;
-
-   DBG("Unregistering oFono Agent from bluetooth daemon");
-
-   msg = dbus_message_new_method_call(BLUEZ_SERVICE, data->handsfree_path,
-   BLUEZ_GATEWAY_INTERFACE, "UnregisterAgent");
-   if (msg == NULL)
-   return -ENOMEM;
-
-   dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &obj_path,
-   DBUS_TYPE_INVALID);
-
-   g_dbus_send_message(connection, msg);
-   return 0;
-}
-
 static int hfp_probe(struct ofono_modem *modem)
 {
-   const char *obj_path = ofono_modem_get_path(modem);
struct hfp_data *data = ofono_modem_get_data(modem);
 
if (data == NULL)
return -EINVAL;
 
-   g_dbus_register_interface(connection, obj_path, HFP_AGENT_INTERFACE,
-   agent_methods, NULL, NULL, modem, NULL);
-
-   data->agent_registered = TRUE;
-
-   if (hfp_register_ofono_handsfree(modem) != 0)
-   return -EINVAL;
-
return 0;
 }
 
 static void hfp_remove(struct ofono_modem *modem)
 {
struct hfp_data *data = ofono_modem_get_data(modem);
-   const char *obj_path = ofono_modem_get_path(modem);
 
if (data->call != NULL)

[RFC v2 01/12] bluetooth: Add org.bluez.Telephony helpers

2012-03-26 Thread Frédéric Danis
Add function to register/unregister Telephony agent to BlueZ
---
 plugins/bluetooth.c |  199 +++
 plugins/bluetooth.h |   14 
 2 files changed, 213 insertions(+), 0 deletions(-)

diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index dbf79eb..0bde1a5 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -44,6 +44,7 @@ static GHashTable *uuid_hash = NULL;
 static GHashTable *adapter_address_hash = NULL;
 static gint bluetooth_refcount;
 static GSList *server_list = NULL;
+static GSList *telephony_list = NULL;
 static const char *adapter_any_name = "any";
 static char *adapter_any_path;
 
@@ -65,6 +66,13 @@ struct cb_data {
GIOChannel *io;
 };
 
+struct agent {
+   char *path;
+   char *uuid;
+   guint16 version;
+   guint16 features;
+};
+
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
char *buf, int size)
 {
@@ -146,6 +154,60 @@ fail:
return err;
 }
 
+static void register_telephony_agent(const char *path, const char *handle,
+   struct agent *agent)
+{
+   DBusMessage *msg;
+   DBusMessageIter iter, dict;
+
+   DBG("Registering oFono Agent for %s to %s", agent->uuid, path);
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE, path,
+   BLUEZ_TELEPHONY_INTERFACE, "RegisterAgent");
+   if (msg == NULL)
+   return;
+
+   dbus_message_iter_init_append(msg, &iter);
+
+   dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+   &agent->path);
+
+   dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+   DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+   DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+   DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+   ofono_dbus_dict_append(&dict, "UUID", DBUS_TYPE_STRING, &agent->uuid);
+
+   ofono_dbus_dict_append(&dict, "Version", DBUS_TYPE_UINT16,
+   &agent->version);
+   ofono_dbus_dict_append(&dict, "Features", DBUS_TYPE_UINT16,
+   &agent->features);
+
+   dbus_message_iter_close_container(&iter, &dict);
+
+   g_dbus_send_message(connection, msg);
+}
+
+static void unregister_telephony_agent(const char *path, const char *handle,
+   struct agent *agent)
+{
+   DBusMessage *msg;
+
+   DBG("Unregistering oFono Agent for %s from %s", agent->uuid, path);
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE, path,
+   BLUEZ_TELEPHONY_INTERFACE,
+   "UnregisterAgent");
+   if (msg == NULL)
+   return;
+
+   dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &agent->path,
+   DBUS_TYPE_INVALID);
+
+   g_dbus_send_message(connection, msg);
+}
+
 typedef void (*PropertyHandler)(DBusMessageIter *iter, gpointer user_data);
 
 struct property_handler {
@@ -702,6 +764,7 @@ static gboolean adapter_added(DBusConnection *connection, 
DBusMessage *message,
void *user_data)
 {
const char *path;
+   GSList *l;
 
dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_INVALID);
@@ -710,6 +773,9 @@ static gboolean adapter_added(DBusConnection *connection, 
DBusMessage *message,
"GetProperties", NULL, adapter_properties_cb,
g_strdup(path), g_free, -1, DBUS_TYPE_INVALID);
 
+   for (l = telephony_list; l; l = l->next)
+   register_telephony_agent(path, NULL, l->data);
+
return TRUE;
 }
 
@@ -982,5 +1048,138 @@ void bluetooth_unregister_server(struct server *server)
bluetooth_unref();
 }
 
+int bluetooth_parse_newconnection_message(DBusMessage *msg, const char 
**device,
+   const char **uuid, guint16 *version,
+   guint16 *features,
+   const char **transport_path)
+{
+   DBusMessageIter args, props;
+   int fd;
+   gboolean has_device = FALSE;
+   gboolean has_uuid = FALSE;
+
+   dbus_message_iter_init(msg, &args);
+
+   if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_UNIX_FD)
+   return -EINVAL;
+
+   dbus_message_iter_get_basic(&args, &fd);
+   dbus_message_iter_next(&args);
+
+   dbus_message_iter_recurse(&args, &props);
+   if (dbus_message_iter_get_arg_type(&props) != DBUS_TYPE_DICT_ENTRY)
+   return -EINVAL;
+
+   while (dbus_message_iter_get_arg_type(&props) == DBUS_TYPE_DICT_ENTRY) {
+   const char *key;
+ 

[RFC v2 00/12] org.bluez.Telephony interface integration

2012-03-26 Thread Frédéric Danis
Those patches integrates the future org.bluez.Telephony interface into
oFono for HFP HF and HFP AG plugins.

For HFP AG plugin, the bluetooth rfcomm server is replaced by a
Telephony Agent registered to org.bluez.Telephony.
For HFP HF plugin, RegisterAgent call of org.bluez.HandsfreeGateway is
replaced by the one of org.bluez.Telephony

Since latest RFC :
- add support of org.bluez.MediaTransport interface in emulator.
  This allows support of audio related functions with the new
  architecture.
- add support for AT+NREC command
- add support of In-band ring tone (+BSIR event)
- add support of volume management (AT+VGS and AT+VGM commands,
  +VGS and +VGM events)

Any comments appreciated.

Frédéric Danis (12):
  bluetooth: Add org.bluez.Telephony helpers
  hfp_hf: Update to org.bluez.Telephony interface
  hfp_ag: Update to org.bluez.Telephony interface
  bluetooth: Add org.bluez.MediaTransport interface
  include: Add audio transport set API
  emulator: Add audio transport set
  hfp_ag: Add media transport support
  emulator: Add AT+NREC support
  emulator: Add +BSIR support
  emulator: Add AT+VGM support
  emulator: Add AT+VGS support
  hfp_ag: Update supported features

 include/emulator.h  |3 +
 plugins/bluetooth.c |  199 +
 plugins/bluetooth.h |   15 +++
 plugins/hfp_ag.c|  129 +--
 plugins/hfp_hf.c|  165 +---
 src/emulator.c  |  348 +++
 6 files changed, 686 insertions(+), 173 deletions(-)

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH v2 3/3] voicecall: Force callheld update after calls swap

2012-03-14 Thread Frédéric Danis
In HFP spec, a callheld indicator update should be sent after swapping
calls, even if it stays to 1 (AG has both active and held calls).
---
 src/voicecall.c |   78 ---
 1 files changed, 74 insertions(+), 4 deletions(-)

diff --git a/src/voicecall.c b/src/voicecall.c
index dc4fdf5..c8c51f1 100644
--- a/src/voicecall.c
+++ b/src/voicecall.c
@@ -119,6 +119,8 @@ static const char *default_en_list[] = { "911", "112", NULL 
};
 static const char *default_en_list_no_sim[] = { "119", "118", "999", "110",
"08", "000", NULL };
 
+static void send_ciev_after_swap_callback(const struct ofono_error *error,
+   void *data);
 static void generic_callback(const struct ofono_error *error, void *data);
 static void hangup_all_active(const struct ofono_error *error, void *data);
 static void multirelease_callback(const struct ofono_error *err, void *data);
@@ -746,6 +748,17 @@ static void voicecall_emit_multiparty(struct voicecall 
*call, gboolean mpty)
&val);
 }
 
+static void emulator_set_indicator_forced(struct ofono_voicecall *vc,
+   const char *name, int value)
+{
+   struct ofono_modem *modem = __ofono_atom_get_modem(vc->atom);
+   struct ofono_emulator *em;
+
+   em = __ofono_atom_find(OFONO_ATOM_TYPE_EMULATOR_HFP, modem);
+   if (em)
+   ofono_emulator_set_indicator_forced(em, name, value);
+}
+
 static void emulator_call_status_cb(struct ofono_atom *atom, void *data)
 {
struct ofono_emulator *em = __ofono_atom_get_data(atom);
@@ -1615,13 +1628,19 @@ static DBusMessage 
*manager_swap_without_accept(DBusConnection *conn,
DBusMessage *msg, void *data)
 {
struct ofono_voicecall *vc = data;
+   ofono_voicecall_cb_t cb;
 
if (vc->pending || vc->dial_req || vc->pending_em)
return __ofono_error_busy(msg);
 
vc->pending = dbus_message_ref(msg);
 
-   vc->driver->swap_without_accept(vc, generic_callback, vc);
+   if (voicecalls_have_active(vc) && voicecalls_have_held(vc))
+   cb = send_ciev_after_swap_callback;
+   else
+   cb = generic_callback;
+
+   vc->driver->swap_without_accept(vc, cb, vc);
 
return NULL;
 }
@@ -1631,6 +1650,7 @@ static DBusMessage *manager_swap_calls(DBusConnection 
*conn,
DBusMessage *msg, void *data)
 {
struct ofono_voicecall *vc = data;
+   ofono_voicecall_cb_t cb;
 
if (vc->driver->swap_without_accept)
return manager_swap_without_accept(conn, msg, data);
@@ -1646,7 +1666,12 @@ static DBusMessage *manager_swap_calls(DBusConnection 
*conn,
 
vc->pending = dbus_message_ref(msg);
 
-   vc->driver->hold_all_active(vc, generic_callback, vc);
+   if (voicecalls_have_active(vc) && voicecalls_have_held(vc))
+   cb = send_ciev_after_swap_callback;
+   else
+   cb = generic_callback;
+
+   vc->driver->hold_all_active(vc, cb, vc);
 
return NULL;
 }
@@ -2300,6 +2325,28 @@ error:
g_free(v);
 }
 
+static void send_ciev_after_swap_callback(const struct ofono_error *error,
+   void *data)
+{
+   struct ofono_voicecall *vc = data;
+   DBusMessage *reply;
+
+   if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
+   DBG("command failed with error: %s",
+   telephony_error_to_str(error));
+
+   if (error->type == OFONO_ERROR_TYPE_NO_ERROR) {
+   reply = dbus_message_new_method_return(vc->pending);
+   emulator_set_indicator_forced(vc, OFONO_EMULATOR_IND_CALLHELD,
+   OFONO_EMULATOR_CALLHELD_MULTIPLE);
+   } else
+   reply = __ofono_error_failed(vc->pending);
+
+   __ofono_dbus_pending_reply(&vc->pending, reply);
+}
+
+
+
 static void generic_callback(const struct ofono_error *error, void *data)
 {
struct ofono_voicecall *vc = data;
@@ -2801,6 +2848,23 @@ static void sim_watch(struct ofono_atom *atom,
sim_state_watch(ofono_sim_get_state(sim), vc);
 }
 
+static void emulator_send_ciev_after_swap_cb(const struct ofono_error *error,
+   void *data)
+{
+   struct ofono_voicecall *vc = data;
+
+   if (vc->pending_em == NULL)
+   return;
+
+   ofono_emulator_send_final(vc->pending_em, error);
+
+   if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
+   emulator_set_indicator_forced(vc, OFONO_EMULATOR_IND_CALLHELD,
+   OFONO_EMULATOR_CALLHELD_MULTIPLE);
+
+   vc->pending_em = NULL;
+}
+
 static void emulator_generic_cb(const

[PATCH v2 2/3] emulator: Force indicator event implementation

2012-03-14 Thread Frédéric Danis
---
 src/emulator.c |   23 +++
 1 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index 0f1ceca..8df721c 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -1245,3 +1245,26 @@ start_ring:
em->callsetup_source = g_timeout_add_seconds(RING_TIMEOUT,
notify_ring, em);
 }
+
+void ofono_emulator_set_indicator_forced(struct ofono_emulator *em,
+   const char *name, int value)
+{
+   int i;
+   struct indicator *ind;
+   char buf[20];
+
+   ind = find_indicator(em, name, &i);
+
+   if (ind == NULL || value < ind->min || value > ind->max)
+   return;
+
+   ind->value = value;
+
+   if (em->events_mode == 3 && em->events_ind && em->slc && ind->active) {
+   if (!g_at_server_command_pending(em->server)) {
+   sprintf(buf, "+CIEV: %d,%d", i, ind->value);
+   g_at_server_send_unsolicited(em->server, buf);
+   } else
+   ind->deferred = TRUE;
+   }
+}
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH v2 1/3] emulator: Add API to force indicator event

2012-03-14 Thread Frédéric Danis
For AT+CHLD=2, +CIEV unsollicited event for callheld should be sent even
if it does not change
---
 include/emulator.h |3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/include/emulator.h b/include/emulator.h
index 5cd894b..39f4ad7 100644
--- a/include/emulator.h
+++ b/include/emulator.h
@@ -105,6 +105,9 @@ enum ofono_emulator_request_type 
ofono_emulator_request_get_type(
 void ofono_emulator_set_indicator(struct ofono_emulator *em,
const char *name, int value);
 
+void ofono_emulator_set_indicator_forced(struct ofono_emulator *em,
+   const char *name, int value);
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH] phonesim: Fix AT+CHLD=1x

2012-03-13 Thread Frédéric Danis
AT+CHLD=1x should only hangup active call
---
 src/callmanager.cpp |   38 --
 1 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/src/callmanager.cpp b/src/callmanager.cpp
index dfa2b9e..7208100 100644
--- a/src/callmanager.cpp
+++ b/src/callmanager.cpp
@@ -441,7 +441,21 @@ void CallManager::hangupConnectedAndHeld()
 
 void CallManager::hangupCall( int id )
 {
-chld1x( id );
+QList newCallList;
+for ( int index = 0; index < callList.size(); ++index ) {
+   if ( callList[index].id == id ) {
+   callList[index].state = CallState_Hangup;
+   sendState( callList[index] );
+   } else {
+   newCallList += callList[index];
+   }
+}
+callList = newCallList;
+
+if ( !hasCall( CallState_Active ) && !hasCall( CallState_Held ) )
+   waitingToIncoming();
+
+emit callStatesChanged( &callList );
 }
 
 void CallManager::hangupRemote( int id )
@@ -491,8 +505,10 @@ bool CallManager::chld0()
 {
 // If there is an incoming call, then that is the one to hang up.
 int id = idForIncoming();
-if ( id >= 0 )
-return chld1x( id );
+if ( id >= 0 ) {
+hangupCall( id );
+return true;
+}
 
 // Bail out if no held calls.
 if ( !hasCall( CallState_Held ) )
@@ -540,24 +556,18 @@ bool CallManager::chld1()
 
 bool CallManager::chld1x( int x )
 {
-QList newCallList;
-bool found = false;
 for ( int index = 0; index < callList.size(); ++index ) {
-if ( callList[index].id == x ) {
-callList[index].state = CallState_Hangup;
-sendState( callList[index] );
-found = true;
-} else {
-newCallList += callList[index];
+if ( callList[index].id == x && callList[index].state == 
CallState_Active) {
+hangupCall( x );
+return true;
 }
 }
-callList = newCallList;
 
 if ( !hasCall( CallState_Active ) && !hasCall( CallState_Held ) )
-waitingToIncoming();
+   waitingToIncoming();
 
 emit callStatesChanged( &callList );
-return found;
+return false;
 }
 
 bool CallManager::chld2()
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH 4/4] voicecall: Force callheld update after calls swap

2012-03-09 Thread Frédéric Danis
In HFP spec, a callheld indicator update should be sent after swapping
calls, even if callheld value has not changed.
---
 src/voicecall.c |   17 +
 1 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/src/voicecall.c b/src/voicecall.c
index dc4fdf5..c3fbc7b 100644
--- a/src/voicecall.c
+++ b/src/voicecall.c
@@ -746,6 +746,16 @@ static void voicecall_emit_multiparty(struct voicecall 
*call, gboolean mpty)
&val);
 }
 
+static void emulator_indicator_set_forced(struct ofono_voicecall *vc,
+   const char *name)
+{
+   struct ofono_modem *modem = __ofono_atom_get_modem(vc->atom);
+   struct ofono_emulator *em;
+
+   em = __ofono_atom_find(OFONO_ATOM_TYPE_EMULATOR_HFP, modem);
+   ofono_emulator_indicator_set_forced(em, name);
+}
+
 static void emulator_call_status_cb(struct ofono_atom *atom, void *data)
 {
struct ofono_emulator *em = __ofono_atom_get_data(atom);
@@ -1621,6 +1631,8 @@ static DBusMessage 
*manager_swap_without_accept(DBusConnection *conn,
 
vc->pending = dbus_message_ref(msg);
 
+   emulator_indicator_set_forced(vc, OFONO_EMULATOR_IND_CALLHELD);
+
vc->driver->swap_without_accept(vc, generic_callback, vc);
 
return NULL;
@@ -1646,6 +1658,8 @@ static DBusMessage *manager_swap_calls(DBusConnection 
*conn,
 
vc->pending = dbus_message_ref(msg);
 
+   emulator_indicator_set_forced(vc, OFONO_EMULATOR_IND_CALLHELD);
+
vc->driver->hold_all_active(vc, generic_callback, vc);
 
return NULL;
@@ -3080,6 +3094,9 @@ static void emulator_chld_cb(struct ofono_emulator *em,
if (vc->driver->hold_all_active == NULL)
goto fail;
 
+   ofono_emulator_indicator_set_forced(em,
+   OFONO_EMULATOR_IND_CALLHELD);
+
vc->pending_em = em;
vc->driver->hold_all_active(vc,
emulator_generic_cb, vc);
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH 3/4] emulator: Force indicator event implementation

2012-03-09 Thread Frédéric Danis
---
 src/emulator.c |   18 --
 1 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index 0f1ceca..34329f0 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -62,6 +62,7 @@ struct indicator {
gboolean deferred;
gboolean active;
gboolean mandatory;
+   gboolean forced;
 };
 
 static void emulator_debug(const char *str, void *data)
@@ -1181,11 +1182,12 @@ void ofono_emulator_set_indicator(struct ofono_emulator 
*em,
 
ind = find_indicator(em, name, &i);
 
-   if (ind == NULL || ind->value == value || value < ind->min
-   || value > ind->max)
+   if (ind == NULL || (ind->value == value && !ind->forced)
+   || value < ind->min || value > ind->max)
return;
 
ind->value = value;
+   ind->forced = FALSE;
 
call_ind = find_indicator(em, OFONO_EMULATOR_IND_CALL, NULL);
cs_ind = find_indicator(em, OFONO_EMULATOR_IND_CALLSETUP, NULL);
@@ -1245,3 +1247,15 @@ start_ring:
em->callsetup_source = g_timeout_add_seconds(RING_TIMEOUT,
notify_ring, em);
 }
+
+void ofono_emulator_indicator_set_forced(struct ofono_emulator *em,
+   const char *name)
+{
+   struct indicator *ind;
+
+   ind = find_indicator(em, name, NULL);
+   if (ind == NULL)
+   return;
+
+   ind->forced = TRUE;
+}
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH 1/4] voicecall: Improve transitions check

2012-03-09 Thread Frédéric Danis
Indicators should not be updated if:
- multiple separate calls are active at same time
- a conf call and a call are active at same time
- multiple separate calls are held at same time
- a conf call and a call are held at same time
- a conf call has call in active and held state
---
 src/voicecall.c |   29 +
 1 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/src/voicecall.c b/src/voicecall.c
index c128227..dc4fdf5 100644
--- a/src/voicecall.c
+++ b/src/voicecall.c
@@ -779,6 +779,8 @@ static void notify_emulator_call_status(struct 
ofono_voicecall *vc)
unsigned int non_mpty = 0;
gboolean multiparty = FALSE;
gboolean held = FALSE;
+   unsigned int non_mpty_held = 0;
+   gboolean multiparty_held = FALSE;
gboolean incoming = FALSE;
gboolean dialing = FALSE;
gboolean alerting = FALSE;
@@ -805,6 +807,12 @@ static void notify_emulator_call_status(struct 
ofono_voicecall *vc)
 
case CALL_STATUS_HELD:
held = TRUE;
+   if (g_slist_find_custom(vc->multiparty_list,
+   GINT_TO_POINTER(v->call->id),
+   call_compare_by_id))
+   multiparty_held = TRUE;
+   else
+   non_mpty_held++;
break;
 
case CALL_STATUS_DIALING:
@@ -838,6 +846,15 @@ static void notify_emulator_call_status(struct 
ofono_voicecall *vc)
if (waiting && (held == FALSE && call == FALSE))
return;
 
+   if (non_mpty > 1 || (non_mpty && multiparty))
+   return;
+
+   if (non_mpty_held > 1 || (non_mpty_held && multiparty_held))
+   return;
+
+   if (multiparty && multiparty_held)
+   return;
+
data.status = call || held ? OFONO_EMULATOR_CALL_ACTIVE :
OFONO_EMULATOR_CALL_INACTIVE;
 
@@ -864,18 +881,6 @@ static void notify_emulator_call_status(struct 
ofono_voicecall *vc)
if (held)
data.status = call ? OFONO_EMULATOR_CALLHELD_MULTIPLE :
OFONO_EMULATOR_CALLHELD_ON_HOLD;
-   else if (non_mpty > 1 || (non_mpty && multiparty))
-   /*
-* After call swap, it is possible that all calls move
-* temporarily to active state (depending on call state update
-* order), generating an update of callheld indicator to 0.
-* This will fail PTS test TP/TWC/BV-03-I.
-*
-* So, in case of multiple active calls, or an active call with
-* an active mutiparty call, force update of callheld indicator
-* to 2 (intermediate state allowed).
-*/
-   data.status = OFONO_EMULATOR_CALLHELD_ON_HOLD;
else
data.status = OFONO_EMULATOR_CALLHELD_NONE;
 
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH 2/4] emulator: Add API to force indicator event

2012-03-09 Thread Frédéric Danis
For AT+CHLD=2, +CIEV unsollicited event for callheld should be sent even
if it does not change
---
 include/emulator.h |3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/include/emulator.h b/include/emulator.h
index 5cd894b..e6bfcbd 100644
--- a/include/emulator.h
+++ b/include/emulator.h
@@ -105,6 +105,9 @@ enum ofono_emulator_request_type 
ofono_emulator_request_get_type(
 void ofono_emulator_set_indicator(struct ofono_emulator *em,
const char *name, int value);
 
+void ofono_emulator_indicator_set_forced(struct ofono_emulator *em,
+   const char *name);
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH] emulator: fix notify_ring

2012-03-08 Thread Frédéric Danis
notify_ring should not use information from waiting call
---
 src/emulator.c |7 ---
 1 files changed, 0 insertions(+), 7 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index 262e782..0f1ceca 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -421,13 +421,6 @@ static gboolean notify_ring(void *user_data)
 
c = find_call_with_status(em, CALL_STATUS_INCOMING);
 
-   /*
-* In case of waiting call becoming an incoming call, call status
-* change may not have been done yet, so try to find waiting call too
-*/
-   if (c == NULL)
-   c = find_call_with_status(em, CALL_STATUS_WAITING);
-
if (c == NULL)
return TRUE;
 
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH] phonesim: Fix call scripting capability

2012-02-29 Thread Frédéric Danis
---
 doc/scriptable.txt |6 +++---
 src/control.cpp|3 +++
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/doc/scriptable.txt b/doc/scriptable.txt
index 670bd21..95ae1e1 100644
--- a/doc/scriptable.txt
+++ b/doc/scriptable.txt
@@ -7,8 +7,8 @@ call, you have to do some operations manually within phonesim 
GUI).  Below are
 several examples:
 
 1. call.js (stand for incoming call and copy it to /tmp/call/)
-tabRegistration.gbIncomingCall.leCaller.text = "12345";
-tabRegistration.gbIncomingCall.pbIncomingCall.click();
+tabCall.gbIncomingCall.leCaller.text = "12345";
+tabCall.gbIncomingCall.pbIncomingCall.click();
 
 Then set the path of script and run the script with its name:
 
@@ -50,6 +50,6 @@ Reference" for details.
 For example, if you want to know the current incoming number, you may write a
 script as below:
 // number.js
-tabRegistration.gbIncomingCall.leCaller.text
+tabCall.gbIncomingCall.leCaller.text
 
 After running the script the similar way as above, you may get the number.
diff --git a/src/control.cpp b/src/control.cpp
index 2666b4c..ee1e7d8 100644
--- a/src/control.cpp
+++ b/src/control.cpp
@@ -667,6 +667,9 @@ Script::Script(QObject *obj, Ui_ControlBase *ui) : 
QDBusAbstractAdaptor(obj)
 
 QScriptValue qsTab8 = engine.newQObject(ui->tab_8);
 engine.globalObject().setProperty("tabPosition", qsTab8);
+
+QScriptValue qsTab9 = engine.newQObject(ui->tab_9);
+engine.globalObject().setProperty("tabCall", qsTab9);
 }
 
 void Script::SetPath(const QString &path, const QDBusMessage &msg)
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH] emulator: Fix for PTS test TC_AG_TWC_BV_02_I

2012-02-28 Thread Frédéric Danis
RING event should only be sent when callsetup indicator is set to
Incoming and there is no active call.

If call indicator is set to inactive while callsetup is
already set to Incoming (waiting call has generated +CCWA),
RING event should be sent after all calls' state have been updated.

As state of calls are updated one by one, generating multiple calls
to ofono_emulator_set_indicator(), do not call notify_ring() just
after call indicator went from active/held to inactive (only start
ring timer).
In ring_timer(), in case of a call in waiting state, just exit and
wait for next timeout.
---
 src/emulator.c |   21 +++--
 1 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index 262e782..fed699c 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -414,6 +414,13 @@ static gboolean notify_ring(void *user_data)
if (em->type == OFONO_EMULATOR_TYPE_HFP && em->slc == FALSE)
return TRUE;
 
+   /*
+* In case of waiting call becoming an incoming call, call status
+* change may not have been done yet, wait for change has been completed
+*/
+   if (find_call_with_status(em, CALL_STATUS_WAITING))
+   return TRUE;
+
g_at_server_send_unsolicited(em->server, "RING");
 
if (!em->clip)
@@ -421,13 +428,6 @@ static gboolean notify_ring(void *user_data)
 
c = find_call_with_status(em, CALL_STATUS_INCOMING);
 
-   /*
-* In case of waiting call becoming an incoming call, call status
-* change may not have been done yet, so try to find waiting call too
-*/
-   if (c == NULL)
-   c = find_call_with_status(em, CALL_STATUS_WAITING);
-
if (c == NULL)
return TRUE;
 
@@ -1221,10 +1221,10 @@ void ofono_emulator_set_indicator(struct ofono_emulator 
*em,
/*
 * Ring timer should be started when:
 * - callsetup indicator is set to Incoming and there is no active call
-*   (not a waiting call)
+*   (not a waiting call), in this case, a first RING should be sent
+*   just after the +CIEV
 * - or call indicator is set to inactive while callsetup is already
 *   set to Incoming.
-* In those cases, a first RING should be sent just after the +CIEV
 * Ring timer should be stopped for all other values of callsetup
 */
if (waiting)
@@ -1247,8 +1247,9 @@ void ofono_emulator_set_indicator(struct ofono_emulator 
*em,
return;
}
 
-start_ring:
notify_ring(em);
+
+start_ring:
em->callsetup_source = g_timeout_add_seconds(RING_TIMEOUT,
notify_ring, em);
 }
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH] emulator: Fix start of RING event

2012-02-09 Thread Frédéric Danis
RING event should only be sent when callsetup indicator is set to
Incoming and there is no active call.

If call indicator is set to inactive while callsetup is
already set to Incoming (waiting call has generated +CCWA),
no RING event should be sent.

Ref.: PTS test TC_AG_TWC_BV_02_I
---
 src/emulator.c |   18 +++---
 1 files changed, 3 insertions(+), 15 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index 262e782..0fa6eac 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -1219,23 +1219,12 @@ void ofono_emulator_set_indicator(struct ofono_emulator 
*em,
}
 
/*
-* Ring timer should be started when:
-* - callsetup indicator is set to Incoming and there is no active call
-*   (not a waiting call)
-* - or call indicator is set to inactive while callsetup is already
-*   set to Incoming.
+* Ring timer should be started when callsetup indicator is set to
+* Incoming and there is no active call (not a waiting call).
 * In those cases, a first RING should be sent just after the +CIEV
 * Ring timer should be stopped for all other values of callsetup
 */
-   if (waiting)
-   return;
-
-   /* Call state went from active/held + waiting -> incoming */
-   if (call && value == OFONO_EMULATOR_CALL_INACTIVE &&
-   cs_ind->value == OFONO_EMULATOR_CALLSETUP_INCOMING)
-   goto start_ring;
-
-   if (!callsetup)
+   if (!callsetup || waiting)
return;
 
if (value != OFONO_EMULATOR_CALLSETUP_INCOMING) {
@@ -1247,7 +1236,6 @@ void ofono_emulator_set_indicator(struct ofono_emulator 
*em,
return;
}
 
-start_ring:
notify_ring(em);
em->callsetup_source = g_timeout_add_seconds(RING_TIMEOUT,
notify_ring, em);
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH] voicecall: Fix emulator AT+CHUP for HFP

2012-02-09 Thread Frédéric Danis
AT+CHUP should be able to hang-up active or incoming calls
---
 src/voicecall.c |3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/src/voicecall.c b/src/voicecall.c
index 094f41d..e224d3a 100644
--- a/src/voicecall.c
+++ b/src/voicecall.c
@@ -2931,7 +2931,8 @@ static void emulator_chup_cb(struct ofono_emulator *em,
goto done;
}
 
-   if (voicecalls_have_active(vc) == FALSE)
+   if (voicecalls_have_active(vc) == FALSE &&
+   voicecalls_have_incoming(vc) == FALSE)
goto fail;
 
vc->pending_em = em;
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[RFC 3/3] hfp_ag: update to org.bluez.Telephony interface

2012-01-31 Thread Frédéric Danis
Bluez moves agent registration from a per device interface to
a per adapter interface.
Update hfp_ag modem emulator to reflect this change.
---
 plugins/hfp_ag.c |  119 ++---
 1 files changed, 49 insertions(+), 70 deletions(-)

diff --git a/plugins/hfp_ag.c b/plugins/hfp_ag.c
index c2d1d30..b1e8188 100644
--- a/plugins/hfp_ag.c
+++ b/plugins/hfp_ag.c
@@ -35,97 +35,79 @@
 
 #include "bluetooth.h"
 
-#define HFP_AG_CHANNEL 13
+#define AGENT_PATH "/hfp_ag"
+#define VERSION_1_5 0x0105
+#define FEATURES   (HFP_AG_FEATURE_3WAY | HFP_AG_FEATURE_REJECT_CALL | \
+   HFP_AG_FEATURE_ENHANCED_CALL_STATUS | \
+   HFP_AG_FEATURE_ENHANCED_CALL_CONTROL | \
+   HFP_AG_FEATURE_EXTENDED_RES_CODE)
 
-static struct server *server;
 static guint modemwatch_id;
 static GList *modems;
 static GHashTable *sim_hash = NULL;
 
-static const gchar *hfp_ag_record =
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"  \n"
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n"
-"  \n"
-"\n";
-
-static void hfp_ag_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
+static DBusMessage *hfp_ag_agent_new_connection(DBusConnection *conn,
+   DBusMessage *msg, void *data)
 {
-   struct ofono_modem *modem;
-   struct ofono_emulator *em;
int fd;
+   const char *device, *uuid;
+   const char *path = NULL;
+   guint16 version = 0;
+   guint16 features = 0;
+   struct ofono_emulator *em;
+   struct ofono_modem *modem;
 
-   DBG("");
+   fd = bluetooth_parse_newconnection_message(msg, &device, &uuid,
+   &version, &features, &path);
+   if (fd < 0)
+   return __ofono_error_invalid_args(msg);
 
-   if (err) {
-   DBG("%s", err->message);
-   return;
-   }
+   DBG("New connection for %s on %s (version 0x%04X, features 0x%02X, " \
+   "media transport path: %s)",
+   device, uuid, version, features, path);
 
/* Pick the first voicecall capable modem */
modem = modems->data;
if (modem == NULL)
-   return;
+   return __ofono_error_failed(msg);
 
DBG("Picked modem %p for emulator", modem);
 
em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_HFP);
if (em == NULL)
-   return;
-
-   fd = g_io_channel_unix_get_fd(io);
-   g_io_channel_set_close_on_unref(io, FALSE);
+   return __ofono_error_failed(msg);
 
ofono_emulator_register(em, fd);
+
+   return dbus_message_new_method_return(msg);
 }
 
+static DBusMessage *hfp_ag_agent_release(DBusConnection *conn,
+   DBusMessage *msg, void *data)
+{
+   DBG("");
+
+   return dbus_message_new_method_return(msg);
+}
+
+static GDBusMethodTable agent_methods[] = {
+   { "NewConnection", "ha{sv}", "", hfp_ag_agent_new_connection,
+   G_DBUS_METHOD_FLAG_ASYNC },
+   { "Release", "", "", hfp_ag_agent_release },
+   { NULL, NULL, NULL, NULL }
+};
+
 static void sim_state_watch(enum ofono_sim_state new_state, void *data)
 {
struct ofono_modem *modem = data;
 
if (new_state != OFONO_SIM_STATE_READY) {
+   if (modems == NULL)
+   return;
+
modems = g_list_remove(modems, modem);
-   if (modems == NULL && server != NULL) {
-   bluetooth_unregister_server(server);
-   server = NULL;
-   }
+   if (modems == NULL)
+   bluetooth_unregister_telephony_agent(AGENT_PATH);
 
return;
}
@@ -138,8 +120,9 @@ static void sim_state_watch(enum ofono_sim_state new_state, 
void *data)
if (modems->next != NULL)
return;
 
-   server = bluetooth_register_server(HFP_AG_CHANNEL, hfp_ag_record,
-   hfp_ag_connect_cb, NULL);
+   bluetooth_register_telephony_agent(AGENT_PATH, HFP_AG_UUID,
+   VERSION_1_5, FEATURES,
+   agent_methods, NULL, NULL);
 }
 
 static gboolean sim_watch_remove(gpointer key, gpointer value,
@@ -203,14 +186,10 @@ static int hfp_ag_init(void)
 static void hfp_ag_exit(void)
 {
__ofono_modemwatch_remove(modemwatch_id);
+
g_list_free(modems);
g_hash_table_foreach_remove(sim_hash, sim_watch_remove, NULL);
g_hash_table_destroy(sim_hash);
-
-

[RFC 2/3] hfp_hf: update to org.bluez.Telephony interface

2012-01-31 Thread Frédéric Danis
Bluez moves agent registration from a per device interface to
a per adapter interface.
Update hfp_hf modem to reflect this change.
---
 plugins/hfp_hf.c |  165 -
 1 files changed, 62 insertions(+), 103 deletions(-)

diff --git a/plugins/hfp_hf.c b/plugins/hfp_hf.c
index 48a734a..7c3747b 100644
--- a/plugins/hfp_hf.c
+++ b/plugins/hfp_hf.c
@@ -51,7 +51,7 @@
 
 #defineBLUEZ_GATEWAY_INTERFACE BLUEZ_SERVICE 
".HandsfreeGateway"
 
-#define HFP_AGENT_INTERFACE "org.bluez.HandsfreeAgent"
+#define HFP_AGENT_PATH "/hfp_hf"
 #define HFP_AGENT_ERROR_INTERFACE "org.bluez.Error"
 
 #ifndef DBUS_TYPE_UNIX_FD
@@ -66,7 +66,6 @@ struct hfp_data {
char *handsfree_path;
char *handsfree_address;
DBusMessage *slc_msg;
-   gboolean agent_registered;
DBusPendingCall *call;
 };
 
@@ -158,52 +157,6 @@ static int service_level_connection(struct ofono_modem 
*modem, int fd)
return -EINPROGRESS;
 }
 
-static DBusMessage *hfp_agent_new_connection(DBusConnection *conn,
-   DBusMessage *msg, void *data)
-{
-   int fd, err;
-   struct ofono_modem *modem = data;
-   struct hfp_data *hfp_data = ofono_modem_get_data(modem);
-   guint16 version;
-
-   if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UNIX_FD, &fd,
-   DBUS_TYPE_UINT16, &version, DBUS_TYPE_INVALID))
-   return __ofono_error_invalid_args(msg);
-
-   hfp_slc_info_init(&hfp_data->info, version);
-
-   err = service_level_connection(modem, fd);
-   if (err < 0 && err != -EINPROGRESS)
-   return __ofono_error_failed(msg);
-
-   hfp_data->slc_msg = msg;
-   dbus_message_ref(msg);
-
-   return NULL;
-}
-
-static DBusMessage *hfp_agent_release(DBusConnection *conn,
-   DBusMessage *msg, void *data)
-{
-   struct ofono_modem *modem = data;
-   struct hfp_data *hfp_data = ofono_modem_get_data(modem);
-   const char *obj_path = ofono_modem_get_path(modem);
-
-   g_dbus_unregister_interface(connection, obj_path, HFP_AGENT_INTERFACE);
-   hfp_data->agent_registered = FALSE;
-
-   ofono_modem_remove(modem);
-
-   return dbus_message_new_method_return(msg);
-}
-
-static GDBusMethodTable agent_methods[] = {
-   { "NewConnection", "hq", "", hfp_agent_new_connection,
-   G_DBUS_METHOD_FLAG_ASYNC },
-   { "Release", "", "", hfp_agent_release },
-   { NULL, NULL, NULL, NULL }
-};
-
 static int hfp_hf_probe(const char *device, const char *dev_addr,
const char *adapter_addr, const char *alias)
 {
@@ -295,77 +248,23 @@ static void hfp_hf_set_alias(const char *device, const 
char *alias)
ofono_modem_set_name(modem, alias);
 }
 
-static int hfp_register_ofono_handsfree(struct ofono_modem *modem)
-{
-   const char *obj_path = ofono_modem_get_path(modem);
-   struct hfp_data *data = ofono_modem_get_data(modem);
-   DBusMessage *msg;
-
-   DBG("Registering oFono Agent to bluetooth daemon");
-
-   msg = dbus_message_new_method_call(BLUEZ_SERVICE, data->handsfree_path,
-   BLUEZ_GATEWAY_INTERFACE, "RegisterAgent");
-   if (msg == NULL)
-   return -ENOMEM;
-
-   dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &obj_path,
-   DBUS_TYPE_INVALID);
-
-   g_dbus_send_message(connection, msg);
-   return 0;
-}
-
-static int hfp_unregister_ofono_handsfree(struct ofono_modem *modem)
-{
-   const char *obj_path = ofono_modem_get_path(modem);
-   struct hfp_data *data = ofono_modem_get_data(modem);
-   DBusMessage *msg;
-
-   DBG("Unregistering oFono Agent from bluetooth daemon");
-
-   msg = dbus_message_new_method_call(BLUEZ_SERVICE, data->handsfree_path,
-   BLUEZ_GATEWAY_INTERFACE, "UnregisterAgent");
-   if (msg == NULL)
-   return -ENOMEM;
-
-   dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &obj_path,
-   DBUS_TYPE_INVALID);
-
-   g_dbus_send_message(connection, msg);
-   return 0;
-}
-
 static int hfp_probe(struct ofono_modem *modem)
 {
-   const char *obj_path = ofono_modem_get_path(modem);
struct hfp_data *data = ofono_modem_get_data(modem);
 
if (data == NULL)
return -EINVAL;
 
-   g_dbus_register_interface(connection, obj_path, HFP_AGENT_INTERFACE,
-   agent_methods, NULL, NULL, modem, NULL);
-
-   data->agent_registered = TRUE;
-
-   if (hfp_register_ofono_handsfree(modem) != 0)
-   return -EINVAL;
-
return 0;
 }
 
 static void hfp_remove(struct ofono_modem *modem)
 {
struct hfp_data *data = ofono_modem_get_data(modem);
-   const char *obj_path = ofono_modem_get_path(modem);
 
if (data->call != NULL)

[RFC 1/3] bluetooth: add org.bluez.Telephony helpers

2012-01-31 Thread Frédéric Danis
Add function to register/unregister Telephony agent to BlueZ
---
 plugins/bluetooth.c |  198 +++
 plugins/bluetooth.h |   14 
 2 files changed, 212 insertions(+), 0 deletions(-)

diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index dbf79eb..de2eb2c 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -44,6 +44,7 @@ static GHashTable *uuid_hash = NULL;
 static GHashTable *adapter_address_hash = NULL;
 static gint bluetooth_refcount;
 static GSList *server_list = NULL;
+static GSList *telephony_list = NULL;
 static const char *adapter_any_name = "any";
 static char *adapter_any_path;
 
@@ -65,6 +66,13 @@ struct cb_data {
GIOChannel *io;
 };
 
+struct agent {
+   char *path;
+   char *uuid;
+   guint16 version;
+   guint16 features;
+};
+
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
char *buf, int size)
 {
@@ -146,6 +154,60 @@ fail:
return err;
 }
 
+static void register_telephony_agent(const char *path, const char *handle,
+   struct agent *agent)
+{
+   DBusMessage *msg;
+   DBusMessageIter iter, dict;
+
+   DBG("Registering oFono Agent for %s to %s", agent->uuid, path);
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE, path,
+   BLUEZ_TELEPHONY_INTERFACE, "RegisterAgent");
+   if (msg == NULL)
+   return;
+
+   dbus_message_iter_init_append(msg, &iter);
+
+   dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+   &agent->path);
+
+   dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+   DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+   DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+   DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+   ofono_dbus_dict_append(&dict, "UUID", DBUS_TYPE_STRING, &agent->uuid);
+
+   ofono_dbus_dict_append(&dict, "Version", DBUS_TYPE_UINT16,
+   &agent->version);
+   ofono_dbus_dict_append(&dict, "Features", DBUS_TYPE_UINT16,
+   &agent->features);
+
+   dbus_message_iter_close_container(&iter, &dict);
+
+   g_dbus_send_message(connection, msg);
+}
+
+static void unregister_telephony_agent(const char *path, const char *handle,
+   struct agent *agent)
+{
+   DBusMessage *msg;
+
+   DBG("Unregistering oFono Agent for %s from %s", agent->uuid, path);
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE, path,
+   BLUEZ_TELEPHONY_INTERFACE,
+   "UnregisterAgent");
+   if (msg == NULL)
+   return;
+
+   dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &agent->path,
+   DBUS_TYPE_INVALID);
+
+   g_dbus_send_message(connection, msg);
+}
+
 typedef void (*PropertyHandler)(DBusMessageIter *iter, gpointer user_data);
 
 struct property_handler {
@@ -702,6 +764,7 @@ static gboolean adapter_added(DBusConnection *connection, 
DBusMessage *message,
void *user_data)
 {
const char *path;
+   GSList *l;
 
dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_INVALID);
@@ -710,6 +773,9 @@ static gboolean adapter_added(DBusConnection *connection, 
DBusMessage *message,
"GetProperties", NULL, adapter_properties_cb,
g_strdup(path), g_free, -1, DBUS_TYPE_INVALID);
 
+   for (l = telephony_list; l; l = l->next)
+   register_telephony_agent(path, NULL, l->data);
+
return TRUE;
 }
 
@@ -982,5 +1048,137 @@ void bluetooth_unregister_server(struct server *server)
bluetooth_unref();
 }
 
+int bluetooth_parse_newconnection_message(DBusMessage *msg, const char 
**device,
+   const char **uuid, guint16 *version,
+   guint16 *features,
+   const char **transport_path)
+{
+   DBusMessageIter args, props;
+   int fd;
+   gboolean has_device = FALSE;
+   gboolean has_uuid = FALSE;
+
+   dbus_message_iter_init(msg, &args);
+
+   if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_UNIX_FD)
+   return -EINVAL;
+
+   dbus_message_iter_get_basic(&args, &fd);
+   dbus_message_iter_next(&args);
+
+   dbus_message_iter_recurse(&args, &props);
+   if (dbus_message_iter_get_arg_type(&props) != DBUS_TYPE_DICT_ENTRY)
+   return -EINVAL;
+
+   while (dbus_message_iter_get_arg_type(&props) == DBUS_TYPE_DICT_ENTRY) {
+   const char *key;
+ 

[RFC 0/3] org.bluez.Telephony interface integration

2012-01-31 Thread Frédéric Danis
Those patches integrates the future org.bluez.Telephony interface into
oFono for HFP HF and HFP AG plugins.

For HFP AG plugin, the bluetooth rfcomm server is replaced by a
Telephony Agent registered to org.bluez.Telephony.
For HFP HF plugin, RegisterAgent call of org.bluez.HandsfreeGateway is
replaced by the one of org.bluez.Telephony

Frédéric Danis (3):
  bluetooth: add org.bluez.Telephony helpers
  hfp_hf: update to org.bluez.Telephony interface
  hfp_ag: update to org.bluez.Telephony interface

 plugins/bluetooth.c |  198 +++
 plugins/bluetooth.h |   14 
 plugins/hfp_ag.c|  119 +--
 plugins/hfp_hf.c|  165 --
 4 files changed, 323 insertions(+), 173 deletions(-)

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH 3/4] hfp_ag: update SDP record to version 1.6

2011-08-31 Thread Frédéric Danis
---
 plugins/hfp_ag.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/plugins/hfp_ag.c b/plugins/hfp_ag.c
index dc65fde..96230fc 100644
--- a/plugins/hfp_ag.c
+++ b/plugins/hfp_ag.c
@@ -68,7 +68,7 @@ static const gchar *hfp_ag_record =
 "\n"
 "  \n"
 "\n"
-"\n"
+"\n"
 "  \n"
 "\n"
 "  \n"
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH 4/4] TODO: mark HFP AG 1.6 indicator activation as done

2011-08-31 Thread Frédéric Danis
---
 TODO |7 ---
 doc/features.txt |8 
 2 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/TODO b/TODO
index 516d325..5672259 100644
--- a/TODO
+++ b/TODO
@@ -148,13 +148,6 @@ Modem Emulator
   Complexity: C4
   Priority: Medium
 
-- Support new HFP 1.6 AG command related to indicators (AT+BIA).
-
-  Complexity: C1
-  Priority: Low
-  Owner: Frédéric Danis 
-  Depends: HFP AG emulator
-
 - Support new HFP 1.6 AG commands allowing to publish, select and connect audio
   codecs (AT+BAC, AT+BCS, +BCS, AT+BCC). This will need to interact with audio
   framework.
diff --git a/doc/features.txt b/doc/features.txt
index b8bcdb1..ad4d176 100644
--- a/doc/features.txt
+++ b/doc/features.txt
@@ -675,11 +675,11 @@ Modem Emulator
 ==
 
 - Support for Bluetooth HandsFree Profile Audio Gateway (HFP AG).  oFono
-  supports the underlying AT command protocol specified by BT HFP version 1.5.
+  supports the underlying AT command protocol specified by BT HFP version 1.6.
   Supported features include 3-way calling, ability to reject a call,
-  enhanced call status, enhanced call control and report of extended error
-  results code.  Audio management is assumed to be performed in another system
-  component, e.g. PulseAudio.
+  enhanced call status, enhanced call control, report of extended error results
+  code and indicator activation. Audio management is assumed to be performed in
+  another system component, e.g. PulseAudio.
 
 - Support for Bluetooth DUN profile.  oFono supports the Dial Up Networking
   profile and all mandatory commands specified by BT DUN 1.1.  For a list
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH 1/4] emulator: add AT+BIA support for HFP

2011-08-31 Thread Frédéric Danis
---
 src/emulator.c |   83 +---
 1 files changed, 73 insertions(+), 10 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index 06ec06c..a907b12 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -60,6 +60,8 @@ struct indicator {
int min;
int max;
gboolean deferred;
+   gboolean active;
+   gboolean mandatory;
 };
 
 static void emulator_debug(const char *str, void *data)
@@ -360,7 +362,8 @@ static void notify_deferred_indicators(GAtServer *server, 
void *user_data)
if (!ind->deferred)
continue;
 
-   if (em->events_mode == 3 && em->events_ind && em->slc) {
+   if (em->events_mode == 3 && em->events_ind && em->slc &&
+   ind->active) {
sprintf(buf, "+CIEV: %d,%d", i, ind->value);
g_at_server_send_unsolicited(em->server, buf);
}
@@ -783,8 +786,60 @@ fail:
}
 }
 
+static void bia_cb(GAtServer *server, GAtServerRequestType type,
+   GAtResult *result, gpointer user_data)
+{
+   struct ofono_emulator *em = user_data;
+
+   switch (type) {
+   case G_AT_SERVER_REQUEST_TYPE_SET:
+   {
+   GAtResultIter iter;
+   GSList *l;
+   struct indicator *ind;
+   int val;
+
+   g_at_result_iter_init(&iter, result);
+   g_at_result_iter_next(&iter, "");
+
+   /* check validity of the request */
+   while (g_at_result_iter_next_number_default(&iter, 0, &val)) {
+   if (val != 0 &&  val != 1)
+   goto fail;
+   }
+
+   if (g_at_result_iter_skip_next(&iter))
+   goto fail;
+
+   /* request is valid, update the indicator activation status */
+   g_at_result_iter_init(&iter, result);
+   g_at_result_iter_next(&iter, "");
+
+   for (l = em->indicators; l; l = l->next) {
+   ind = l->data;
+
+   if (!g_at_result_iter_next_number_default(&iter,
+   ind->active, &val))
+   break;
+
+   if (!ind->mandatory)
+   ind->active = val;
+   }
+
+   g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
+   break;
+   }
+
+   default:
+fail:
+   g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
+   break;
+   }
+}
+
 static void emulator_add_indicator(struct ofono_emulator *em, const char* name,
-   int min, int max, int dflt)
+   int min, int max, int dflt,
+   gboolean mandatory)
 {
struct indicator *ind;
 
@@ -798,6 +853,8 @@ static void emulator_add_indicator(struct ofono_emulator 
*em, const char* name,
ind->min = min;
ind->max = max;
ind->value = dflt;
+   ind->active = TRUE;
+   ind->mandatory = mandatory;
 
em->indicators = g_slist_append(em->indicators, ind);
 }
@@ -860,15 +917,20 @@ void ofono_emulator_register(struct ofono_emulator *em, 
int fd)
em);
 
if (em->type == OFONO_EMULATOR_TYPE_HFP) {
-   emulator_add_indicator(em, OFONO_EMULATOR_IND_SERVICE, 0, 1, 0);
-   emulator_add_indicator(em, OFONO_EMULATOR_IND_CALL, 0, 1, 0);
+   emulator_add_indicator(em, OFONO_EMULATOR_IND_SERVICE, 0, 1, 0,
+   FALSE);
+   emulator_add_indicator(em, OFONO_EMULATOR_IND_CALL, 0, 1, 0,
+   TRUE);
emulator_add_indicator(em, OFONO_EMULATOR_IND_CALLSETUP, 0, 3,
-   0);
+   0, TRUE);
emulator_add_indicator(em, OFONO_EMULATOR_IND_CALLHELD, 0, 2,
-   0);
-   emulator_add_indicator(em, OFONO_EMULATOR_IND_SIGNAL, 0, 5, 0);
-   emulator_add_indicator(em, OFONO_EMULATOR_IND_ROAMING, 0, 1, 0);
-   emulator_add_indicator(em, OFONO_EMULATOR_IND_BATTERY, 0, 5, 5);
+   0, TRUE);
+   emulator_add_indicator(em, OFONO_EMULATOR_IND_SIGNAL, 0, 5, 0,
+   FALSE);
+   emulator_add_indicator(em, OFONO_EMULATOR_IND_ROAMING, 0, 1, 0,
+   FALSE);
+

[PATCH 2/4] include: update HFP features types to version 1.6

2011-08-31 Thread Frédéric Danis
---
 include/types.h |   10 ++
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/include/types.h b/include/types.h
index 536dac7..0a3b72c 100644
--- a/include/types.h
+++ b/include/types.h
@@ -115,7 +115,7 @@ struct ofono_uuid {
unsigned char uuid[OFONO_SHA1_UUID_LEN];
 };
 
-/* HFP AG supported features bitmap. Bluetooth HFP 1.5 spec page 77 */
+/* HFP AG supported features bitmap. Bluetooth HFP 1.6 spec page 88 */
 enum hfp_ag_feature {
HFP_AG_FEATURE_3WAY =   0x1,
HFP_AG_FEATURE_ECNR =   0x2,
@@ -125,10 +125,11 @@ enum hfp_ag_feature {
HFP_AG_FEATURE_REJECT_CALL =0x20,
HFP_AG_FEATURE_ENHANCED_CALL_STATUS =   0x40,
HFP_AG_FEATURE_ENHANCED_CALL_CONTROL =  0x80,
-   HFP_AG_FEATURE_EXTENDED_RES_CODE =  0x100
+   HFP_AG_FEATURE_EXTENDED_RES_CODE =  0x100,
+   HFP_AG_FEATURE_CODEC_NEGOTIATION =  0x200
 };
 
-/* HFP HF supported features bitmap. Bluetooth HFP 1.5 spec page 77 */
+/* HFP HF supported features bitmap. Bluetooth HFP 1.6 spec page 88 */
 enum hfp_hf_feature {
HFP_HF_FEATURE_ECNR =   0x1,
HFP_HF_FEATURE_3WAY =   0x2,
@@ -136,7 +137,8 @@ enum hfp_hf_feature {
HFP_HF_FEATURE_VOICE_RECOGNITION =  0x8,
HFP_HF_FEATURE_REMOTE_VOLUME_CONTROL =  0x10,
HFP_HF_FEATURE_ENHANCED_CALL_STATUS =   0x20,
-   HFP_HF_FEATURE_ENHANCED_CALL_CONTROL =  0x40
+   HFP_HF_FEATURE_ENHANCED_CALL_CONTROL =  0x40,
+   HFP_HF_FEATURE_CODEC_NEGOTIATION =  0x80
 };
 
 const char *ofono_uuid_to_str(const struct ofono_uuid *uuid);
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH v3 2/2] hfp_hf: retrieve AG version

2011-08-08 Thread Frédéric Danis
---
 plugins/hfp_hf.c |9 +
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/plugins/hfp_hf.c b/plugins/hfp_hf.c
index 9fa420a..6516e75 100644
--- a/plugins/hfp_hf.c
+++ b/plugins/hfp_hf.c
@@ -161,11 +161,14 @@ static DBusMessage 
*hfp_agent_new_connection(DBusConnection *conn,
int fd, err;
struct ofono_modem *modem = data;
struct hfp_data *hfp_data = ofono_modem_get_data(modem);
+   guint16 version;
 
if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UNIX_FD, &fd,
-   DBUS_TYPE_INVALID))
+   DBUS_TYPE_UINT16, &version, DBUS_TYPE_INVALID))
return __ofono_error_invalid_args(msg);
 
+   hfp_slc_info_init(&hfp_data->info, version);
+
err = service_level_connection(modem, fd);
if (err < 0 && err != -EINPROGRESS)
return __ofono_error_failed(msg);
@@ -192,7 +195,7 @@ static DBusMessage *hfp_agent_release(DBusConnection *conn,
 }
 
 static GDBusMethodTable agent_methods[] = {
-   { "NewConnection", "h", "", hfp_agent_new_connection,
+   { "NewConnection", "hq", "", hfp_agent_new_connection,
G_DBUS_METHOD_FLAG_ASYNC },
{ "Release", "", "", hfp_agent_release },
{ NULL, NULL, NULL, NULL }
@@ -223,8 +226,6 @@ static int hfp_hf_probe(const char *device, const char 
*dev_addr,
if (data == NULL)
goto free;
 
-   hfp_slc_info_init(&data->info, HFP_VERSION_1_5);
-
data->handsfree_path = g_strdup(device);
if (data->handsfree_path == NULL)
goto free;
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH v3 1/2] hfpmodem: fix hf features

2011-08-08 Thread Frédéric Danis
check audio gateway version and only set right features
---
 drivers/hfpmodem/slc.c |7 ++-
 drivers/hfpmodem/slc.h |5 -
 plugins/hfp_hf.c   |2 +-
 plugins/phonesim.c |2 +-
 4 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/hfpmodem/slc.c b/drivers/hfpmodem/slc.c
index f9eca22..4028479 100644
--- a/drivers/hfpmodem/slc.c
+++ b/drivers/hfpmodem/slc.c
@@ -52,7 +52,7 @@ struct slc_establish_data {
gpointer userdata;
 };
 
-void hfp_slc_info_init(struct hfp_slc_info *info)
+void hfp_slc_info_init(struct hfp_slc_info *info, guint16 version)
 {
info->ag_features = 0;
info->ag_mpty_features = 0;
@@ -60,9 +60,14 @@ void hfp_slc_info_init(struct hfp_slc_info *info)
info->hf_features = HFP_HF_FEATURE_3WAY;
info->hf_features |= HFP_HF_FEATURE_CLIP;
info->hf_features |= HFP_HF_FEATURE_REMOTE_VOLUME_CONTROL;
+
+   if (version < HFP_VERSION_1_5)
+   goto done;
+
info->hf_features |= HFP_HF_FEATURE_ENHANCED_CALL_STATUS;
info->hf_features |= HFP_HF_FEATURE_ENHANCED_CALL_CONTROL;
 
+done:
memset(info->cind_val, 0, sizeof(info->cind_val));
memset(info->cind_pos, 0, sizeof(info->cind_pos));
 }
diff --git a/drivers/hfpmodem/slc.h b/drivers/hfpmodem/slc.h
index f37a59c..6c2302c 100644
--- a/drivers/hfpmodem/slc.h
+++ b/drivers/hfpmodem/slc.h
@@ -27,6 +27,9 @@
 #define AG_CHLD_3  0x20
 #define AG_CHLD_4  0x40
 
+#define HFP_VERSION_1_50x0105
+#define HFP_VERSION_LATEST 0x
+
 enum hfp_indicator {
HFP_INDICATOR_SERVICE = 0,
HFP_INDICATOR_CALL,
@@ -49,7 +52,7 @@ struct hfp_slc_info {
unsigned int cind_val[HFP_INDICATOR_LAST];
 };
 
-void hfp_slc_info_init(struct hfp_slc_info *info);
+void hfp_slc_info_init(struct hfp_slc_info *info, guint16 version);
 void hfp_slc_info_free(struct hfp_slc_info *info);
 
 void hfp_slc_establish(struct hfp_slc_info *info, hfp_slc_cb_t connect_cb,
diff --git a/plugins/hfp_hf.c b/plugins/hfp_hf.c
index 5625141..9fa420a 100644
--- a/plugins/hfp_hf.c
+++ b/plugins/hfp_hf.c
@@ -223,7 +223,7 @@ static int hfp_hf_probe(const char *device, const char 
*dev_addr,
if (data == NULL)
goto free;
 
-   hfp_slc_info_init(&data->info);
+   hfp_slc_info_init(&data->info, HFP_VERSION_1_5);
 
data->handsfree_path = g_strdup(device);
if (data->handsfree_path == NULL)
diff --git a/plugins/phonesim.c b/plugins/phonesim.c
index 2b3bcf2..e81a2b4 100644
--- a/plugins/phonesim.c
+++ b/plugins/phonesim.c
@@ -880,7 +880,7 @@ static int localhfp_enable(struct ofono_modem *modem)
 
g_at_chat_set_disconnect_function(chat, slc_failed, modem);
 
-   hfp_slc_info_init(info);
+   hfp_slc_info_init(info, HFP_VERSION_LATEST);
info->chat = chat;
hfp_slc_establish(info, slc_established, slc_failed, modem);
 
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH v3 0/2] add profile version to HandsfreeAgent

2011-08-08 Thread Frédéric Danis
Some phones with HFP Audio Gateway version previous to 1.5 (i.e.
Samsung SGH-D600 returning 0x0101 as profile version) do not accept
an AT+BRSF with latest features.
The Handsfree agent should adapt its AT+BRSF command depending on the
remote version, so add version information as parameter of
NewConnection method.
For localhfp modem, use the highest version possible (0x) so it
will always send all implemented features.

Frédéric Danis (2):
  hfpmodem: fix hf features
  hfp_hf: retrieve AG version

 drivers/hfpmodem/slc.c |7 ++-
 drivers/hfpmodem/slc.h |5 -
 plugins/hfp_hf.c   |9 +
 plugins/phonesim.c |2 +-
 4 files changed, 16 insertions(+), 7 deletions(-)

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH v2 1/2] hfpmodem: fix hf features

2011-08-08 Thread Frédéric Danis
check audio gateway version and only set right features
---
 drivers/hfpmodem/slc.c |7 ++-
 drivers/hfpmodem/slc.h |2 +-
 plugins/hfp_hf.c   |2 +-
 plugins/phonesim.c |2 +-
 4 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/hfpmodem/slc.c b/drivers/hfpmodem/slc.c
index f9eca22..79b4798 100644
--- a/drivers/hfpmodem/slc.c
+++ b/drivers/hfpmodem/slc.c
@@ -52,7 +52,7 @@ struct slc_establish_data {
gpointer userdata;
 };
 
-void hfp_slc_info_init(struct hfp_slc_info *info)
+void hfp_slc_info_init(struct hfp_slc_info *info, guint16 version)
 {
info->ag_features = 0;
info->ag_mpty_features = 0;
@@ -60,9 +60,14 @@ void hfp_slc_info_init(struct hfp_slc_info *info)
info->hf_features = HFP_HF_FEATURE_3WAY;
info->hf_features |= HFP_HF_FEATURE_CLIP;
info->hf_features |= HFP_HF_FEATURE_REMOTE_VOLUME_CONTROL;
+
+   if (version < 0x0105)
+   goto done;
+
info->hf_features |= HFP_HF_FEATURE_ENHANCED_CALL_STATUS;
info->hf_features |= HFP_HF_FEATURE_ENHANCED_CALL_CONTROL;
 
+done:
memset(info->cind_val, 0, sizeof(info->cind_val));
memset(info->cind_pos, 0, sizeof(info->cind_pos));
 }
diff --git a/drivers/hfpmodem/slc.h b/drivers/hfpmodem/slc.h
index f37a59c..dd6f926 100644
--- a/drivers/hfpmodem/slc.h
+++ b/drivers/hfpmodem/slc.h
@@ -49,7 +49,7 @@ struct hfp_slc_info {
unsigned int cind_val[HFP_INDICATOR_LAST];
 };
 
-void hfp_slc_info_init(struct hfp_slc_info *info);
+void hfp_slc_info_init(struct hfp_slc_info *info, guint16 version);
 void hfp_slc_info_free(struct hfp_slc_info *info);
 
 void hfp_slc_establish(struct hfp_slc_info *info, hfp_slc_cb_t connect_cb,
diff --git a/plugins/hfp_hf.c b/plugins/hfp_hf.c
index 5625141..52423bc 100644
--- a/plugins/hfp_hf.c
+++ b/plugins/hfp_hf.c
@@ -223,7 +223,7 @@ static int hfp_hf_probe(const char *device, const char 
*dev_addr,
if (data == NULL)
goto free;
 
-   hfp_slc_info_init(&data->info);
+   hfp_slc_info_init(&data->info, 0x0105);
 
data->handsfree_path = g_strdup(device);
if (data->handsfree_path == NULL)
diff --git a/plugins/phonesim.c b/plugins/phonesim.c
index 2b3bcf2..3c094d3 100644
--- a/plugins/phonesim.c
+++ b/plugins/phonesim.c
@@ -880,7 +880,7 @@ static int localhfp_enable(struct ofono_modem *modem)
 
g_at_chat_set_disconnect_function(chat, slc_failed, modem);
 
-   hfp_slc_info_init(info);
+   hfp_slc_info_init(info, G_MAXUINT16);
info->chat = chat;
hfp_slc_establish(info, slc_established, slc_failed, modem);
 
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH v2 2/2] hfp_hf: retrieve AG version

2011-08-08 Thread Frédéric Danis
---
 plugins/hfp_hf.c |9 +
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/plugins/hfp_hf.c b/plugins/hfp_hf.c
index 52423bc..6516e75 100644
--- a/plugins/hfp_hf.c
+++ b/plugins/hfp_hf.c
@@ -161,11 +161,14 @@ static DBusMessage 
*hfp_agent_new_connection(DBusConnection *conn,
int fd, err;
struct ofono_modem *modem = data;
struct hfp_data *hfp_data = ofono_modem_get_data(modem);
+   guint16 version;
 
if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UNIX_FD, &fd,
-   DBUS_TYPE_INVALID))
+   DBUS_TYPE_UINT16, &version, DBUS_TYPE_INVALID))
return __ofono_error_invalid_args(msg);
 
+   hfp_slc_info_init(&hfp_data->info, version);
+
err = service_level_connection(modem, fd);
if (err < 0 && err != -EINPROGRESS)
return __ofono_error_failed(msg);
@@ -192,7 +195,7 @@ static DBusMessage *hfp_agent_release(DBusConnection *conn,
 }
 
 static GDBusMethodTable agent_methods[] = {
-   { "NewConnection", "h", "", hfp_agent_new_connection,
+   { "NewConnection", "hq", "", hfp_agent_new_connection,
G_DBUS_METHOD_FLAG_ASYNC },
{ "Release", "", "", hfp_agent_release },
{ NULL, NULL, NULL, NULL }
@@ -223,8 +226,6 @@ static int hfp_hf_probe(const char *device, const char 
*dev_addr,
if (data == NULL)
goto free;
 
-   hfp_slc_info_init(&data->info, 0x0105);
-
data->handsfree_path = g_strdup(device);
if (data->handsfree_path == NULL)
goto free;
-- 
1.7.1

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


  1   2   3   >