* [PATCH v0 01/15] handsfree-audio: Add card driver
2013-03-12 12:41 ` [PATCH v0 00/15] Add handsfree audio card driver Claudio Takahasi
@ 2013-03-12 12:41 ` Claudio Takahasi
2013-03-13 16:53 ` Frederic Danis
2013-03-18 18:58 ` Denis Kenzior
2013-03-12 12:42 ` [PATCH v0 02/15] hfp_hf_bluez5: Register handsfree audio driver Claudio Takahasi
` (13 subsequent siblings)
14 siblings, 2 replies; 43+ messages in thread
From: Claudio Takahasi @ 2013-03-12 12:41 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 3119 bytes --]
This patch adds a new handsfree audio driver abstration to allow
implementing the connect callbacks and other potential functions
specific of each HFP profile version. This approach also avoids
including dependency of hfpmodem in handsfree-audio, keeping the service
level handling inside the hfp_hf_bluez5 only.
---
include/handsfree-audio.h | 11 +++++++++++
src/handsfree-audio.c | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 45 insertions(+)
diff --git a/include/handsfree-audio.h b/include/handsfree-audio.h
index c5403c7..69f5a8e 100644
--- a/include/handsfree-audio.h
+++ b/include/handsfree-audio.h
@@ -30,6 +30,17 @@ extern "C" {
struct ofono_handsfree_card;
+struct ofono_handsfree_card_driver {
+ int (*probe) (struct ofono_handsfree_card *card, void *data);
+ void (*remove) (struct ofono_handsfree_card *card);
+ int (*audio_connect) (const char *remote, const char *local);
+};
+
+int ofono_handsfree_card_driver_register(
+ const struct ofono_handsfree_card_driver *d);
+void ofono_handsfree_card_driver_unregister(
+ const struct ofono_handsfree_card_driver *d);
+
struct ofono_handsfree_card *ofono_handsfree_card_create(const char *remote,
const char *local);
int ofono_handsfree_card_register(struct ofono_handsfree_card *card);
diff --git a/src/handsfree-audio.c b/src/handsfree-audio.c
index 73c6183..ffae47b 100644
--- a/src/handsfree-audio.c
+++ b/src/handsfree-audio.c
@@ -52,6 +52,7 @@ struct ofono_handsfree_card {
char *remote;
char *local;
char *path;
+ const struct ofono_handsfree_card_driver *driver;
};
struct agent {
@@ -66,6 +67,7 @@ static struct agent *agent = NULL;
static int ref_count = 0;
static GSList *card_list = 0;
static guint sco_watch = 0;
+static GSList *g_drivers = NULL;
static void send_new_connection(const char *card, int fd)
{
@@ -255,6 +257,7 @@ struct ofono_handsfree_card *ofono_handsfree_card_create(const char *remote,
const char *local)
{
struct ofono_handsfree_card *card;
+ GSList *l;
card = g_new0(struct ofono_handsfree_card, 1);
@@ -263,6 +266,16 @@ struct ofono_handsfree_card *ofono_handsfree_card_create(const char *remote,
card_list = g_slist_prepend(card_list, card);
+ for (l = g_drivers; l; l = g_slist_next(l)) {
+ const struct ofono_handsfree_card_driver *drv = l->data;
+
+ if (drv->probe(card, NULL) < 0)
+ continue;
+
+ card->driver = drv;
+ break;
+ }
+
return card;
}
@@ -534,6 +547,27 @@ static const GDBusSignalTable am_signals[] = {
{ }
};
+int ofono_handsfree_card_driver_register(
+ const struct ofono_handsfree_card_driver *d)
+{
+ DBG("driver: %p", d);
+
+ if (d->probe == NULL)
+ return -EINVAL;
+
+ g_drivers = g_slist_prepend(g_drivers, (void *) d);
+
+ return 0;
+}
+
+void ofono_handsfree_card_driver_unregister(
+ const struct ofono_handsfree_card_driver *d)
+{
+ DBG("driver: %p", d);
+
+ g_drivers = g_slist_remove(g_drivers, (void *) d);
+}
+
void ofono_handsfree_audio_ref(void)
{
ref_count += 1;
--
1.7.11.7
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [PATCH v0 01/15] handsfree-audio: Add card driver
2013-03-12 12:41 ` [PATCH v0 01/15] handsfree-audio: Add " Claudio Takahasi
@ 2013-03-13 16:53 ` Frederic Danis
2013-03-13 17:46 ` Denis Kenzior
2013-03-18 18:58 ` Denis Kenzior
1 sibling, 1 reply; 43+ messages in thread
From: Frederic Danis @ 2013-03-13 16:53 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 1526 bytes --]
Hello Claudio,
On 12/03/2013 13:41, Claudio Takahasi wrote:
> This patch adds a new handsfree audio driver abstration to allow
> implementing the connect callbacks and other potential functions
> specific of each HFP profile version. This approach also avoids
> including dependency of hfpmodem in handsfree-audio, keeping the service
> level handling inside the hfp_hf_bluez5 only.
> ---
> include/handsfree-audio.h | 11 +++++++++++
> src/handsfree-audio.c | 34 ++++++++++++++++++++++++++++++++++
> 2 files changed, 45 insertions(+)
>
> diff --git a/include/handsfree-audio.h b/include/handsfree-audio.h
> index c5403c7..69f5a8e 100644
> --- a/include/handsfree-audio.h
> +++ b/include/handsfree-audio.h
> @@ -30,6 +30,17 @@ extern "C" {
>
> struct ofono_handsfree_card;
>
> +struct ofono_handsfree_card_driver {
> + int (*probe) (struct ofono_handsfree_card *card, void *data);
> + void (*remove) (struct ofono_handsfree_card *card);
> + int (*audio_connect) (const char *remote, const char *local);
> +};
If I understand correctly this will be used by both hfp_hf_bluez5 and
hfp_ag_bluez5.
As connection process are not the same for HF and AG roles in HFP 1.6
handsfree-audio will need a way to discriminate drivers related to each
of them.
You may add something like profile UUID to this struct.
Regards
Fred
--
Frederic Danis Open Source Technology Center
frederic.danis(a)intel.com Intel Corporation
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [PATCH v0 01/15] handsfree-audio: Add card driver
2013-03-13 16:53 ` Frederic Danis
@ 2013-03-13 17:46 ` Denis Kenzior
2013-03-14 9:59 ` Frederic Danis
0 siblings, 1 reply; 43+ messages in thread
From: Denis Kenzior @ 2013-03-13 17:46 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 647 bytes --]
Hi Fred,
>> +struct ofono_handsfree_card_driver {
>> + int (*probe) (struct ofono_handsfree_card *card, void *data);
>> + void (*remove) (struct ofono_handsfree_card *card);
>> + int (*audio_connect) (const char *remote, const char *local);
>> +};
>
> If I understand correctly this will be used by both hfp_hf_bluez5 and
> hfp_ag_bluez5.
> As connection process are not the same for HF and AG roles in HFP 1.6
> handsfree-audio will need a way to discriminate drivers related to each
> of them.
> You may add something like profile UUID to this struct.
>
Why do we need the UUID if we have a driver method?
Regards,
-Denis
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [PATCH v0 01/15] handsfree-audio: Add card driver
2013-03-13 17:46 ` Denis Kenzior
@ 2013-03-14 9:59 ` Frederic Danis
0 siblings, 0 replies; 43+ messages in thread
From: Frederic Danis @ 2013-03-14 9:59 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 1570 bytes --]
Hello Denis,
On 13/03/2013 18:46, Denis Kenzior wrote:
> Hi Fred,
>
>>> +struct ofono_handsfree_card_driver {
>>> + int (*probe) (struct ofono_handsfree_card *card, void *data);
>>> + void (*remove) (struct ofono_handsfree_card *card);
>>> + int (*audio_connect) (const char *remote, const char *local);
>>> +};
>>
>> If I understand correctly this will be used by both hfp_hf_bluez5 and
>> hfp_ag_bluez5.
>> As connection process are not the same for HF and AG roles in HFP 1.6
>> handsfree-audio will need a way to discriminate drivers related to each
>> of them.
>> You may add something like profile UUID to this struct.
>>
>
> Why do we need the UUID if we have a driver method?
AFAIU, both HFP plugins (hfp_hf_bluez5 and hfp_ag_bluez5) will register
a card driver.
With this patches, when ofono_handsfree_card_create() is called it links
the first registered driver to the ofono_handsfree_card. I.e., if HFP AG
card driver is registered before HFP HF one, it will use the driver
connection method of HFP HF.
Plus, as you know, audio connection in HFP 1.6 is not the same for HF
and AG roles.
This is why I think we need a way to distinguish card drivers of HFP HF
and HFP AG.
I think we can do this by adding UUID to ofono_handsfree_card_driver or
to probe function (so passing it to ofono_handsfree_card_create).
Did I miss something ?
Regards
Fred
--
Frederic Danis Open Source Technology Center
frederic.danis(a)intel.com Intel Corporation
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v0 01/15] handsfree-audio: Add card driver
2013-03-12 12:41 ` [PATCH v0 01/15] handsfree-audio: Add " Claudio Takahasi
2013-03-13 16:53 ` Frederic Danis
@ 2013-03-18 18:58 ` Denis Kenzior
1 sibling, 0 replies; 43+ messages in thread
From: Denis Kenzior @ 2013-03-18 18:58 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 622 bytes --]
Hi Claudio,
On 03/12/2013 07:41 AM, Claudio Takahasi wrote:
> This patch adds a new handsfree audio driver abstration to allow
> implementing the connect callbacks and other potential functions
> specific of each HFP profile version. This approach also avoids
> including dependency of hfpmodem in handsfree-audio, keeping the service
> level handling inside the hfp_hf_bluez5 only.
> ---
> include/handsfree-audio.h | 11 +++++++++++
> src/handsfree-audio.c | 34 ++++++++++++++++++++++++++++++++++
> 2 files changed, 45 insertions(+)
>
I pushed my own version of this patch.
Regards,
-Denis
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH v0 02/15] hfp_hf_bluez5: Register handsfree audio driver
2013-03-12 12:41 ` [PATCH v0 00/15] Add handsfree audio card driver Claudio Takahasi
2013-03-12 12:41 ` [PATCH v0 01/15] handsfree-audio: Add " Claudio Takahasi
@ 2013-03-12 12:42 ` Claudio Takahasi
2013-03-18 18:59 ` Denis Kenzior
2013-03-12 12:42 ` [PATCH v0 03/15] hfp_hf_bluez5: Add extracting version Claudio Takahasi
` (12 subsequent siblings)
14 siblings, 1 reply; 43+ messages in thread
From: Claudio Takahasi @ 2013-03-12 12:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 1825 bytes --]
This patch registers the Handsfree Audio Card driver for devices
compliant with HFP 1.5.
---
plugins/hfp_hf_bluez5.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/plugins/hfp_hf_bluez5.c b/plugins/hfp_hf_bluez5.c
index 381a541..2020e63 100644
--- a/plugins/hfp_hf_bluez5.c
+++ b/plugins/hfp_hf_bluez5.c
@@ -311,6 +311,26 @@ static struct ofono_modem_driver hfp_driver = {
.post_sim = hfp_post_sim,
};
+static int card_probe(struct ofono_handsfree_card *card, void *data)
+{
+ return 0;
+}
+
+static void card_remove(struct ofono_handsfree_card *card)
+{
+}
+
+static int card_audio_connect15(const char *remote, const char *local)
+{
+ return 0;
+}
+
+static struct ofono_handsfree_card_driver card_driver15 = {
+ .probe = card_probe,
+ .remove = card_remove,
+ .audio_connect = card_audio_connect15,
+};
+
static ofono_bool_t device_path_compare(struct ofono_modem *modem,
void *userdata)
{
@@ -615,8 +635,16 @@ static int hfp_init(void)
return -EIO;
}
+ err = ofono_handsfree_card_driver_register(&card_driver15);
+ if (err < 0) {
+ g_dbus_unregister_interface(conn, HFP_EXT_PROFILE_PATH,
+ BLUEZ_PROFILE_INTERFACE);
+ return err;
+ }
+
err = ofono_modem_driver_register(&hfp_driver);
if (err < 0) {
+ ofono_handsfree_card_driver_unregister(&card_driver15);
g_dbus_unregister_interface(conn, HFP_EXT_PROFILE_PATH,
BLUEZ_PROFILE_INTERFACE);
return err;
@@ -647,6 +675,7 @@ static void hfp_exit(void)
g_dbus_unregister_interface(conn, HFP_EXT_PROFILE_PATH,
BLUEZ_PROFILE_INTERFACE);
ofono_modem_driver_unregister(&hfp_driver);
+ ofono_handsfree_card_driver_unregister(&card_driver15);
g_dbus_client_unref(bluez);
ofono_handsfree_audio_unref();
--
1.7.11.7
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH v0 03/15] hfp_hf_bluez5: Add extracting version
2013-03-12 12:41 ` [PATCH v0 00/15] Add handsfree audio card driver Claudio Takahasi
2013-03-12 12:41 ` [PATCH v0 01/15] handsfree-audio: Add " Claudio Takahasi
2013-03-12 12:42 ` [PATCH v0 02/15] hfp_hf_bluez5: Register handsfree audio driver Claudio Takahasi
@ 2013-03-12 12:42 ` Claudio Takahasi
2013-03-18 18:55 ` Denis Kenzior
2013-03-12 12:42 ` [PATCH v0 04/15] handsfree-audio: Add version to card driver Claudio Takahasi
` (11 subsequent siblings)
14 siblings, 1 reply; 43+ messages in thread
From: Claudio Takahasi @ 2013-03-12 12:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 2056 bytes --]
This patch parses and reads the profile "Version" that comes in the fd
dictionary of the NewConnection method. "Version" is input for Audio Card
registration.
---
plugins/hfp_hf_bluez5.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/plugins/hfp_hf_bluez5.c b/plugins/hfp_hf_bluez5.c
index 2020e63..a8d8277 100644
--- a/plugins/hfp_hf_bluez5.c
+++ b/plugins/hfp_hf_bluez5.c
@@ -343,6 +343,37 @@ static ofono_bool_t device_path_compare(struct ofono_modem *modem,
return g_str_equal(path, value);
}
+static int get_version(DBusMessageIter *iter, uint16_t *version)
+{
+ DBusMessageIter dict, entry, valiter;
+ const char *key;
+ uint16_t value;
+
+ dbus_message_iter_recurse(iter, &dict);
+
+ /* Dict entry key */
+ dbus_message_iter_recurse(&dict, &entry);
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&entry, &key);
+ if (g_str_equal("Version", key) == FALSE)
+ return -EINVAL;
+
+ /* Dict entry value */
+ dbus_message_iter_next(&entry);
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
+ return -EINVAL;
+
+ dbus_message_iter_recurse(&entry, &valiter);
+ dbus_message_iter_get_basic(&valiter, &value);
+
+ if (version)
+ *version = value;
+
+ return 0;
+}
+
static DBusMessage *profile_new_connection(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
@@ -353,6 +384,7 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
DBusMessageIter entry;
const char *device;
char local[18], remote[18];
+ uint16_t version;
int fd, err;
DBG("Profile handler NewConnection");
@@ -373,6 +405,11 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
if (fd < 0)
goto invalid;
+ dbus_message_iter_next(&entry);
+
+ if (get_version(&entry, &version) < 0)
+ goto invalid;
+
modem = ofono_modem_find(device_path_compare, (void *) device);
if (modem == NULL) {
close(fd);
--
1.7.11.7
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [PATCH v0 03/15] hfp_hf_bluez5: Add extracting version
2013-03-12 12:42 ` [PATCH v0 03/15] hfp_hf_bluez5: Add extracting version Claudio Takahasi
@ 2013-03-18 18:55 ` Denis Kenzior
0 siblings, 0 replies; 43+ messages in thread
From: Denis Kenzior @ 2013-03-18 18:55 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 2466 bytes --]
Hi Claudio,
On 03/12/2013 07:42 AM, Claudio Takahasi wrote:
> This patch parses and reads the profile "Version" that comes in the fd
> dictionary of the NewConnection method. "Version" is input for Audio Card
> registration.
> ---
> plugins/hfp_hf_bluez5.c | 37 +++++++++++++++++++++++++++++++++++++
> 1 file changed, 37 insertions(+)
>
> diff --git a/plugins/hfp_hf_bluez5.c b/plugins/hfp_hf_bluez5.c
> index 2020e63..a8d8277 100644
> --- a/plugins/hfp_hf_bluez5.c
> +++ b/plugins/hfp_hf_bluez5.c
> @@ -343,6 +343,37 @@ static ofono_bool_t device_path_compare(struct ofono_modem *modem,
> return g_str_equal(path, value);
> }
>
> +static int get_version(DBusMessageIter *iter, uint16_t *version)
> +{
> + DBusMessageIter dict, entry, valiter;
> + const char *key;
> + uint16_t value;
> +
> + dbus_message_iter_recurse(iter,&dict);
> +
> + /* Dict entry key */
> + dbus_message_iter_recurse(&dict,&entry);
> + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
> + return -EINVAL;
> +
> + dbus_message_iter_get_basic(&entry,&key);
> + if (g_str_equal("Version", key) == FALSE)
> + return -EINVAL;
> +
> + /* Dict entry value */
> + dbus_message_iter_next(&entry);
> + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
> + return -EINVAL;
> +
> + dbus_message_iter_recurse(&entry,&valiter);
> + dbus_message_iter_get_basic(&valiter,&value);
> +
> + if (version)
> + *version = value;
> +
> + return 0;
> +}
> +
> static DBusMessage *profile_new_connection(DBusConnection *conn,
> DBusMessage *msg, void *user_data)
> {
> @@ -353,6 +384,7 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
> DBusMessageIter entry;
> const char *device;
> char local[18], remote[18];
> + uint16_t version;
> int fd, err;
>
> DBG("Profile handler NewConnection");
> @@ -373,6 +405,11 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
> if (fd< 0)
> goto invalid;
>
> + dbus_message_iter_next(&entry);
> +
I would not mind extra sanity checking here, e.g. argument type checking
> + if (get_version(&entry,&version)< 0)
> + goto invalid;
> +
I don't like this. The fd_properties is a dictionary, you cannot assume
that Version will be always the first one.
> modem = ofono_modem_find(device_path_compare, (void *) device);
> if (modem == NULL) {
> close(fd);
Regards,
-Denis
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH v0 04/15] handsfree-audio: Add version to card driver
2013-03-12 12:41 ` [PATCH v0 00/15] Add handsfree audio card driver Claudio Takahasi
` (2 preceding siblings ...)
2013-03-12 12:42 ` [PATCH v0 03/15] hfp_hf_bluez5: Add extracting version Claudio Takahasi
@ 2013-03-12 12:42 ` Claudio Takahasi
2013-03-18 18:59 ` Denis Kenzior
2013-03-12 12:42 ` [PATCH v0 05/15] hfp_hf_bluez5: Pass version to card registration Claudio Takahasi
` (10 subsequent siblings)
14 siblings, 1 reply; 43+ messages in thread
From: Claudio Takahasi @ 2013-03-12 12:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 2081 bytes --]
This patch extends the Handsfree Audio Card driver adding the Handsfree
Profile version to allow switching different drivers to manage SCO
connections or any other specific action related to a given profile
version.
---
include/handsfree-audio.h | 4 +++-
src/handsfree-audio.c | 5 ++++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/include/handsfree-audio.h b/include/handsfree-audio.h
index 69f5a8e..e99a2dd 100644
--- a/include/handsfree-audio.h
+++ b/include/handsfree-audio.h
@@ -26,11 +26,13 @@
extern "C" {
#endif
+#include <stdint.h>
#include <ofono/types.h>
struct ofono_handsfree_card;
struct ofono_handsfree_card_driver {
+ uint16_t version;
int (*probe) (struct ofono_handsfree_card *card, void *data);
void (*remove) (struct ofono_handsfree_card *card);
int (*audio_connect) (const char *remote, const char *local);
@@ -42,7 +44,7 @@ void ofono_handsfree_card_driver_unregister(
const struct ofono_handsfree_card_driver *d);
struct ofono_handsfree_card *ofono_handsfree_card_create(const char *remote,
- const char *local);
+ const char *local, uint16_t version);
int ofono_handsfree_card_register(struct ofono_handsfree_card *card);
void ofono_handsfree_card_remove(struct ofono_handsfree_card *card);
diff --git a/src/handsfree-audio.c b/src/handsfree-audio.c
index ffae47b..1e636cc 100644
--- a/src/handsfree-audio.c
+++ b/src/handsfree-audio.c
@@ -254,7 +254,7 @@ static const GDBusSignalTable card_signals[] = {
};
struct ofono_handsfree_card *ofono_handsfree_card_create(const char *remote,
- const char *local)
+ const char *local, uint16_t version)
{
struct ofono_handsfree_card *card;
GSList *l;
@@ -269,6 +269,9 @@ struct ofono_handsfree_card *ofono_handsfree_card_create(const char *remote,
for (l = g_drivers; l; l = g_slist_next(l)) {
const struct ofono_handsfree_card_driver *drv = l->data;
+ if (drv->version != version)
+ continue;
+
if (drv->probe(card, NULL) < 0)
continue;
--
1.7.11.7
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH v0 05/15] hfp_hf_bluez5: Pass version to card registration
2013-03-12 12:41 ` [PATCH v0 00/15] Add handsfree audio card driver Claudio Takahasi
` (3 preceding siblings ...)
2013-03-12 12:42 ` [PATCH v0 04/15] handsfree-audio: Add version to card driver Claudio Takahasi
@ 2013-03-12 12:42 ` Claudio Takahasi
2013-03-12 12:42 ` [PATCH v0 06/15] hfp_hf_bluez5: Add version to HFP 1.5 card driver Claudio Takahasi
` (9 subsequent siblings)
14 siblings, 0 replies; 43+ messages in thread
From: Claudio Takahasi @ 2013-03-12 12:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 654 bytes --]
Informs the HFP version of the remote device when the Audio Card is
created.
---
plugins/hfp_hf_bluez5.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/hfp_hf_bluez5.c b/plugins/hfp_hf_bluez5.c
index a8d8277..f201b05 100644
--- a/plugins/hfp_hf_bluez5.c
+++ b/plugins/hfp_hf_bluez5.c
@@ -454,7 +454,7 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
hfp = ofono_modem_get_data(modem);
hfp->msg = dbus_message_ref(msg);
- hfp->card = ofono_handsfree_card_create(remote, local);
+ hfp->card = ofono_handsfree_card_create(remote, local, version);
return NULL;
--
1.7.11.7
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH v0 06/15] hfp_hf_bluez5: Add version to HFP 1.5 card driver
2013-03-12 12:41 ` [PATCH v0 00/15] Add handsfree audio card driver Claudio Takahasi
` (4 preceding siblings ...)
2013-03-12 12:42 ` [PATCH v0 05/15] hfp_hf_bluez5: Pass version to card registration Claudio Takahasi
@ 2013-03-12 12:42 ` Claudio Takahasi
2013-03-12 12:42 ` [PATCH v0 07/15] core: Add bt_str2ba() to bluetooth.h Claudio Takahasi
` (8 subsequent siblings)
14 siblings, 0 replies; 43+ messages in thread
From: Claudio Takahasi @ 2013-03-12 12:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 532 bytes --]
---
plugins/hfp_hf_bluez5.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/plugins/hfp_hf_bluez5.c b/plugins/hfp_hf_bluez5.c
index f201b05..1b3b7bc 100644
--- a/plugins/hfp_hf_bluez5.c
+++ b/plugins/hfp_hf_bluez5.c
@@ -326,6 +326,7 @@ static int card_audio_connect15(const char *remote, const char *local)
}
static struct ofono_handsfree_card_driver card_driver15 = {
+ .version = HFP_VERSION_1_5,
.probe = card_probe,
.remove = card_remove,
.audio_connect = card_audio_connect15,
--
1.7.11.7
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH v0 07/15] core: Add bt_str2ba() to bluetooth.h
2013-03-12 12:41 ` [PATCH v0 00/15] Add handsfree audio card driver Claudio Takahasi
` (5 preceding siblings ...)
2013-03-12 12:42 ` [PATCH v0 06/15] hfp_hf_bluez5: Add version to HFP 1.5 card driver Claudio Takahasi
@ 2013-03-12 12:42 ` Claudio Takahasi
2013-03-18 19:00 ` Denis Kenzior
2013-03-12 12:42 ` [PATCH v0 08/15] hfp_hf_bluez5: Add HFP 1.5 connect implementation Claudio Takahasi
` (7 subsequent siblings)
14 siblings, 1 reply; 43+ messages in thread
From: Claudio Takahasi @ 2013-03-12 12:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 976 bytes --]
This patch adds a utility Bluetooth function to convert Bluetooth
address from string to bdaddr_t.
---
src/bluetooth.h | 8 ++++++++
src/handsfree-audio.c | 1 +
2 files changed, 9 insertions(+)
diff --git a/src/bluetooth.h b/src/bluetooth.h
index 1584109..af6f02c 100644
--- a/src/bluetooth.h
+++ b/src/bluetooth.h
@@ -69,3 +69,11 @@ static inline int bt_bacmp(const bdaddr_t *ba1, const bdaddr_t *ba2)
{
return memcmp(ba1, ba2, sizeof(bdaddr_t));
}
+
+static inline void bt_str2ba(const char *str, bdaddr_t *ba)
+{
+ int i;
+
+ for (i = 5; i >= 0; i--, str += 3)
+ ba->b[i] = strtol(str, NULL, 16);
+}
diff --git a/src/handsfree-audio.c b/src/handsfree-audio.c
index 1e636cc..c11c325 100644
--- a/src/handsfree-audio.c
+++ b/src/handsfree-audio.c
@@ -26,6 +26,7 @@
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
+#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
--
1.7.11.7
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH v0 08/15] hfp_hf_bluez5: Add HFP 1.5 connect implementation
2013-03-12 12:41 ` [PATCH v0 00/15] Add handsfree audio card driver Claudio Takahasi
` (6 preceding siblings ...)
2013-03-12 12:42 ` [PATCH v0 07/15] core: Add bt_str2ba() to bluetooth.h Claudio Takahasi
@ 2013-03-12 12:42 ` Claudio Takahasi
2013-03-12 12:42 ` [PATCH v0 09/15] handsfree-audio: Add calling connect callback Claudio Takahasi
` (6 subsequent siblings)
14 siblings, 0 replies; 43+ messages in thread
From: Claudio Takahasi @ 2013-03-12 12:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 1464 bytes --]
This patch adds the Audio Card driver connect callback implementation
to handle SCO connection requested by the driver. This approach
addresses devices compliant with HFP 1.5
---
plugins/hfp_hf_bluez5.c | 31 ++++++++++++++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/plugins/hfp_hf_bluez5.c b/plugins/hfp_hf_bluez5.c
index 1b3b7bc..f1c3027 100644
--- a/plugins/hfp_hf_bluez5.c
+++ b/plugins/hfp_hf_bluez5.c
@@ -322,7 +322,36 @@ static void card_remove(struct ofono_handsfree_card *card)
static int card_audio_connect15(const char *remote, const char *local)
{
- return 0;
+ struct sockaddr_sco addr;
+ int sk, ret;
+
+ sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET | O_NONBLOCK | SOCK_CLOEXEC,
+ BTPROTO_SCO);
+ if (sk < 0)
+ return -1;
+
+ /* Bind to local address */
+ memset(&addr, 0, sizeof(addr));
+ addr.sco_family = AF_BLUETOOTH;
+ bt_str2ba(local, &addr.sco_bdaddr);
+
+ if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ close(sk);
+ return -1;
+ }
+
+ /* Connect to remote device */
+ memset(&addr, 0, sizeof(addr));
+ addr.sco_family = AF_BLUETOOTH;
+ bt_str2ba(remote, &addr.sco_bdaddr);
+
+ ret = connect(sk, (struct sockaddr *) &addr, sizeof(addr));
+ if (ret < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) {
+ close(sk);
+ return -1;
+ }
+
+ return sk;
}
static struct ofono_handsfree_card_driver card_driver15 = {
--
1.7.11.7
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH v0 09/15] handsfree-audio: Add calling connect callback
2013-03-12 12:41 ` [PATCH v0 00/15] Add handsfree audio card driver Claudio Takahasi
` (7 preceding siblings ...)
2013-03-12 12:42 ` [PATCH v0 08/15] hfp_hf_bluez5: Add HFP 1.5 connect implementation Claudio Takahasi
@ 2013-03-12 12:42 ` Claudio Takahasi
2013-03-12 12:42 ` [PATCH v0 10/15] handsfree-audio: Add connect GIOChannel watch Claudio Takahasi
` (5 subsequent siblings)
14 siblings, 0 replies; 43+ messages in thread
From: Claudio Takahasi @ 2013-03-12 12:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 1013 bytes --]
This patch adds the call of the connect callback implemented in the
driver when "Connect" method of the Audio Card gets called.
---
src/handsfree-audio.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/src/handsfree-audio.c b/src/handsfree-audio.c
index c11c325..8a0d97d 100644
--- a/src/handsfree-audio.c
+++ b/src/handsfree-audio.c
@@ -237,7 +237,18 @@ static DBusMessage *card_get_properties(DBusConnection *conn,
static DBusMessage *card_connect(DBusConnection *conn,
DBusMessage *msg, void *data)
{
- return __ofono_error_not_implemented(msg);
+ struct ofono_handsfree_card *card = data;
+ const struct ofono_handsfree_card_driver *driver = card->driver;
+ int sk;
+
+ if (driver == NULL)
+ return __ofono_error_not_implemented(msg);
+
+ sk = driver->audio_connect(card->remote, card->local);
+ if (sk < 0)
+ return __ofono_error_failed(msg);
+
+ return NULL;
}
static const GDBusMethodTable card_methods[] = {
--
1.7.11.7
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH v0 10/15] handsfree-audio: Add connect GIOChannel watch
2013-03-12 12:41 ` [PATCH v0 00/15] Add handsfree audio card driver Claudio Takahasi
` (8 preceding siblings ...)
2013-03-12 12:42 ` [PATCH v0 09/15] handsfree-audio: Add calling connect callback Claudio Takahasi
@ 2013-03-12 12:42 ` Claudio Takahasi
2013-03-12 12:42 ` [PATCH v0 11/15] handsfree-audio: Add sending SCO fd Claudio Takahasi
` (4 subsequent siblings)
14 siblings, 0 replies; 43+ messages in thread
From: Claudio Takahasi @ 2013-03-12 12:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 2330 bytes --]
This patch adds the GIOChannel watch of the SCO socket. For HF initiated
connections, when the audio connection is established the reply for the
Card "Connect" method should be sent.
---
src/handsfree-audio.c | 43 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/src/handsfree-audio.c b/src/handsfree-audio.c
index 8a0d97d..f5d0a7b 100644
--- a/src/handsfree-audio.c
+++ b/src/handsfree-audio.c
@@ -54,6 +54,8 @@ struct ofono_handsfree_card {
char *local;
char *path;
const struct ofono_handsfree_card_driver *driver;
+ DBusMessage *msg;
+ guint sco_watch;
};
struct agent {
@@ -234,11 +236,40 @@ static DBusMessage *card_get_properties(DBusConnection *conn,
return reply;
}
+static gboolean sco_connect_cb(GIOChannel *io, GIOCondition cond,
+ gpointer user_data)
+
+{
+ struct ofono_handsfree_card *card = user_data;
+ DBusMessage *reply;
+
+ if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
+ reply = __ofono_error_failed(card->msg);
+ goto done;
+ }
+
+ reply = dbus_message_new_method_return(card->msg);
+
+done:
+ g_dbus_send_message(ofono_dbus_get_connection(), reply);
+
+ return FALSE;
+}
+
+static void sco_watch_destroy(gpointer user_data)
+{
+ struct ofono_handsfree_card *card = user_data;
+
+ card->sco_watch = 0;
+ dbus_message_unref(card->msg);
+}
+
static DBusMessage *card_connect(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct ofono_handsfree_card *card = data;
const struct ofono_handsfree_card_driver *driver = card->driver;
+ GIOChannel *io;
int sk;
if (driver == NULL)
@@ -248,6 +279,15 @@ static DBusMessage *card_connect(DBusConnection *conn,
if (sk < 0)
return __ofono_error_failed(msg);
+ io = g_io_channel_unix_new(sk);
+ card->sco_watch = g_io_add_watch_full(io, G_PRIORITY_DEFAULT,
+ G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ sco_connect_cb, card, sco_watch_destroy);
+
+ g_io_channel_unref(io);
+
+ card->msg = dbus_message_ref(msg);
+
return NULL;
}
@@ -383,6 +423,9 @@ void ofono_handsfree_card_remove(struct ofono_handsfree_card *card)
g_free(card->remote);
g_free(card->local);
+ if (card->sco_watch > 0)
+ g_source_remove(card->sco_watch);
+
g_free(card);
}
--
1.7.11.7
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH v0 11/15] handsfree-audio: Add sending SCO fd
2013-03-12 12:41 ` [PATCH v0 00/15] Add handsfree audio card driver Claudio Takahasi
` (9 preceding siblings ...)
2013-03-12 12:42 ` [PATCH v0 10/15] handsfree-audio: Add connect GIOChannel watch Claudio Takahasi
@ 2013-03-12 12:42 ` Claudio Takahasi
2013-03-12 12:42 ` [PATCH v0 12/15] handsfree-audio: Return NotAvailable on "Connect" Claudio Takahasi
` (3 subsequent siblings)
14 siblings, 0 replies; 43+ messages in thread
From: Claudio Takahasi @ 2013-03-12 12:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 826 bytes --]
This patch adds the call of NewConnection method when the SCO connection
is established for HF initiated scenarios.
---
src/handsfree-audio.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/handsfree-audio.c b/src/handsfree-audio.c
index f5d0a7b..6fa8b67 100644
--- a/src/handsfree-audio.c
+++ b/src/handsfree-audio.c
@@ -242,12 +242,19 @@ static gboolean sco_connect_cb(GIOChannel *io, GIOCondition cond,
{
struct ofono_handsfree_card *card = user_data;
DBusMessage *reply;
+ int sk;
if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
reply = __ofono_error_failed(card->msg);
goto done;
}
+ sk = g_io_channel_unix_get_fd(io);
+
+ send_new_connection(card->path, sk);
+
+ close(sk);
+
reply = dbus_message_new_method_return(card->msg);
done:
--
1.7.11.7
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH v0 12/15] handsfree-audio: Return NotAvailable on "Connect"
2013-03-12 12:41 ` [PATCH v0 00/15] Add handsfree audio card driver Claudio Takahasi
` (10 preceding siblings ...)
2013-03-12 12:42 ` [PATCH v0 11/15] handsfree-audio: Add sending SCO fd Claudio Takahasi
@ 2013-03-12 12:42 ` Claudio Takahasi
2013-03-12 12:42 ` [PATCH v0 13/15] handsfree-audio: Return InProgress on Connect Claudio Takahasi
` (2 subsequent siblings)
14 siblings, 0 replies; 43+ messages in thread
From: Claudio Takahasi @ 2013-03-12 12:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 712 bytes --]
Returns "Operation currently not available" if "Connect" method of the
Handsfree Audio Card gets called and there isn't an agent registered.
---
src/handsfree-audio.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/handsfree-audio.c b/src/handsfree-audio.c
index 6fa8b67..8950347 100644
--- a/src/handsfree-audio.c
+++ b/src/handsfree-audio.c
@@ -282,6 +282,9 @@ static DBusMessage *card_connect(DBusConnection *conn,
if (driver == NULL)
return __ofono_error_not_implemented(msg);
+ if (agent == NULL)
+ return __ofono_error_not_available(msg);
+
sk = driver->audio_connect(card->remote, card->local);
if (sk < 0)
return __ofono_error_failed(msg);
--
1.7.11.7
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH v0 13/15] handsfree-audio: Return InProgress on Connect
2013-03-12 12:41 ` [PATCH v0 00/15] Add handsfree audio card driver Claudio Takahasi
` (11 preceding siblings ...)
2013-03-12 12:42 ` [PATCH v0 12/15] handsfree-audio: Return NotAvailable on "Connect" Claudio Takahasi
@ 2013-03-12 12:42 ` Claudio Takahasi
2013-03-12 15:26 ` Frederic Danis
2013-03-12 12:42 ` [PATCH v0 14/15] handsfree-audio: Check agent before sending fd Claudio Takahasi
2013-03-12 12:42 ` [PATCH v0 15/15] doc: Add Handsfree Audio Card "Connect" errors Claudio Takahasi
14 siblings, 1 reply; 43+ messages in thread
From: Claudio Takahasi @ 2013-03-12 12:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 680 bytes --]
This patch returns "Operation already in progress" if there is a
pending Handsfree Audio Card "Connect" method call pending.
---
src/handsfree-audio.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/handsfree-audio.c b/src/handsfree-audio.c
index 8950347..805f3b6 100644
--- a/src/handsfree-audio.c
+++ b/src/handsfree-audio.c
@@ -285,6 +285,9 @@ static DBusMessage *card_connect(DBusConnection *conn,
if (agent == NULL)
return __ofono_error_not_available(msg);
+ if (card->msg)
+ return __ofono_error_busy(msg);
+
sk = driver->audio_connect(card->remote, card->local);
if (sk < 0)
return __ofono_error_failed(msg);
--
1.7.11.7
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [PATCH v0 13/15] handsfree-audio: Return InProgress on Connect
2013-03-12 12:42 ` [PATCH v0 13/15] handsfree-audio: Return InProgress on Connect Claudio Takahasi
@ 2013-03-12 15:26 ` Frederic Danis
2013-03-12 17:26 ` Claudio Takahasi
0 siblings, 1 reply; 43+ messages in thread
From: Frederic Danis @ 2013-03-12 15:26 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 1117 bytes --]
Hello Claudio,
On 12/03/2013 13:42, Claudio Takahasi wrote:
> This patch returns "Operation already in progress" if there is a
> pending Handsfree Audio Card "Connect" method call pending.
> ---
> src/handsfree-audio.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/src/handsfree-audio.c b/src/handsfree-audio.c
> index 8950347..805f3b6 100644
> --- a/src/handsfree-audio.c
> +++ b/src/handsfree-audio.c
> @@ -285,6 +285,9 @@ static DBusMessage *card_connect(DBusConnection *conn,
> if (agent == NULL)
> return __ofono_error_not_available(msg);
>
> + if (card->msg)
> + return __ofono_error_busy(msg);
> +
> sk = driver->audio_connect(card->remote, card->local);
> if (sk < 0)
> return __ofono_error_failed(msg);
>
Shouldn't you also test if there is already a SCO connection (sco_watch) ?
I think that only one SCO link can be connected at a time for a
Handsfree Audio Card.
Regards
Fred
--
Frederic Danis Open Source Technology Center
frederic.danis(a)intel.com Intel Corporation
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v0 13/15] handsfree-audio: Return InProgress on Connect
2013-03-12 15:26 ` Frederic Danis
@ 2013-03-12 17:26 ` Claudio Takahasi
0 siblings, 0 replies; 43+ messages in thread
From: Claudio Takahasi @ 2013-03-12 17:26 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 1416 bytes --]
Hi Frederic:
On Tue, Mar 12, 2013 at 12:26 PM, Frederic Danis
<frederic.danis@linux.intel.com> wrote:
> Hello Claudio,
>
>
> On 12/03/2013 13:42, Claudio Takahasi wrote:
>>
>> This patch returns "Operation already in progress" if there is a
>> pending Handsfree Audio Card "Connect" method call pending.
>> ---
>> src/handsfree-audio.c | 3 +++
>> 1 file changed, 3 insertions(+)
>>
>> diff --git a/src/handsfree-audio.c b/src/handsfree-audio.c
>> index 8950347..805f3b6 100644
>> --- a/src/handsfree-audio.c
>> +++ b/src/handsfree-audio.c
>> @@ -285,6 +285,9 @@ static DBusMessage *card_connect(DBusConnection *conn,
>> if (agent == NULL)
>> return __ofono_error_not_available(msg);
>>
>> + if (card->msg)
>> + return __ofono_error_busy(msg);
>> +
>> sk = driver->audio_connect(card->remote, card->local);
>> if (sk < 0)
>> return __ofono_error_failed(msg);
>>
>
> Shouldn't you also test if there is already a SCO connection (sco_watch) ?
> I think that only one SCO link can be connected at a time for a Handsfree
> Audio Card.
>
> Regards
>
> Fred
It is equivalent to check for card->sco_watch or card->msg.
card->sco_watch monitors the SCO connection attempt only.
At the moment, oFono is not keeping the SCO socket reference after
passing it to the Agent(P.A.).
Regards,
Claudio
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH v0 14/15] handsfree-audio: Check agent before sending fd
2013-03-12 12:41 ` [PATCH v0 00/15] Add handsfree audio card driver Claudio Takahasi
` (12 preceding siblings ...)
2013-03-12 12:42 ` [PATCH v0 13/15] handsfree-audio: Return InProgress on Connect Claudio Takahasi
@ 2013-03-12 12:42 ` Claudio Takahasi
2013-03-12 12:42 ` [PATCH v0 15/15] doc: Add Handsfree Audio Card "Connect" errors Claudio Takahasi
14 siblings, 0 replies; 43+ messages in thread
From: Claudio Takahasi @ 2013-03-12 12:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 739 bytes --]
This patch avoids sending the SCO fd when the connection is established
and the agent left the bus. This check covers the scenario when the
agent leaves the bus between "Connect" method call until the SCO
GIOChannel watch gets called.
---
src/handsfree-audio.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/handsfree-audio.c b/src/handsfree-audio.c
index 805f3b6..62d316f 100644
--- a/src/handsfree-audio.c
+++ b/src/handsfree-audio.c
@@ -251,7 +251,8 @@ static gboolean sco_connect_cb(GIOChannel *io, GIOCondition cond,
sk = g_io_channel_unix_get_fd(io);
- send_new_connection(card->path, sk);
+ if (agent)
+ send_new_connection(card->path, sk);
close(sk);
--
1.7.11.7
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH v0 15/15] doc: Add Handsfree Audio Card "Connect" errors
2013-03-12 12:41 ` [PATCH v0 00/15] Add handsfree audio card driver Claudio Takahasi
` (13 preceding siblings ...)
2013-03-12 12:42 ` [PATCH v0 14/15] handsfree-audio: Check agent before sending fd Claudio Takahasi
@ 2013-03-12 12:42 ` Claudio Takahasi
14 siblings, 0 replies; 43+ messages in thread
From: Claudio Takahasi @ 2013-03-12 12:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 688 bytes --]
---
doc/handsfree-audio-api.txt | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/doc/handsfree-audio-api.txt b/doc/handsfree-audio-api.txt
index 6c3c8b5..7d20925 100644
--- a/doc/handsfree-audio-api.txt
+++ b/doc/handsfree-audio-api.txt
@@ -70,6 +70,11 @@ Methods dict GetProperties()
the audio connection could not be established, this
method will return an error.
+ Possible Errors: [service].Error.InProgress
+ [service].Error.Failed
+ [service].Error.NotAvailable
+ [service].Error.NotImplemented
+
Signals PropertyChanged(string name, variant value)
This signal indicates a changed value of the given
--
1.7.11.7
^ permalink raw reply related [flat|nested] 43+ messages in thread