2009-04-08 08:46:55

by Zhao Forrest

[permalink] [raw]
Subject: [PATCH 4/4] IPC integration part for HFP Audio gateway -- take5

From: Forrest Zhao <[email protected]>

---
audio/gateway.c | 77 +++++++++++++++++++++++++++++++++++++
audio/gateway.h | 7 +++
audio/unix.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 192 insertions(+), 7 deletions(-)

diff --git a/audio/gateway.c b/audio/gateway.c
index 272927b..62359eb 100644
--- a/audio/gateway.c
+++ b/audio/gateway.c
@@ -1126,3 +1126,80 @@ int gateway_close(struct audio_device *device)
"Connected", DBUS_TYPE_BOOLEAN, &value);
return 0;
}
+
+/* These are functions to be called from unix.c for audio system
+ * ifaces (alsa, gstreamer, etc.) */
+gboolean gateway_request_stream(struct audio_device *dev,
+ gateway_stream_cb_t cb, void *user_data)
+{
+ struct gateway *gw = dev->gateway;
+ GError *err = NULL;
+ GIOChannel *io;
+
+ if (!gw->sco) {
+ if (!gw->rfcomm)
+ return FALSE;
+ gw->sco_start_cb = cb;
+ gw->sco_start_cb_data = user_data;
+ io = bt_io_connect(BT_IO_SCO, sco_connect_cb, dev, NULL, &err,
+ BT_IO_OPT_SOURCE_BDADDR, &dev->src,
+ BT_IO_OPT_DEST_BDADDR, &dev->dst,
+ BT_IO_OPT_INVALID);
+ if (!io) {
+ error("%s", err->message);
+ g_error_free(err);
+ return FALSE;
+ }
+ } else {
+ if (cb)
+ cb(dev, user_data);
+ }
+ return TRUE;
+}
+
+int gateway_config_stream(struct audio_device *dev, gateway_stream_cb_t sco_cb,
+ void *user_data)
+{
+ struct gateway *gw = dev->gateway;
+
+ if (!gw->rfcomm) {
+ gw->sco_start_cb = sco_cb;
+ gw->sco_start_cb_data = user_data;
+ return get_records(dev);
+ }
+
+ if (sco_cb)
+ sco_cb(dev, user_data);
+
+ return 0;
+}
+
+gboolean gateway_cancel_stream(struct audio_device *dev, unsigned int id)
+{
+ gateway_close(dev);
+ return TRUE;
+}
+
+int gateway_get_sco_fd(struct audio_device *dev)
+{
+ GIOChannel *sco_chan = dev->gateway->sco;
+
+ if (!sco_chan)
+ return -1;
+
+ return g_io_channel_unix_get_fd(sco_chan);
+}
+
+void gateway_suspend_stream(struct audio_device *dev)
+{
+ struct gateway *gw = dev->gateway;
+
+ if (gw->sco) {
+ g_io_channel_close(gw->sco);
+ g_io_channel_unref(gw->sco);
+ gw->sco = NULL;
+ gw->sco_start_cb = NULL;
+ gw->sco_start_cb_data = NULL;
+ }
+}
+
diff --git a/audio/gateway.h b/audio/gateway.h
index 78eef87..7acad46 100644
--- a/audio/gateway.h
+++ b/audio/gateway.h
@@ -32,3 +32,10 @@ struct gateway *gateway_init(struct audio_device *device);
gboolean gateway_is_connected(struct audio_device *dev);
int gateway_connect_rfcomm(struct audio_device *dev, GIOChannel *chan);
void gateway_start_service(struct audio_device *device);
+gboolean gateway_request_stream(struct audio_device *dev,
+ gateway_stream_cb_t cb, void *user_data);
+int gateway_config_stream(struct audio_device *dev, gateway_stream_cb_t cb,
+ void *user_data);
+gboolean gateway_cancel_stream(struct audio_device *dev, unsigned int id);
+int gateway_get_sco_fd(struct audio_device *dev);
+void gateway_suspend_stream(struct audio_device *dev);
diff --git a/audio/unix.c b/audio/unix.c
index 1234f45..ea40cd8 100644
--- a/audio/unix.c
+++ b/audio/unix.c
@@ -47,6 +47,7 @@
#include "a2dp.h"
#include "headset.h"
#include "sink.h"
+#include "gateway.h"
#include "unix.h"
#include "glib-helper.h"

@@ -55,6 +56,7 @@
typedef enum {
TYPE_NONE,
TYPE_HEADSET,
+ TYPE_GATEWAY,
TYPE_SINK,
TYPE_SOURCE
} service_type_t;
@@ -182,6 +184,8 @@ static service_type_t select_service(struct audio_device *dev, const char *inter
return TYPE_SINK;
else if (!strcmp(interface, AUDIO_HEADSET_INTERFACE) && dev->headset)
return TYPE_HEADSET;
+ else if (!strcmp(interface, AUDIO_GATEWAY_INTERFACE) && dev->gateway)
+ return TYPE_GATEWAY;

return TYPE_NONE;
}
@@ -226,7 +230,7 @@ static uint8_t headset_generate_capability(struct audio_device *dev,

pcm = (void *) codec;
pcm->sampling_rate = 8000;
- if (headset_get_nrec(dev))
+ if (dev->headset && headset_get_nrec(dev))
pcm->flags |= BT_PCM_FLAG_NREC;
if (!headset_get_sco_hci(dev))
pcm->flags |= BT_PCM_FLAG_PCM_ROUTING;
@@ -299,6 +303,32 @@ failed:
unix_ipc_error(client, BT_SET_CONFIGURATION, EIO);
}

+static void gateway_setup_complete(struct audio_device *dev, void *user_data)
+{
+ struct unix_client *client = user_data;
+ char buf[BT_SUGGESTED_BUFFER_SIZE];
+ struct bt_set_configuration_rsp *rsp = (void *) buf;
+
+ if (!dev) {
+ unix_ipc_error(client, BT_SET_CONFIGURATION, EIO);
+ return;
+ }
+
+ client->req_id = 0;
+
+ memset(buf, 0, sizeof(buf));
+
+ rsp->h.type = BT_RESPONSE;
+ rsp->h.name = BT_SET_CONFIGURATION;
+ rsp->h.length = sizeof(*rsp);
+
+ rsp->link_mtu = 48;
+
+ client->data_fd = gateway_get_sco_fd(dev);
+
+ unix_ipc_sendmsg(client, &rsp->h);
+}
+
static void headset_resume_complete(struct audio_device *dev, void *user_data)
{
struct unix_client *client = user_data;
@@ -343,6 +373,35 @@ failed:
unix_ipc_error(client, BT_START_STREAM, EIO);
}

+static void gateway_resume_complete(struct audio_device *dev, void *user_data)
+{
+ struct unix_client *client = user_data;
+ char buf[BT_SUGGESTED_BUFFER_SIZE];
+ struct bt_start_stream_rsp *rsp = (void *) buf;
+ struct bt_new_stream_ind *ind = (void *) buf;
+
+ memset(buf, 0, sizeof(buf));
+ rsp->h.type = BT_RESPONSE;
+ rsp->h.name = BT_START_STREAM;
+ rsp->h.length = sizeof(*rsp);
+
+ unix_ipc_sendmsg(client, &rsp->h);
+
+ memset(buf, 0, sizeof(buf));
+ ind->h.type = BT_INDICATION;
+ ind->h.name = BT_NEW_STREAM;
+ ind->h.length = sizeof(*ind);
+
+ unix_ipc_sendmsg(client, &ind->h);
+
+ client->data_fd = gateway_get_sco_fd(dev);
+ if (unix_sendmsg_fd(client->sock, client->data_fd) < 0) {
+ error("unix_sendmsg_fd: %s(%d)", strerror(errno), errno);
+ unix_ipc_error(client, BT_START_STREAM, EIO);
+ }
+ client->req_id = 0;
+}
+
static void headset_suspend_complete(struct audio_device *dev, void *user_data)
{
struct unix_client *client = user_data;
@@ -757,6 +816,7 @@ static void start_discovery(struct audio_device *dev, struct unix_client *client
break;

case TYPE_HEADSET:
+ case TYPE_GATEWAY:
headset_discovery_complete(dev, client);
break;

@@ -908,6 +968,13 @@ static void start_config(struct audio_device *dev, struct unix_client *client)
client);
client->cancel = headset_cancel_stream;
break;
+ case TYPE_GATEWAY:
+ if (gateway_config_stream(dev, gateway_setup_complete, client) >= 0) {
+ client->cancel = gateway_cancel_stream;
+ id = 1;
+ } else
+ id = 0;
+ break;

default:
error("No known services for device");
@@ -970,6 +1037,14 @@ static void start_resume(struct audio_device *dev, struct unix_client *client)
client->cancel = headset_cancel_stream;
break;

+ case TYPE_GATEWAY:
+ if (gateway_request_stream(dev, gateway_resume_complete, client))
+ id = 1;
+ else
+ id = 0;
+ client->cancel = gateway_cancel_stream;
+ break;
+
default:
error("No known services for device");
goto failed;
@@ -1030,6 +1105,13 @@ static void start_suspend(struct audio_device *dev, struct unix_client *client)
client->cancel = headset_cancel_stream;
break;

+ case TYPE_GATEWAY:
+ gateway_suspend_stream(dev);
+ client->cancel = gateway_cancel_stream;
+ headset_suspend_complete(dev, client);
+ id = 1;
+ break;
+
default:
error("No known services for device");
goto failed;
@@ -1142,6 +1224,17 @@ static void handle_getcapabilities_req(struct unix_client *client,
dev = manager_find_device(req->object, &src, &dst,
client->interface, FALSE);

+ if (!dev && req->transport == BT_CAPABILITIES_TRANSPORT_SCO) {
+ g_free(client->interface);
+ client->interface = g_strdup(AUDIO_GATEWAY_INTERFACE);
+
+ dev = manager_find_device(req->object, &src, &dst,
+ client->interface, TRUE);
+ if (!dev && (req->flags & BT_FLAG_AUTOCONNECT))
+ dev = manager_find_device(req->object, &src, &dst,
+ client->interface, FALSE);
+ }
+
if (!dev) {
error("Unable to find a matching device");
goto failed;
@@ -1252,9 +1345,17 @@ failed:
static int handle_sco_transport(struct unix_client *client,
struct bt_set_configuration_req *req)
{
- if (!client->interface)
- client->interface = g_strdup(AUDIO_HEADSET_INTERFACE);
- else if (!g_str_equal(client->interface, AUDIO_HEADSET_INTERFACE))
+ struct audio_device *dev = client->dev;
+
+ if (!client->interface) {
+ if (dev->headset)
+ client->interface = g_strdup(AUDIO_HEADSET_INTERFACE);
+ else if (dev->gateway)
+ client->interface = g_strdup(AUDIO_GATEWAY_INTERFACE);
+ else
+ return -EIO;
+ } else if (!g_str_equal(client->interface, AUDIO_HEADSET_INTERFACE) &&
+ !g_str_equal(client->interface, AUDIO_GATEWAY_INTERFACE))
return -EIO;

return 0;
@@ -1339,6 +1440,9 @@ static void handle_setconfiguration_req(struct unix_client *client,
goto failed;
}

+ if (!client->dev)
+ goto failed;
+
if (req->codec.transport == BT_CAPABILITIES_TRANSPORT_SCO) {
err = handle_sco_transport(client, req);
if (err < 0) {
@@ -1353,9 +1457,6 @@ static void handle_setconfiguration_req(struct unix_client *client,
}
}

- if (!client->dev)
- goto failed;
-
start_config(client->dev, client);

return;
--
1.5.4.5



2009-04-10 06:00:14

by Rajan Batra

[permalink] [raw]
Subject: Re: [PATCH 4/4] IPC integration part for HFP Audio gateway -- take5

> Did you use the latest version of PA?
when i restart my machine. pulseaudio daemon is by default
running. i havent done any setting to use PA for bluez nor loaded any
bluetooth modules in PA.

so this means i am not using PA for bluez rite ? so i guess all
should go to ALSA

thanks.
-rajan



On Fri, Apr 10, 2009 at 8:07 AM, Zhao Forrest <[email protected]> wrote:
> On Fri, Apr 10, 2009 at 1:14 AM, Rajan Batra <[email protected]> wrote:
>> Hello,
>>   i used today's git bluez head code for headset gateway. i am able
>> to dial the number. receive the call.
>> but the voice stream is not starting. i have connected headphone to my
>> bluez linux host.
>> i am not able to hear or pass my voice to  other side.
>>
>> do i have to do some setting in PA ?.  or any extra settings.
> Did you use the latest version of PA?
>
>>
>> i do following steps :
>>
>> 1)   dbus-send --system --type=method_call --print-reply
>> --dest=org.bluez /org/bluez/32112/hci0/dev_00_24_04_46_4E_FA
>> org.bluez.HeadsetGateway.Connect
>>
>>
>> 2)  dbus-send --system --type=method_call --print-reply
>> --dest=org.bluez /org/bluez/32112/hci0/dev_00_24_04_46_4E_FA
>> org.bluez.HeadsetGateway.Call string:<number>
>>
>> i changed macro in gateway.c
>>     #define AG_PLACE_CALL "ATD%s\r"
>> to
>>     #define AG_PLACE_CALL "ATD%s;\r"
>>
>>  without semicolon, phone wasnt dialing the number.
>>
> According to HFP spec there should not be semicolon, this might be an
> interoperability issue.
>
> Thanks,
> Forrest
>

2009-04-10 05:56:28

by Rajan Batra

[permalink] [raw]
Subject: Re: [PATCH 4/4] IPC integration part for HFP Audio gateway -- take5

Please find bluetooth -d -n log attached.
I called a number, number answered the call. but i didnt hear any
voice and also
couldnt send my voice to other side.

Is there anything appears obvious from log ? (about what i am missing)

thanks.
-Rajan Batra


On Fri, Apr 10, 2009 at 11:14 AM, Rajan Batra <[email protected]> wrote:
> Hello,
>
>     what am i missing to establish voice connection ?
> why ALSA is not able to stream voice from Phone to my bluez headphone ?
> is there some settings ?
>
> thanks.
> Rajan
>
>
> On Fri, Apr 10, 2009 at 8:07 AM, Zhao Forrest <[email protected]> wrote:
>> On Fri, Apr 10, 2009 at 1:14 AM, Rajan Batra <[email protected]> wrote:
>>> Hello,
>>>   i used today's git bluez head code for headset gateway. i am able
>>> to dial the number. receive the call.
>>> but the voice stream is not starting. i have connected headphone to my
>>> bluez linux host.
>>> i am not able to hear or pass my voice to  other side.
>>>
>>> do i have to do some setting in PA ?.  or any extra settings.
>> Did you use the latest version of PA?
>>
>>>
>>> i do following steps :
>>>
>>> 1)   dbus-send --system --type=method_call --print-reply
>>> --dest=org.bluez /org/bluez/32112/hci0/dev_00_24_04_46_4E_FA
>>> org.bluez.HeadsetGateway.Connect
>>>
>>>
>>> 2)  dbus-send --system --type=method_call --print-reply
>>> --dest=org.bluez /org/bluez/32112/hci0/dev_00_24_04_46_4E_FA
>>> org.bluez.HeadsetGateway.Call string:<number>
>>>
>>> i changed macro in gateway.c
>>>     #define AG_PLACE_CALL "ATD%s\r"
>>> to
>>>     #define AG_PLACE_CALL "ATD%s;\r"
>>>
>>>  without semicolon, phone wasnt dialing the number.
>>>
>> According to HFP spec there should not be semicolon, this might be an
>> interoperability issue.
>>
>> Thanks,
>> Forrest
>>
>


Attachments:
bluez-GatewayLog.txt (13.88 kB)

2009-04-10 05:44:32

by Rajan Batra

[permalink] [raw]
Subject: Re: [PATCH 4/4] IPC integration part for HFP Audio gateway -- take5

Hello,

what am i missing to establish voice connection ?
why ALSA is not able to stream voice from Phone to my bluez headphone ?
is there some settings ?

thanks.
Rajan


On Fri, Apr 10, 2009 at 8:07 AM, Zhao Forrest <[email protected]> wrote:
> On Fri, Apr 10, 2009 at 1:14 AM, Rajan Batra <[email protected]> wrote:
>> Hello,
>>   i used today's git bluez head code for headset gateway. i am able
>> to dial the number. receive the call.
>> but the voice stream is not starting. i have connected headphone to my
>> bluez linux host.
>> i am not able to hear or pass my voice to  other side.
>>
>> do i have to do some setting in PA ?.  or any extra settings.
> Did you use the latest version of PA?
>
>>
>> i do following steps :
>>
>> 1)   dbus-send --system --type=method_call --print-reply
>> --dest=org.bluez /org/bluez/32112/hci0/dev_00_24_04_46_4E_FA
>> org.bluez.HeadsetGateway.Connect
>>
>>
>> 2)  dbus-send --system --type=method_call --print-reply
>> --dest=org.bluez /org/bluez/32112/hci0/dev_00_24_04_46_4E_FA
>> org.bluez.HeadsetGateway.Call string:<number>
>>
>> i changed macro in gateway.c
>>     #define AG_PLACE_CALL "ATD%s\r"
>> to
>>     #define AG_PLACE_CALL "ATD%s;\r"
>>
>>  without semicolon, phone wasnt dialing the number.
>>
> According to HFP spec there should not be semicolon, this might be an
> interoperability issue.
>
> Thanks,
> Forrest
>

2009-04-10 02:37:36

by Zhao Forrest

[permalink] [raw]
Subject: Re: [PATCH 4/4] IPC integration part for HFP Audio gateway -- take5

On Fri, Apr 10, 2009 at 1:14 AM, Rajan Batra <[email protected]> wrote:
> Hello,
> ? i used today's git bluez head code for headset gateway. i am able
> to dial the number. receive the call.
> but the voice stream is not starting. i have connected headphone to my
> bluez linux host.
> i am not able to hear or pass my voice to ?other side.
>
> do i have to do some setting in PA ?. ?or any extra settings.
Did you use the latest version of PA?

>
> i do following steps :
>
> 1) ? dbus-send --system --type=method_call --print-reply
> --dest=org.bluez /org/bluez/32112/hci0/dev_00_24_04_46_4E_FA
> org.bluez.HeadsetGateway.Connect
>
>
> 2) ?dbus-send --system --type=method_call --print-reply
> --dest=org.bluez /org/bluez/32112/hci0/dev_00_24_04_46_4E_FA
> org.bluez.HeadsetGateway.Call string:<number>
>
> i changed macro in gateway.c
> ? ? #define AG_PLACE_CALL "ATD%s\r"
> to
> ? ? #define AG_PLACE_CALL "ATD%s;\r"
>
> ?without semicolon, phone wasnt dialing the number.
>
According to HFP spec there should not be semicolon, this might be an
interoperability issue.

Thanks,
Forrest

2009-04-09 17:14:01

by Rajan Batra

[permalink] [raw]
Subject: Re: [PATCH 4/4] IPC integration part for HFP Audio gateway -- take5

Hello,
i used today's git bluez head code for headset gateway. i am able
to dial the number. receive the call.
but the voice stream is not starting. i have connected headphone to my
bluez linux host.
i am not able to hear or pass my voice to other side.

do i have to do some setting in PA ?. or any extra settings.

i do following steps :

1) dbus-send --system --type=method_call --print-reply
--dest=org.bluez /org/bluez/32112/hci0/dev_00_24_04_46_4E_FA
org.bluez.HeadsetGateway.Connect


2) dbus-send --system --type=method_call --print-reply
--dest=org.bluez /org/bluez/32112/hci0/dev_00_24_04_46_4E_FA
org.bluez.HeadsetGateway.Call string:<number>

i changed macro in gateway.c
#define AG_PLACE_CALL "ATD%s\r"
to
#define AG_PLACE_CALL "ATD%s;\r"

without semicolon, phone wasnt dialing the number.


-thanks and regards,
-rajan batra




On Wed, Apr 8, 2009 at 5:58 PM, Johan Hedberg <[email protected]> wrote:
> Hi Forrest,
>
> On Wed, Apr 08, 2009, Forrest Zhao wrote:
>> From: Forrest Zhao <[email protected]>
>>
>> ---
>>  audio/gateway.c |   77 +++++++++++++++++++++++++++++++++++++
>>  audio/gateway.h |    7 +++
>>  audio/unix.c    |  115 +++++++++++++++++++++++++++++++++++++++++++++++++++---
>>  3 files changed, 192 insertions(+), 7 deletions(-)
>
> Thanks! The patch has now been pushed upstream with some minor coding
> style fixes.
>
> Johan
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

2009-04-08 12:28:12

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 4/4] IPC integration part for HFP Audio gateway -- take5

Hi Forrest,

On Wed, Apr 08, 2009, Forrest Zhao wrote:
> From: Forrest Zhao <[email protected]>
>
> ---
> audio/gateway.c | 77 +++++++++++++++++++++++++++++++++++++
> audio/gateway.h | 7 +++
> audio/unix.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++---
> 3 files changed, 192 insertions(+), 7 deletions(-)

Thanks! The patch has now been pushed upstream with some minor coding
style fixes.

Johan