* [RFC v6 01/12] bluetooth: Add org.bluez.Telephony helpers
2012-08-01 10:09 [RFC v6 00/12] Add org.bluez.Telephony interface =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
@ 2012-08-01 10:09 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
2012-08-01 10:09 ` [RFC v6 02/12] hfp_hf: Update to org.bluez.Telephony interface =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
` (10 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis @ 2012-08-01 10:09 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 8052 bytes --]
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 != DBUS_TYPE_OBJECT_PATH)
+ return -EINVAL;
+ dbus_message_iter_get_basic(&value, device);
+ has_device = TRUE;
+ } else if (strcasecmp(key, "Version") == 0) {
+ if (var != DBUS_TYPE_UINT16)
+ return -EINVAL;
+ dbus_message_iter_get_basic(&value, version);
+ } else if (strcasecmp(key, "Features") == 0) {
+ if (var != DBUS_TYPE_UINT16)
+ return -EINVAL;
+ dbus_message_iter_get_basic(&value, features);
+ } else if (strcasecmp(key, "Transport") == 0) {
+ if (var != DBUS_TYPE_OBJECT_PATH)
+ return -EINVAL;
+ dbus_message_iter_get_basic(&value, transport_path);
+ }
+
+ dbus_message_iter_next(&props);
+ }
+
+ return has_device ? fd : -EINVAL;
+}
+
+void bluetooth_register_telephony_agent(const char *path, const char *uuid,
+ guint16 version, guint16 features,
+ const GDBusMethodTable *methods,
+ void *user_data,
+ GDBusDestroyFunction destroy)
+{
+ GSList *l;
+ struct agent *agent;
+
+ for (l = telephony_list; l; l = l->next) {
+ agent = l->data;
+
+ if (g_strcmp0(path, agent->path) == 0) {
+ ofono_error("Telephony agent path \"%s\" already " \
+ "registered", path);
+ return;
+ }
+ }
+
+ agent = g_try_new0(struct agent, 1);
+ if (!agent)
+ return;
+
+ agent->path = g_strdup(path);
+ agent->uuid = g_strdup(uuid);
+ agent->version = version;
+ agent->features = features;
+
+ bluetooth_ref();
+
+ g_dbus_register_interface(connection, path,
+ BLUEZ_TELEPHONY_AGENT_INTERFACE, methods, NULL,
+ NULL, user_data, destroy);
+
+ telephony_list = g_slist_prepend(telephony_list, agent);
+
+ g_hash_table_foreach(adapter_address_hash,
+ (GHFunc) register_telephony_agent, agent);
+}
+
+void bluetooth_unregister_telephony_agent(const char *path)
+{
+ GSList *l;
+ struct agent *agent;
+
+ for (l = telephony_list; l; l = l->next) {
+ agent = l->data;
+
+ if (g_strcmp0(path, agent->path) == 0)
+ break;
+ }
+
+ if (l == NULL)
+ return;
+
+ g_hash_table_foreach(adapter_address_hash,
+ (GHFunc) unregister_telephony_agent, agent);
+
+ telephony_list = g_slist_remove(telephony_list, agent);
+ g_free(agent->path);
+ g_free(agent->uuid);
+ g_free(agent);
+
+ g_dbus_unregister_interface(connection, path,
+ BLUEZ_TELEPHONY_AGENT_INTERFACE);
+
+ bluetooth_unref();
+}
+
OFONO_PLUGIN_DEFINE(bluetooth, "Bluetooth Utils Plugins", VERSION,
OFONO_PLUGIN_PRIORITY_DEFAULT, NULL, NULL)
diff --git a/plugins/bluetooth.h b/plugins/bluetooth.h
index 4fc16ad..6a2fbf0 100644
--- a/plugins/bluetooth.h
+++ b/plugins/bluetooth.h
@@ -21,6 +21,7 @@
#include <ofono/modem.h>
#include <ofono/dbus.h>
+#include <gdbus.h>
#define BLUEZ_SERVICE "org.bluez"
#define BLUEZ_MANAGER_INTERFACE BLUEZ_SERVICE ".Manager"
@@ -28,6 +29,8 @@
#define BLUEZ_DEVICE_INTERFACE BLUEZ_SERVICE ".Device"
#define BLUEZ_SERVICE_INTERFACE BLUEZ_SERVICE ".Service"
#define BLUEZ_SERIAL_INTERFACE BLUEZ_SERVICE ".Serial"
+#define BLUEZ_TELEPHONY_INTERFACE BLUEZ_SERVICE ".Telephony"
+#define BLUEZ_TELEPHONY_AGENT_INTERFACE BLUEZ_SERVICE ".TelephonyAgent"
#define DBUS_TIMEOUT 15
@@ -82,3 +85,13 @@ void bluetooth_parse_properties(DBusMessage *reply, const char *property, ...);
int bluetooth_sap_client_register(struct bluetooth_sap_driver *sap,
struct ofono_modem *modem);
void bluetooth_sap_client_unregister(struct ofono_modem *modem);
+
+int bluetooth_parse_newconnection_message(DBusMessage *msg, const char **device,
+ guint16 *version, guint16 *features,
+ const char **transport_path);
+void bluetooth_register_telephony_agent(const char *path, const char *uuid,
+ guint16 version, guint16 features,
+ const GDBusMethodTable *methods,
+ void *user_data,
+ GDBusDestroyFunction destroy);
+void bluetooth_unregister_telephony_agent(const char *path);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 13+ messages in thread* [RFC v6 02/12] hfp_hf: Update to org.bluez.Telephony interface
2012-08-01 10:09 [RFC v6 00/12] Add org.bluez.Telephony interface =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
2012-08-01 10:09 ` [RFC v6 01/12] bluetooth: Add org.bluez.Telephony helpers =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
@ 2012-08-01 10:09 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
2012-08-01 10:09 ` [RFC v6 03/12] hfp_ag: " =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
` (9 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis @ 2012-08-01 10:09 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 7644 bytes --]
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 @@
#define BLUEZ_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 hfp_data *data = ofono_modem_get_data(modem);
- const char *obj_path = ofono_modem_get_path(modem);
if (data->call != NULL)
dbus_pending_call_cancel(data->call);
- if (g_dbus_unregister_interface(connection, obj_path,
- HFP_AGENT_INTERFACE))
- hfp_unregister_ofono_handsfree(modem);
+ g_hash_table_remove(modem_hash, data->handsfree_path);
g_free(data->handsfree_address);
g_free(data->handsfree_path);
@@ -465,7 +364,7 @@ static int hfp_disable(struct ofono_modem *modem)
g_at_chat_unref(data->info.chat);
data->info.chat = NULL;
- if (data->agent_registered) {
+ if (ofono_modem_get_powered(modem)) {
status = bluetooth_send_with_reply(data->handsfree_path,
BLUEZ_GATEWAY_INTERFACE, "Disconnect",
&data->call, hfp_power_down,
@@ -497,6 +396,61 @@ static void hfp_post_sim(struct ofono_modem *modem)
DBG("%p", modem);
}
+static DBusMessage *hfp_agent_new_connection(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ int fd, err;
+ struct ofono_modem *modem;
+ struct hfp_data *hfp_data;
+ const char *device;
+ const char *path = NULL;
+ guint16 features = 0;
+ guint16 version = 0;
+
+ fd = bluetooth_parse_newconnection_message(msg, &device, &version,
+ &features, &path);
+ if (fd < 0)
+ return __ofono_error_invalid_args(msg);
+
+ DBG("New connection for %s (version 0x%04X, features 0x%02X, " \
+ "media transport path: %s)",
+ device, version, features, path);
+
+ modem = g_hash_table_lookup(modem_hash, device);
+ if (modem == NULL)
+ return __ofono_error_invalid_args(msg);
+
+ hfp_data = ofono_modem_get_data(modem);
+
+ 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)
+{
+ 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_agent_new_connection) },
+ { GDBUS_METHOD("Release", NULL, NULL, hfp_agent_release) },
+ { }
+};
+
static struct ofono_modem_driver hfp_driver = {
.name = "hfp",
.modem_type = OFONO_MODEM_TYPE_HFP,
@@ -517,6 +471,8 @@ static struct bluetooth_profile hfp_hf = {
static int hfp_init(void)
{
+ dbus_uint16_t features = HFP_HF_FEATURE_3WAY | HFP_HF_FEATURE_CLIP |
+ HFP_HF_FEATURE_REMOTE_VOLUME_CONTROL;
int err;
if (DBUS_TYPE_UNIX_FD < 0)
@@ -537,11 +493,16 @@ static int hfp_init(void)
modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, NULL);
+ bluetooth_register_telephony_agent(HFP_AGENT_PATH, HFP_HS_UUID,
+ HFP_VERSION_1_5, features,
+ agent_methods, NULL, NULL);
+
return 0;
}
static void hfp_exit(void)
{
+ bluetooth_unregister_telephony_agent(HFP_AGENT_PATH);
bluetooth_unregister_uuid(HFP_AG_UUID);
ofono_modem_driver_unregister(&hfp_driver);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 13+ messages in thread* [RFC v6 03/12] hfp_ag: Update to org.bluez.Telephony interface
2012-08-01 10:09 [RFC v6 00/12] Add org.bluez.Telephony interface =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
2012-08-01 10:09 ` [RFC v6 01/12] bluetooth: Add org.bluez.Telephony helpers =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
2012-08-01 10:09 ` [RFC v6 02/12] hfp_hf: Update to org.bluez.Telephony interface =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
@ 2012-08-01 10:09 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
2012-08-01 10:09 ` [RFC v6 04/12] bluetooth: Add define for MediaTransport interface =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
` (8 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis @ 2012-08-01 10:09 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 5601 bytes --]
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 =
-"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
-"<record>\n"
-" <attribute id=\"0x0001\">\n"
-" <sequence>\n"
-" <uuid value=\"0x111F\"/>\n"
-" <uuid value=\"0x1203\"/>\n"
-" </sequence>\n"
-" </attribute>\n"
-"\n"
-" <attribute id=\"0x0004\">\n"
-" <sequence>\n"
-" <sequence>\n"
-" <uuid value=\"0x0100\"/>\n"
-" </sequence>\n"
-" <sequence>\n"
-" <uuid value=\"0x0003\"/>\n"
-" <uint8 value=\"13\" name=\"channel\"/>\n"
-" </sequence>\n"
-" </sequence>\n"
-" </attribute>\n"
-"\n"
-" <attribute id=\"0x0009\">\n"
-" <sequence>\n"
-" <sequence>\n"
-" <uuid value=\"0x111E\"/>\n"
-" <uint16 value=\"0x0105\" name=\"version\"/>\n"
-" </sequence>\n"
-" </sequence>\n"
-" </attribute>\n"
-"\n"
-" <attribute id=\"0x0100\">\n"
-" <text value=\"Hands-Free Audio Gateway\" name=\"name\"/>\n"
-" </attribute>\n"
-"\n"
-" <attribute id=\"0x0301\">\n"
-" <uint8 value=\"0x01\" />\n"
-" </attribute>\n"
-"\n"
-" <attribute id=\"0x0311\">\n"
-" <uint16 value=\"0x0001\" />\n"
-" </attribute>\n"
-"</record>\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)
static int hfp_ag_init(void)
{
+ if (DBUS_TYPE_UNIX_FD < 0)
+ return -EBADF;
+
sim_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
modemwatch_id = __ofono_modemwatch_add(modem_watch, NULL, NULL);
@@ -203,14 +195,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);
-
- if (server) {
- bluetooth_unregister_server(server);
- server = NULL;
- }
}
OFONO_PLUGIN_DEFINE(hfp_ag, "Hands-Free Audio Gateway Profile Plugins", VERSION,
--
1.7.9.5
^ permalink raw reply related [flat|nested] 13+ messages in thread* [RFC v6 04/12] bluetooth: Add define for MediaTransport interface
2012-08-01 10:09 [RFC v6 00/12] Add org.bluez.Telephony interface =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
` (2 preceding siblings ...)
2012-08-01 10:09 ` [RFC v6 03/12] hfp_ag: " =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
@ 2012-08-01 10:09 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
2012-08-01 10:09 ` [RFC v6 05/12] include: Add set/get data APIs to emulator =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
` (7 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis @ 2012-08-01 10:09 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 542 bytes --]
---
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"
#define BLUEZ_TELEPHONY_INTERFACE BLUEZ_SERVICE ".Telephony"
#define BLUEZ_TELEPHONY_AGENT_INTERFACE BLUEZ_SERVICE ".TelephonyAgent"
+#define BLUEZ_TRANSPORT_INTERFACE BLUEZ_SERVICE ".MediaTransport"
#define DBUS_TIMEOUT 15
--
1.7.9.5
^ permalink raw reply related [flat|nested] 13+ messages in thread* [RFC v6 05/12] include: Add set/get data APIs to emulator
2012-08-01 10:09 [RFC v6 00/12] Add org.bluez.Telephony interface =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
` (3 preceding siblings ...)
2012-08-01 10:09 ` [RFC v6 04/12] bluetooth: Add define for MediaTransport interface =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
@ 2012-08-01 10:09 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
2012-08-01 10:09 ` [RFC v6 06/12] emulator: Add set/get data APIs =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
` (6 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis @ 2012-08-01 10:09 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 715 bytes --]
---
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
^ permalink raw reply related [flat|nested] 13+ messages in thread* [RFC v6 06/12] emulator: Add set/get data APIs
2012-08-01 10:09 [RFC v6 00/12] Add org.bluez.Telephony interface =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
` (4 preceding siblings ...)
2012-08-01 10:09 ` [RFC v6 05/12] include: Add set/get data APIs to emulator =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
@ 2012-08-01 10:09 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
2012-08-01 10:09 ` [RFC v6 07/12] hfp_ag: Add AT+NREC support =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
` (5 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis @ 2012-08-01 10:09 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 1039 bytes --]
---
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
^ permalink raw reply related [flat|nested] 13+ messages in thread* [RFC v6 07/12] hfp_ag: Add AT+NREC support
2012-08-01 10:09 [RFC v6 00/12] Add org.bluez.Telephony interface =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
` (5 preceding siblings ...)
2012-08-01 10:09 ` [RFC v6 06/12] emulator: Add set/get data APIs =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
@ 2012-08-01 10:09 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
2012-08-01 10:09 ` [RFC v6 08/12] hfp_ag: Add +BSIR support =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
` (4 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis @ 2012-08-01 10:09 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 5074 bytes --]
---
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 == NULL)
+ return;
+
+ if (audio->call)
+ dbus_pending_call_cancel(audio->call);
+
+ g_free(audio->path);
+ g_free(audio);
+}
+
static DBusMessage *hfp_ag_agent_new_connection(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -60,6 +201,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, &version,
&features, &path);
@@ -83,6 +225,15 @@ static DBusMessage *hfp_ag_agent_new_connection(DBusConnection *conn,
ofono_emulator_register(em, fd);
+ audio = g_new0(struct bt_audio, 1);
+ audio->em = em;
+ audio->path = g_strdup(path);
+ audio->r_features = features;
+ ofono_emulator_set_data(em, audio,
+ (ofono_destroy_func)free_audio_management);
+
+ ofono_emulator_add_handler(em, "+NREC", emulator_nrec_cb, audio, NULL);
+
return dbus_message_new_method_return(msg);
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 13+ messages in thread* [RFC v6 08/12] hfp_ag: Add +BSIR support
2012-08-01 10:09 [RFC v6 00/12] Add org.bluez.Telephony interface =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
` (6 preceding siblings ...)
2012-08-01 10:09 ` [RFC v6 07/12] hfp_ag: Add AT+NREC support =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
@ 2012-08-01 10:09 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
2012-08-01 10:09 ` [RFC v6 09/12] hfp_ag: Add AT+VGM support =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
` (3 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis @ 2012-08-01 10:09 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 2593 bytes --]
---
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
^ permalink raw reply related [flat|nested] 13+ messages in thread* [RFC v6 09/12] hfp_ag: Add AT+VGM support
2012-08-01 10:09 [RFC v6 00/12] Add org.bluez.Telephony interface =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
` (7 preceding siblings ...)
2012-08-01 10:09 ` [RFC v6 08/12] hfp_ag: Add +BSIR support =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
@ 2012-08-01 10:09 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
2012-08-01 10:09 ` [RFC v6 10/12] hfp_ag: Add AT+VGS support =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
` (2 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis @ 2012-08-01 10:09 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 3412 bytes --]
---
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
^ permalink raw reply related [flat|nested] 13+ messages in thread* [RFC v6 10/12] hfp_ag: Add AT+VGS support
2012-08-01 10:09 [RFC v6 00/12] Add org.bluez.Telephony interface =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
` (8 preceding siblings ...)
2012-08-01 10:09 ` [RFC v6 09/12] hfp_ag: Add AT+VGM support =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
@ 2012-08-01 10:09 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
2012-08-01 10:09 ` [RFC v6 11/12] emulator: Update supported features =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
2012-08-01 10:09 ` [RFC v6 12/12] dun_gw: Update to org.bluez.Telephony interface =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
11 siblings, 0 replies; 13+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis @ 2012-08-01 10:09 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 3485 bytes --]
---
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
^ permalink raw reply related [flat|nested] 13+ messages in thread* [RFC v6 11/12] emulator: Update supported features
2012-08-01 10:09 [RFC v6 00/12] Add org.bluez.Telephony interface =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
` (9 preceding siblings ...)
2012-08-01 10:09 ` [RFC v6 10/12] hfp_ag: Add AT+VGS support =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
@ 2012-08-01 10:09 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
2012-08-01 10:09 ` [RFC v6 12/12] dun_gw: Update to org.bluez.Telephony interface =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
11 siblings, 0 replies; 13+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis @ 2012-08-01 10:09 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 741 bytes --]
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
^ permalink raw reply related [flat|nested] 13+ messages in thread* [RFC v6 12/12] dun_gw: Update to org.bluez.Telephony interface
2012-08-01 10:09 [RFC v6 00/12] Add org.bluez.Telephony interface =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
` (10 preceding siblings ...)
2012-08-01 10:09 ` [RFC v6 11/12] emulator: Update supported features =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
@ 2012-08-01 10:09 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis
11 siblings, 0 replies; 13+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Danis @ 2012-08-01 10:09 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 4832 bytes --]
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_0 0x0100
+
+#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 =
-"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
-"<record>\n"
-" <attribute id=\"0x0001\">\n"
-" <sequence>\n"
-" <uuid value=\"0x1103\"/>\n"
-" </sequence>\n"
-" </attribute>\n"
-"\n"
-" <attribute id=\"0x0004\">\n"
-" <sequence>\n"
-" <sequence>\n"
-" <uuid value=\"0x0100\"/>\n"
-" </sequence>\n"
-" <sequence>\n"
-" <uuid value=\"0x0003\"/>\n"
-" <uint8 value=\"1\" name=\"channel\"/>\n"
-" </sequence>\n"
-" </sequence>\n"
-" </attribute>\n"
-"\n"
-" <attribute id=\"0x0009\">\n"
-" <sequence>\n"
-" <sequence>\n"
-" <uuid value=\"0x1103\"/>\n"
-" <uint16 value=\"0x0100\" name=\"version\"/>\n"
-" </sequence>\n"
-" </sequence>\n"
-" </attribute>\n"
-"\n"
-" <attribute id=\"0x0100\">\n"
-" <text value=\"Dial-up Networking\" name=\"name\"/>\n"
-" </attribute>\n"
-"</record>\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_server(server);
- server = NULL;
- }
}
OFONO_PLUGIN_DEFINE(dun_gw, "Dial-up Networking Profile Plugins", VERSION,
--
1.7.9.5
^ permalink raw reply related [flat|nested] 13+ messages in thread