Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [RFC v4 6/6] Bluetooth: Manually enable or disable 6LoWPAN between devices
From: Marcel Holtmann @ 2013-11-14  8:07 UTC (permalink / raw)
  To: Jukka Rissanen; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1384337495-9043-7-git-send-email-jukka.rissanen@linux.intel.com>

Hi Jukka,

> This is a temporary patch where user can manually enable or
> disable BT 6LoWPAN functionality between devices.
> Eventually the connection is established automatically if
> the devices are advertising suitable capability and this patch
> can be removed.
> 
> Before connecting the devices do this
> 
> echo 1 > /sys/kernel/debug/bluetooth/hci0/6lowpan
> 
> This enables 6LoWPAN support and creates the bt0 interface
> automatically when devices are finally connected.
> 
> Rebooting or unloading the bluetooth kernel module will also clear the
> settings from the kernel.
> 
> Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
> ---
> net/bluetooth/6lowpan.c  | 105 +++++++++++++++++++++++++++++++++++++++++++++++
> net/bluetooth/6lowpan.h  |   1 +
> net/bluetooth/hci_core.c |   4 ++
> 3 files changed, 110 insertions(+)
> 
> diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
> index 5f0489c..579a75f 100644
> --- a/net/bluetooth/6lowpan.c
> +++ b/net/bluetooth/6lowpan.c
> @@ -26,6 +26,8 @@
>  */
> 
> #include <linux/version.h>
> +#include <linux/debugfs.h>
> +#include <linux/string.h>
> #include <linux/bitops.h>
> #include <linux/if_arp.h>
> #include <linux/netdevice.h>
> @@ -1571,6 +1573,109 @@ static struct notifier_block bt_6lowpan_dev_notifier = {
> 	.notifier_call = device_event,
> };
> 
> +static LIST_HEAD(user_enabled);
> +DEFINE_RWLOCK(enabled_lock);

make this one static as well.

> +
> +struct lowpan_enabled {
> +	__u8 dev_name[HCI_MAX_NAME_LENGTH];
> +	bool enabled;
> +	struct list_head list;
> +};
> +
> +static int debugfs_show(struct seq_file *f, void *p)
> +{
> +	struct lowpan_enabled *entry, *tmp;
> +	bool found = false;
> +
> +	write_lock(&enabled_lock);
> +	list_for_each_entry_safe(entry, tmp, &user_enabled, list) {
> +		seq_printf(f, "%d\n", entry->enabled);
> +		found = true;
> +	}
> +	write_unlock(&enabled_lock);
> +
> +	if (!found)
> +		seq_printf(f, "0\n");
> +
> +	return 0;
> +}

So I do not get this one. Why not just use the bit set in hci_dev. This looks like just wrong.

> +
> +static int debugfs_open(struct inode *inode, struct file *file)
> +{
> +	return single_open(file, debugfs_show, inode->i_private);
> +}
> +
> +static ssize_t writer(struct file *fp, const char __user *user_buffer,
> +		size_t count, loff_t *position)
> +{
> +	struct hci_dev *hdev = fp->f_inode->i_private;
> +	struct lowpan_enabled *entry = NULL, *tmp;
> +	bool new_value, old_value;
> +	char buf[3] = { 0 };
> +	ssize_t ret;
> +
> +	BT_DBG("dev %s count %zd", hdev->dev_name, count);
> +
> +        ret = simple_write_to_buffer(buf, 2, position, user_buffer, count);
> +	if (ret <= 0)
> +		return ret;
> +
> +	if (strtobool(buf, &new_value) < 0)
> +		return -EINVAL;
> +
> +	ret = -ENOENT;
> +
> +	write_lock(&enabled_lock);
> +	list_for_each_entry_safe(entry, tmp, &user_enabled, list) {
> +		if (!strncmp(entry->dev_name, hdev->dev_name,
> +						HCI_MAX_NAME_LENGTH)) {
> +			old_value = entry->enabled;
> +			entry->enabled = new_value;
> +			ret = 0;
> +			break;
> +		}
> +	}
> +	write_unlock(&enabled_lock);
> +
> +	if (ret == 0 && old_value == new_value)
> +		return count;
> +
> +	if (ret < 0) {
> +		entry = kzalloc(sizeof(*entry), GFP_KERNEL);
> +		if (!entry)
> +			return -ENOMEM;
> +
> +		strncpy(entry->dev_name, hdev->dev_name, HCI_MAX_NAME_LENGTH);
> +		entry->enabled = new_value;
> +
> +		write_lock(&enabled_lock);
> +		INIT_LIST_HEAD(&entry->list);
> +		list_add(&entry->list, &user_enabled);
> +		write_unlock(&enabled_lock);
> +	}
> +
> +	if (new_value == true)
> +		set_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags);
> +	else
> +		clear_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags);
> +
> +	return count;
> +}
> +
> +static const struct file_operations ble_6lowpan_debugfs_fops = {
> +	.open		= debugfs_open,
> +	.read		= seq_read,
> +	.write		= writer,
> +	.llseek		= seq_lseek,
> +	.release	= single_release,
> +};
> +
> +void bt_6lowpan_add_debugfs(struct hci_dev *hdev)
> +{
> +	debugfs_create_file("6lowpan", 0644, hdev->debugfs, hdev,
> +			&ble_6lowpan_debugfs_fops);
> +}
> +
> int bt_6lowpan_init(void)
> {
> 	return register_netdevice_notifier(&bt_6lowpan_dev_notifier);
> diff --git a/net/bluetooth/6lowpan.h b/net/bluetooth/6lowpan.h
> index 680eac8..5f60cf2 100644
> --- a/net/bluetooth/6lowpan.h
> +++ b/net/bluetooth/6lowpan.h
> @@ -22,5 +22,6 @@ int bt_6lowpan_add_conn(struct l2cap_conn *conn);
> int bt_6lowpan_del_conn(struct l2cap_conn *conn);
> int bt_6lowpan_init(void);
> void bt_6lowpan_cleanup(void);
> +void bt_6lowpan_add_debugfs(struct hci_dev *hdev);
> 
> #endif /* __6LOWPAN_H */
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 03e8355..a229ce0 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -34,6 +34,8 @@
> #include <net/bluetooth/bluetooth.h>
> #include <net/bluetooth/hci_core.h>
> 
> +#include "6lowpan.h"
> +
> static void hci_rx_work(struct work_struct *work);
> static void hci_cmd_work(struct work_struct *work);
> static void hci_tx_work(struct work_struct *work);
> @@ -1408,6 +1410,8 @@ static int __hci_init(struct hci_dev *hdev)
> 				    hdev, &conn_max_interval_fops);
> 	}
> 
> +	bt_6lowpan_add_debugfs(hdev);
> +

Since we only set the HCI_6LOWPAN_ENABLED bit, why not move this whole code into hci_core.c. It is just setting the bit, right?

Regards

Marcel


^ permalink raw reply

* Re: bluetoothd failure after a "malloc retun NULL" injection (attachment fix)
From: Johan Hedberg @ 2013-11-14  8:19 UTC (permalink / raw)
  To: Marcel Holtmann
  Cc: Luiz Augusto von Dentz, Oprisenescu, CatalinX,
	linux-bluetooth@vger.kernel.org, Trandafir, IonutX
In-Reply-To: <E03FE70C-ECC4-4D7D-917E-6F3E92297C1C@holtmann.org>

Hi Marcel,

On Thu, Nov 14, 2013, Marcel Holtmann wrote:
> >> Following is an issue encountered and handled using bluez-5.10 on a
> >> 32bit Tizen 2.0 IVI based distribution.
> >> 
> >> If malloc returns a random NULL bluetoothd exits with core dumped.
> >> In this case we do the following:
> >>      -start bluetoothd,
> >>      -at a random malloc call from any library (*lib*.so*), a random NULL will be returned by bluetoothd with a ld_preloaded library.
> >> 
> >> ~# LD_PRELOAD=/root/lib_wrapper.so /usr/libexec/bluetooth/bluetoothd -E
> >> 
> >> Analyzing the dump, it points directly to a DBUS_ERROR_NO_MEMORY
> >> which, after handling, keeps bluetoothd from dumping and allowing
> >> it to return the fatal error occurred as exit status, thus failing
> >> gracefully.
> >> 
> >> A fix proposal, handling the use-case is attached.
> > 
> > Im afraid if we start treating all the out of memory cases we wont
> > have time to do anything else, and quite frankly if this happens for
> > real the least concern would be bluetoothd, so I believe we should
> > just treat OOM cases as unrecoverable. Since this can happen with any
> > dbus_error, I would probably suggest to wrap it perhaps we a
> > g_dbus_error API that does assert in OOM.
> 
> I am fine with fixing obvious ones. However long-term these tiny sized
> memory allocation must just abort the program if we run out of memory.
> Since there is no recovery from it anyway.

Did you actually take a look at the patch? It's not exactly fixing any
missing error checks but only modifying the behavior if the error is OOM
by not doing a g_printerr call in that case. However, the main()
function still does an error() call when connect_dbus() returns failure
(even if it's -ENOMEM) so I don't really see how this particular patch
would fix any obvious OOM handling issue.

Johan

^ permalink raw reply

* Re: [PATCH] Enable autosuspend for Intel Bluetooth device
From: Marcel Holtmann @ 2013-11-14  8:19 UTC (permalink / raw)
  To: Tedd Ho-Jeong An; +Cc: linux-bluetooth@vger.kernel.org development, Don Fry
In-Reply-To: <20131112131641.76cd6c5f@han1-desk-dev>

Hi Tedd,

> This patch enables autosuspend for Intel Bluetooth device.
> 
> After btusb is loaded for Intel Bluetooth device, the power/control
> attribute contains "on" value by default which disables the autosuspend.
> Based on the USB PM document(Documentation/usb/power-management.txt),
> kernel disabled the autosuspend for all devices other than hub by default.
> 
> "The USB specification states that all USB devices must support power
> management.  Nevertheless, the sad fact is that many devices do not
> support it very well.  You can suspend them all right, but when you
> try to resume them they disconnect themselves from the USB bus or
> they stop working entirely.  This seems to be especially prevalent
> among printers and scanners, but plenty of other types of device have
> the same deficiency.
> 
> For this reason, by default the kernel disables autosuspend (the
> power/control attribute is initialized to "on") for all devices other
> than hubs.  Hubs, at least, appear to be reasonably well-behaved in
> this regard."
> 
> This document also described how the driver can enables the autosuspend
> by using an USB api.
> 
> "Drivers can enable autosuspend for their devices by calling
> 
> 	usb_enable_autosuspend(struct usb_device *udev);
> 
> in their probe() routine, if they know that the device is capable of
> suspending and resuming correctly.  This is exactly equivalent to
> writing "auto" to the device's power/control attribute."
> 
> For Intel Bluetooth device, the autosuspend needs to be enabled so the
> device can transit to LPM(Low Power Mode) and ULPM(Ultra LPM) states after
> receiving suspend message from the host.
> 
> Signed-off-by: Tedd Ho-Jeong An <tedd.an@intel.com>
> ---
> drivers/bluetooth/btusb.c |    4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)

patch has been applied to bluetooth-next tree.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH] Bluetooth: Add support for Intel Bluetooth device [8087:0a2a]
From: Marcel Holtmann @ 2013-11-14  8:20 UTC (permalink / raw)
  To: Tedd Ho-Jeong An; +Cc: linux-bluetooth@vger.kernel.org development, Don Fry
In-Reply-To: <20131112131058.6c23affb@han1-desk-dev>

Hi Tedd,

> This patch adds support for new Intel Bluetooth device.
> 
> T:  Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  4 Spd=12   MxCh= 0
> D:  Ver= 2.01 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
> P:  Vendor=8087 ProdID=0a2a Rev= 0.01
> C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA
> I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E:  Ad=81(I) Atr=03(Int.) MxPS=  64 Ivl=1ms
> E:  Ad=02(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms
> E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms
> I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E:  Ad=03(O) Atr=01(Isoc) MxPS=   0 Ivl=1ms
> E:  Ad=83(I) Atr=01(Isoc) MxPS=   0 Ivl=1ms
> I:  If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E:  Ad=03(O) Atr=01(Isoc) MxPS=   9 Ivl=1ms
> E:  Ad=83(I) Atr=01(Isoc) MxPS=   9 Ivl=1ms
> I:  If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E:  Ad=03(O) Atr=01(Isoc) MxPS=  17 Ivl=1ms
> E:  Ad=83(I) Atr=01(Isoc) MxPS=  17 Ivl=1ms
> I:  If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E:  Ad=03(O) Atr=01(Isoc) MxPS=  25 Ivl=1ms
> E:  Ad=83(I) Atr=01(Isoc) MxPS=  25 Ivl=1ms
> I:  If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E:  Ad=03(O) Atr=01(Isoc) MxPS=  33 Ivl=1ms
> E:  Ad=83(I) Atr=01(Isoc) MxPS=  33 Ivl=1ms
> I:  If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E:  Ad=03(O) Atr=01(Isoc) MxPS=  49 Ivl=1ms
> E:  Ad=83(I) Atr=01(Isoc) MxPS=  49 Ivl=1ms
> 
> Signed-off-by: Tedd Ho-Jeong An <tedd.an@intel.com>
> ---
> drivers/bluetooth/btusb.c |    1 +
> 1 file changed, 1 insertion(+)

patch has been applied to bluetooth-next tree.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH] android/debug: Move debug functions to hal-utils.c
From: Johan Hedberg @ 2013-11-14  9:05 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1384413276-29884-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

On Thu, Nov 14, 2013, Andrei Emeltchenko wrote:
> Debug functions will be used by HALs and haltest.
> ---
>  android/Android.mk        |    2 -
>  android/Makefile.am       |    3 -
>  android/client/if-av.c    |    1 +
>  android/client/if-bt.c    |    1 +
>  android/client/if-hf.c    |    1 +
>  android/client/if-hh.c    |    1 +
>  android/client/if-main.h  |    2 -
>  android/client/if-pan.c   |    1 +
>  android/client/if-sock.c  |    1 +
>  android/client/textconv.c |  300 ---------------------------------------------
>  android/client/textconv.h |  120 ------------------
>  android/hal-bluetooth.c   |    3 +-
>  android/hal-utils.c       |  269 ++++++++++++++++++++++++++++++++++++++++
>  android/hal-utils.h       |  103 ++++++++++++++++
>  14 files changed, 379 insertions(+), 429 deletions(-)
>  delete mode 100644 android/client/textconv.c
>  delete mode 100644 android/client/textconv.h

Applied. Thanks.

Johan

^ permalink raw reply

* Re: Adapter name reset on suspend/resume
From: Bastien Nocera @ 2013-11-14  9:31 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <130CE89B-A508-4FB9-B7EA-35D500742EC1@holtmann.org>

On Thu, 2013-11-14 at 08:28 +0900, Marcel Holtmann wrote:
> Hi Bastien,
> 
> > After suspending and resuming my laptop, hci0's name is reset to what
> > looks like the factory name:
> > $ hciconfig -a | grep Name
> > 	Name: 'BCM20702A'
> > 
> > This is the device in question:
> > Bus 001 Device 004: ID 0a5c:21e6 Broadcom Corp. BCM20702 Bluetooth 4.0 [ThinkPad]
> > 
> > And my laptop is a Lenovo X1 Carbon.
> > 
> > Neither udevadm nor btmon show the device going away on suspend and
> > coming back on resume.
> 
> can you start btmon, call hciconfig hci0 name, then suspend, then
> resume, call hciconfig hci0 name again.

Bluetooth monitor ver 5.10
= New Index: F4:B7:E2:E8:99:E2 (BR/EDR,USB,hci0)                   [hci0] 0.176335
< HCI Command: Read Local Name (0x03|0x0014) plen 0                [hci0] 9.797930
> HCI Event: Command Complete (0x0e) plen 252                      [hci0] 9.813834
      Read Local Name (0x03|0x0014) ncmd 1
        Status: Success (0x00)
        Name: nuvo
< HCI Command: Read Local Name (0x03|0x0014) plen 0               [hci0] 33.109166
> HCI Event: Command Complete (0x0e) plen 252                     [hci0] 33.125157
      Read Local Name (0x03|0x0014) ncmd 1
        Status: Success (0x00)
        Name: BCM20702A

> I am wondering if for some reason the suspend/resume actually does a
> HCI Reset without telling us. The name normally only gets reset to
> BCM20702A when doing a full reset.

Looks like that's what it's doing.

> Another possibility is that we actually forgot to set it in the first
> place. I am pretty sure I have intensively tested and that should not
> happen, but you might just found a corner case.

It's set on a normal boot, it seems to be reset only when suspending.

Cheers

^ permalink raw reply

* Re: bluetoothd failure after a "malloc retun NULL" injection (attachment fix)
From: Luiz Augusto von Dentz @ 2013-11-14  9:37 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz, Oprisenescu, CatalinX,
	linux-bluetooth@vger.kernel.org, Trandafir, IonutX
In-Reply-To: <20131114081937.GA2019@x220.p-661hnu-f1>

Hi Johan,

On Thu, Nov 14, 2013 at 10:19 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> Hi Marcel,
>
> On Thu, Nov 14, 2013, Marcel Holtmann wrote:
>> >> Following is an issue encountered and handled using bluez-5.10 on a
>> >> 32bit Tizen 2.0 IVI based distribution.
>> >>
>> >> If malloc returns a random NULL bluetoothd exits with core dumped.
>> >> In this case we do the following:
>> >>      -start bluetoothd,
>> >>      -at a random malloc call from any library (*lib*.so*), a random NULL will be returned by bluetoothd with a ld_preloaded library.
>> >>
>> >> ~# LD_PRELOAD=/root/lib_wrapper.so /usr/libexec/bluetooth/bluetoothd -E
>> >>
>> >> Analyzing the dump, it points directly to a DBUS_ERROR_NO_MEMORY
>> >> which, after handling, keeps bluetoothd from dumping and allowing
>> >> it to return the fatal error occurred as exit status, thus failing
>> >> gracefully.
>> >>
>> >> A fix proposal, handling the use-case is attached.
>> >
>> > Im afraid if we start treating all the out of memory cases we wont
>> > have time to do anything else, and quite frankly if this happens for
>> > real the least concern would be bluetoothd, so I believe we should
>> > just treat OOM cases as unrecoverable. Since this can happen with any
>> > dbus_error, I would probably suggest to wrap it perhaps we a
>> > g_dbus_error API that does assert in OOM.
>>
>> I am fine with fixing obvious ones. However long-term these tiny sized
>> memory allocation must just abort the program if we run out of memory.
>> Since there is no recovery from it anyway.
>
> Did you actually take a look at the patch? It's not exactly fixing any
> missing error checks but only modifying the behavior if the error is OOM
> by not doing a g_printerr call in that case. However, the main()
> function still does an error() call when connect_dbus() returns failure
> (even if it's -ENOMEM) so I don't really see how this particular patch
> would fix any obvious OOM handling issue.

Yep, I was thinking more in the following:

diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
index 9542109..ced55d9 100644
--- a/gdbus/gdbus.h
+++ b/gdbus/gdbus.h
@@ -216,6 +216,7 @@ struct GDBusSecurityTable {
        .flags = G_DBUS_SIGNAL_FLAG_EXPERIMENTAL

 void g_dbus_set_flags(int flags);
+gboolean g_dbus_error_is_set(DBusError *err);

 gboolean g_dbus_register_interface(DBusConnection *connection,
                                        const char *path, const char *name,
diff --git a/gdbus/object.c b/gdbus/object.c
index b248cbb..699c7e2 100644
--- a/gdbus/object.c
+++ b/gdbus/object.c
@@ -27,6 +27,7 @@

 #include <stdio.h>
 #include <string.h>
+#include <assert.h>

 #include <glib.h>
 #include <dbus/dbus.h>
@@ -1820,3 +1821,16 @@ void g_dbus_set_flags(int flags)
 {
        global_flags = flags;
 }
+
+gboolean g_dbus_error_is_set(DBusError *err)
+{
+       dbus_bool_t ret;
+
+       ret = dbus_error_is_set(err);
+       if (!ret)
+               return FALSE;
+
+       assert(!dbus_error_has_name(err, DBUS_ERROR_NO_MEMORY));
+
+       return TRUE;
+}

But perhaps there is a way to set libdbus to not handle OOM cases and
just assert/exit, the interesting part is that even in dbus code
itself there are comments like this:

     /* FIXME have less lame handling for OOM, we just silently fail to
      * watch.  (In reality though, the whole OOM handling in dbus is
      * stupid but we won't go into that in this comment =) )
      */


-- 
Luiz Augusto von Dentz

^ permalink raw reply related

* [PATCH BlueZ 1/7] android/hal-a2dp: Use conn_state instead of connection_state
From: Luiz Augusto von Dentz @ 2013-11-14 10:18 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This is shorter and more consistent with other HAL such as HID.
---
 android/hal-a2dp.c | 8 ++++----
 android/hal-msg.h  | 6 +++---
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/android/hal-a2dp.c b/android/hal-a2dp.c
index 4fe7c20..cdb5229 100644
--- a/android/hal-a2dp.c
+++ b/android/hal-a2dp.c
@@ -31,9 +31,9 @@ static bool interface_ready(void)
 	return cbs != NULL;
 }
 
-static void handle_connection_state(void *buf)
+static void handle_conn_state(void *buf)
 {
-	struct hal_ev_a2dp_connection_state *ev = buf;
+	struct hal_ev_a2dp_conn_state *ev = buf;
 
 	if (cbs->connection_state_cb)
 		cbs->connection_state_cb(ev->state,
@@ -55,8 +55,8 @@ void bt_notify_a2dp(uint8_t opcode, void *buf, uint16_t len)
 		return;
 
 	switch (opcode) {
-	case HAL_EV_A2DP_CONNECTION_STATE:
-		handle_connection_state(buf);
+	case HAL_EV_A2DP_CONN_STATE:
+		handle_conn_state(buf);
 		break;
 	case HAL_EV_A2DP_AUDIO_STATE:
 		handle_audio_state(buf);
diff --git a/android/hal-msg.h b/android/hal-msg.h
index 847cc1f..30fe624 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -530,13 +530,13 @@ struct hal_ev_pan_conn_state {
 	uint8_t  remote_role;
 } __attribute__((packed));
 
-#define HAL_EV_A2DP_CONNECTION_STATE	0x81
-struct hal_ev_a2dp_connection_state {
+#define HAL_EV_A2DP_CONN_STATE			0x81
+struct hal_ev_a2dp_conn_state {
 	uint8_t state;
 	uint8_t bdaddr[6];
 } __attribute__((packed));
 
-#define HAL_EV_A2DP_AUDIO_STATE	0x82
+#define HAL_EV_A2DP_AUDIO_STATE			0x82
 struct hal_ev_a2dp_audio_state {
 	uint8_t state;
 	uint8_t bdaddr[6];
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH BlueZ 2/7] android/hal-a2dp: Add implemention of .init
From: Luiz Augusto von Dentz @ 2013-11-14 10:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384424301-31265-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 android/hal-a2dp.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/android/hal-a2dp.c b/android/hal-a2dp.c
index cdb5229..50a36fb 100644
--- a/android/hal-a2dp.c
+++ b/android/hal-a2dp.c
@@ -99,13 +99,16 @@ static bt_status_t disconnect(bt_bdaddr_t *bd_addr)
 
 static bt_status_t init(btav_callbacks_t *callbacks)
 {
+	struct hal_cmd_register_module cmd;
+
 	DBG("");
 
 	cbs = callbacks;
 
-	/* TODO: enable service */
+	cmd.service_id = HAL_SERVICE_ID_A2DP;
 
-	return BT_STATUS_SUCCESS;
+	return hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
+					sizeof(cmd), &cmd, 0, NULL, NULL);
 }
 
 static void cleanup()
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH BlueZ 3/7] android/hal-a2dp: Add implemention of .cleanup
From: Luiz Augusto von Dentz @ 2013-11-14 10:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384424301-31265-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 android/hal-a2dp.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/android/hal-a2dp.c b/android/hal-a2dp.c
index 50a36fb..e9fadb7 100644
--- a/android/hal-a2dp.c
+++ b/android/hal-a2dp.c
@@ -113,14 +113,19 @@ static bt_status_t init(btav_callbacks_t *callbacks)
 
 static void cleanup()
 {
+	struct hal_cmd_unregister_module cmd;
+
 	DBG("");
 
 	if (!interface_ready())
 		return;
 
-	/* TODO: disable service */
-
 	cbs = NULL;
+
+	cmd.service_id = HAL_SERVICE_ID_A2DP;
+
+	hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
+					sizeof(cmd), &cmd, 0, NULL, NULL);
 }
 
 static btav_interface_t iface = {
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH BlueZ 4/7] android/hal-a2dp: Add defines for possible connection states
From: Luiz Augusto von Dentz @ 2013-11-14 10:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384424301-31265-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 android/hal-msg.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/android/hal-msg.h b/android/hal-msg.h
index 30fe624..44fd5c8 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -530,6 +530,11 @@ struct hal_ev_pan_conn_state {
 	uint8_t  remote_role;
 } __attribute__((packed));
 
+#define HAL_A2DP_STATE_DISCONNECTED		0x00
+#define HAL_A2DP_STATE_CONNECTING		0x01
+#define HAL_A2DP_STATE_CONNECTED		0x02
+#define HAL_A2DP_STATE_DISCONNECTING		0x03
+
 #define HAL_EV_A2DP_CONN_STATE			0x81
 struct hal_ev_a2dp_conn_state {
 	uint8_t state;
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH BlueZ 5/7] android/a2dp: Add initial implementation of socket handling
From: Luiz Augusto von Dentz @ 2013-11-14 10:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384424301-31265-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This adds initial code to handle incoming connection and notifying
connection states.
---
 android/a2dp.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 132 insertions(+)

diff --git a/android/a2dp.c b/android/a2dp.c
index 052f4f3..5ffb8ae 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -32,13 +32,77 @@
 #include <fcntl.h>
 #include <glib.h>
 
+#include "btio/btio.h"
 #include "lib/bluetooth.h"
 #include "log.h"
 #include "a2dp.h"
 #include "hal-msg.h"
 #include "ipc.h"
+#include "utils.h"
+
+#define L2CAP_PSM_AVDTP 0x19
 
 static int notification_sk = -1;
+static GIOChannel *io = NULL;
+static GSList *devices = NULL;
+
+struct a2dp_device {
+	bdaddr_t	dst;
+	uint8_t		state;
+	GIOChannel	*io;
+	guint		watch;
+};
+
+static int device_cmp(gconstpointer s, gconstpointer user_data)
+{
+	const struct a2dp_device *dev = s;
+	const bdaddr_t *dst = user_data;
+
+	return bacmp(&dev->dst, dst);
+}
+
+static void a2dp_device_free(struct a2dp_device *dev)
+{
+	if (dev->watch > 0)
+		g_source_remove(dev->watch);
+
+	if (dev->io)
+		g_io_channel_unref(dev->io);
+
+	devices = g_slist_remove(devices, dev);
+	g_free(dev);
+}
+
+static struct a2dp_device *a2dp_device_new(const bdaddr_t *dst)
+{
+	struct a2dp_device *dev;
+
+	dev = g_new0(struct a2dp_device, 1);
+	bacpy(&dev->dst, dst);
+	devices = g_slist_prepend(devices, dev);
+
+	return dev;
+}
+
+static void bt_a2dp_notify_state(struct a2dp_device *dev, uint8_t state)
+{
+	struct hal_ev_a2dp_conn_state ev;
+	char address[18];
+
+	if (dev->state == state)
+		return;
+
+	dev->state = state;
+
+	ba2str(&dev->dst, address);
+	DBG("device %s state %u", address, state);
+
+	bdaddr2android(&dev->dst, ev.bdaddr);
+	ev.state = state;
+
+	ipc_send(notification_sk, HAL_SERVICE_ID_A2DP,
+			HAL_EV_A2DP_CONN_STATE, sizeof(ev), &ev, -1);
+}
 
 static uint8_t bt_a2dp_connect(struct hal_cmd_a2dp_connect *cmd, uint16_t len)
 {
@@ -74,10 +138,72 @@ void bt_a2dp_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
 	ipc_send_rsp(sk, HAL_SERVICE_ID_A2DP, status);
 }
 
+static gboolean watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
+{
+	struct a2dp_device *dev = data;
+
+	bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTED);
+
+	a2dp_device_free(dev);
+
+	return FALSE;
+}
+
+static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
+{
+	struct a2dp_device *dev;
+	bdaddr_t src, dst;
+	char address[18];
+	GError *gerr = NULL;
+	GSList *l;
+
+	if (err) {
+		error("%s", err->message);
+		return;
+	}
+
+	bt_io_get(chan, &gerr,
+			BT_IO_OPT_SOURCE_BDADDR, &src,
+			BT_IO_OPT_DEST_BDADDR, &dst,
+			BT_IO_OPT_INVALID);
+	if (gerr) {
+		error("%s", gerr->message);
+		g_error_free(gerr);
+		g_io_channel_shutdown(chan, TRUE, NULL);
+		return;
+	}
+
+	l = g_slist_find_custom(devices, &dst, device_cmp);
+	if (l)
+		return;
+
+	ba2str(&dst, address);
+	DBG("Incoming connection from %s", address);
+
+	dev = a2dp_device_new(&dst);
+	dev->watch = g_io_add_watch(dev->io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+								watch_cb, dev);
+
+	bt_a2dp_notify_state(dev, HAL_A2DP_STATE_CONNECTED);
+}
+
 bool bt_a2dp_register(int sk, const bdaddr_t *addr)
 {
+	GError *err = NULL;
+
 	DBG("");
 
+	io = bt_io_listen(connect_cb, NULL, NULL, NULL, &err,
+				BT_IO_OPT_SOURCE_BDADDR, addr,
+				BT_IO_OPT_PSM, L2CAP_PSM_AVDTP,
+				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+				BT_IO_OPT_INVALID);
+	if (!io) {
+		error("Failed to listen on AVDTP channel: %s", err->message);
+		g_error_free(err);
+		return false;
+	}
+
 	notification_sk = sk;
 
 	return true;
@@ -88,4 +214,10 @@ void bt_a2dp_unregister(void)
 	DBG("");
 
 	notification_sk = -1;
+
+	if (io) {
+		g_io_channel_shutdown(io, TRUE, NULL);
+		g_io_channel_unref(io);
+		io = NULL;
+	}
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH BlueZ 6/7] android/a2dp: Add initial implementation of HAL_OP_A2DP_CONNECT
From: Luiz Augusto von Dentz @ 2013-11-14 10:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384424301-31265-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 android/a2dp.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 71 insertions(+), 18 deletions(-)

diff --git a/android/a2dp.c b/android/a2dp.c
index 5ffb8ae..adbad05 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -45,6 +45,7 @@
 static int notification_sk = -1;
 static GIOChannel *io = NULL;
 static GSList *devices = NULL;
+static const bdaddr_t *adapter_addr = NULL;
 
 struct a2dp_device {
 	bdaddr_t	dst;
@@ -104,11 +105,74 @@ static void bt_a2dp_notify_state(struct a2dp_device *dev, uint8_t state)
 			HAL_EV_A2DP_CONN_STATE, sizeof(ev), &ev, -1);
 }
 
+static gboolean watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
+{
+	struct a2dp_device *dev = data;
+
+	bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTED);
+
+	a2dp_device_free(dev);
+
+	return FALSE;
+}
+
+static void signaling_connect_cb(GIOChannel *chan, GError *err,
+							gpointer user_data)
+{
+	struct a2dp_device *dev = user_data;
+
+	if (err) {
+		bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTED);
+		error("%s", err->message);
+		a2dp_device_free(dev);
+		return;
+	}
+
+	dev->watch = g_io_add_watch(dev->io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+								watch_cb, dev);
+
+	bt_a2dp_notify_state(dev, HAL_A2DP_STATE_CONNECTED);
+}
+
 static uint8_t bt_a2dp_connect(struct hal_cmd_a2dp_connect *cmd, uint16_t len)
 {
-	DBG("Not Implemented");
+	struct a2dp_device *dev;
+	char addr[18];
+	bdaddr_t dst;
+	GSList *l;
+	GError *err = NULL;
 
-	return HAL_STATUS_FAILED;
+	DBG("");
+
+	if (len < sizeof(*cmd))
+		return HAL_STATUS_INVALID;
+
+	android2bdaddr(&cmd->bdaddr, &dst);
+
+	l = g_slist_find_custom(devices, &dst, device_cmp);
+	if (l)
+		return HAL_STATUS_FAILED;
+
+	dev = a2dp_device_new(&dst);
+	dev->io = bt_io_connect(signaling_connect_cb, dev, NULL, &err,
+					BT_IO_OPT_SOURCE_BDADDR, adapter_addr,
+					BT_IO_OPT_DEST_BDADDR, &dev->dst,
+					BT_IO_OPT_PSM, L2CAP_PSM_AVDTP,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+					BT_IO_OPT_INVALID);
+	if (err) {
+		error("%s", err->message);
+		g_error_free(err);
+		a2dp_device_free(dev);
+		return HAL_STATUS_FAILED;
+	}
+
+	ba2str(&dev->dst, addr);
+	DBG("connecting to %s", addr);
+
+	bt_a2dp_notify_state(dev, HAL_A2DP_STATE_CONNECTING);
+
+	return HAL_STATUS_SUCCESS;
 }
 
 static uint8_t bt_a2dp_disconnect(struct hal_cmd_a2dp_connect *cmd,
@@ -138,17 +202,6 @@ void bt_a2dp_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
 	ipc_send_rsp(sk, HAL_SERVICE_ID_A2DP, status);
 }
 
-static gboolean watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
-{
-	struct a2dp_device *dev = data;
-
-	bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTED);
-
-	a2dp_device_free(dev);
-
-	return FALSE;
-}
-
 static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 {
 	struct a2dp_device *dev;
@@ -181,10 +234,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 	DBG("Incoming connection from %s", address);
 
 	dev = a2dp_device_new(&dst);
-	dev->watch = g_io_add_watch(dev->io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-								watch_cb, dev);
-
-	bt_a2dp_notify_state(dev, HAL_A2DP_STATE_CONNECTED);
+	signaling_connect_cb(chan, err, dev);
 }
 
 bool bt_a2dp_register(int sk, const bdaddr_t *addr)
@@ -193,8 +243,10 @@ bool bt_a2dp_register(int sk, const bdaddr_t *addr)
 
 	DBG("");
 
+	adapter_addr = addr;
+
 	io = bt_io_listen(connect_cb, NULL, NULL, NULL, &err,
-				BT_IO_OPT_SOURCE_BDADDR, addr,
+				BT_IO_OPT_SOURCE_BDADDR, adapter_addr,
 				BT_IO_OPT_PSM, L2CAP_PSM_AVDTP,
 				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
 				BT_IO_OPT_INVALID);
@@ -213,6 +265,7 @@ void bt_a2dp_unregister(void)
 {
 	DBG("");
 
+	adapter_addr = NULL;
 	notification_sk = -1;
 
 	if (io) {
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH BlueZ 7/7] android/a2dp: Add initial implementation of HAL_OP_A2DP_DISCONNECT
From: Luiz Augusto von Dentz @ 2013-11-14 10:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384424301-31265-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 android/a2dp.c | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/android/a2dp.c b/android/a2dp.c
index adbad05..6d2f8a3 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -178,9 +178,30 @@ static uint8_t bt_a2dp_connect(struct hal_cmd_a2dp_connect *cmd, uint16_t len)
 static uint8_t bt_a2dp_disconnect(struct hal_cmd_a2dp_connect *cmd,
 								uint16_t len)
 {
-	DBG("Not Implemented");
+	struct a2dp_device *dev;
+	GSList *l;
+	bdaddr_t dst;
+
+	DBG("");
+
+	if (len < sizeof(*cmd))
+		return HAL_STATUS_INVALID;
+
+	android2bdaddr(&cmd->bdaddr, &dst);
+
+	l = g_slist_find_custom(devices, &dst, device_cmp);
+	if (!l)
+		return HAL_STATUS_FAILED;
+
+	dev = l->data;
 
-	return HAL_STATUS_FAILED;
+	/* Wait signaling channel to HUP */
+	if (dev->io)
+		g_io_channel_shutdown(dev->io, TRUE, NULL);
+
+	bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTING);
+
+	return HAL_STATUS_SUCCESS;
 }
 
 void bt_a2dp_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
-- 
1.8.3.1


^ permalink raw reply related

* Re: [PATCH BlueZ 1/7] android/hal-a2dp: Use conn_state instead of connection_state
From: Johan Hedberg @ 2013-11-14 12:26 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1384424301-31265-1-git-send-email-luiz.dentz@gmail.com>

Hi Luiz,

On Thu, Nov 14, 2013, Luiz Augusto von Dentz wrote:
> This is shorter and more consistent with other HAL such as HID.
> ---
>  android/hal-a2dp.c | 8 ++++----
>  android/hal-msg.h  | 6 +++---
>  2 files changed, 7 insertions(+), 7 deletions(-)

Applied with the couple of tweaks that we discussed offline. Thanks.

Johan

^ permalink raw reply

* [PATCH BlueZ] core: Do not change service state in btd_service_connect if it fails
From: Luiz Augusto von Dentz @ 2013-11-14 12:27 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

If .connect fails and the service state changes it may re-enter
connect_next, inverting the order and messing up the error of each
connect request.
---
 src/service.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/src/service.c b/src/service.c
index 52a8291..7a480d6 100644
--- a/src/service.c
+++ b/src/service.c
@@ -198,18 +198,16 @@ int btd_service_connect(struct btd_service *service)
 		return -EBUSY;
 	}
 
-	change_state(service, BTD_SERVICE_STATE_CONNECTING, 0);
-
 	err = profile->connect(service);
-	if (err == 0)
+	if (err == 0) {
+		change_state(service, BTD_SERVICE_STATE_CONNECTING, 0);
 		return 0;
+	}
 
 	ba2str(device_get_address(service->device), addr);
 	error("%s profile connect failed for %s: %s", profile->name, addr,
 								strerror(-err));
 
-	btd_service_connecting_complete(service, err);
-
 	return err;
 }
 
-- 
1.8.3.1


^ permalink raw reply related

* Re: [PATCH v2 0/8] android: Some adapter and mgmt handling code cleanup
From: Johan Hedberg @ 2013-11-14 12:59 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth, Szymon Janc
In-Reply-To: <1384300100-8941-1-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

On Tue, Nov 12, 2013, Szymon Janc wrote:
> v2:
>  - addressed Johan comments about using static adapter structure instead of
>    bunch of static adapter_* variables
>  - Added a patch for utilizing mgmt library for passing adapter ready callback
>    (patch 3)
> 
> v1:
>   This patchset moves mgmt initalization handling from main.c to adapter.c so
>   now all mgmt handling is done from adaper.c. Adapter.c is also renamed to
>   bluetooth.c to match service name implemented by it.
> 
>   Startup and shutdown timeouts are still handled in main.c (mostly due to
>   both resulting in mainloop shutdown so extra callback are avoided).
> 
>   IO handling and commands dispatch is still done in main.c
> 
> 
> Comments are welcome.
> 
> -- 
> BR
> Szymon Janc
> 
> Szymon Janc (8):
>   android: Make adapter static
>   android: Move adapter initialization to adapter.c
>   android: Don't use static pointer for storing adapter_ready callback
>   android/hidhost: Use adapter address provided on register
>   android: Report adapter address in adapter_ready callback
>   android: Remove not needed bt_adapter_get_address function
>   android: Rename adapter.c to bluetooth.c
>   android: Rename bluetooth service functions to match service name
> 
>  android/Android.mk  |    2 +-
>  android/Makefile.am |    4 +-
>  android/adapter.c   | 2008 -----------------------------------------------
>  android/adapter.h   |   37 -
>  android/bluetooth.c | 2177 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  android/bluetooth.h |   38 +
>  android/hidhost.c   |   21 +-
>  android/main.c      |  314 ++------
>  8 files changed, 2287 insertions(+), 2314 deletions(-)
>  delete mode 100644 android/adapter.c
>  delete mode 100644 android/adapter.h
>  create mode 100644 android/bluetooth.c
>  create mode 100644 android/bluetooth.h

All patches in this set have been applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH BlueZ] core: Do not change service state in btd_service_connect if it fails
From: Johan Hedberg @ 2013-11-14 12:59 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1384432071-2703-1-git-send-email-luiz.dentz@gmail.com>

Hi Luiz,

On Thu, Nov 14, 2013, Luiz Augusto von Dentz wrote:
> If .connect fails and the service state changes it may re-enter
> connect_next, inverting the order and messing up the error of each
> connect request.
> ---
>  src/service.c | 8 +++-----
>  1 file changed, 3 insertions(+), 5 deletions(-)

Applied. Thanks.

Johan

^ permalink raw reply

* [PATCH 1/2] android: Add PTS PICS for GAP
From: Jakub Tyszkowski @ 2013-11-14 13:26 UTC (permalink / raw)
  To: linux-bluetooth

PTS PICS for GAP, targeting Android 4.4.

---
 android/pics-gap.txt | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 201 insertions(+)
 create mode 100644 android/pics-gap.txt

diff --git a/android/pics-gap.txt b/android/pics-gap.txt
new file mode 100644
index 0000000..bcb64cb
--- /dev/null
+++ b/android/pics-gap.txt
@@ -0,0 +1,201 @@
+GAP PICS for the PTS tool.
+
+* - different than PTS defaults
+
++------------------+------------+
+|  Parameter Name  |  Selected  |
++------------------+------------+
+| TSPC_GAP_0_1     |   False    |
+| TSPC_GAP_0_2     |   False    |
+| TSPC_GAP_0_3     |   True*    |
+| TSPC_GAP_0A_1    |   False    |
+| TSPC_GAP_1_1     |   True*    |
+| TSPC_GAP_1_2     |   False    |
+| TSPC_GAP_1_3     |   True*    |
+| TSPC_GAP_1_4     |   True*    |
+| TSPC_GAP_1_5     |   True     |
+| TSPC_GAP_1_6     |   False    |
+| TSPC_GAP_1_7     |   True*    |
+| TSPC_GAP_2_1     |   True*    |
+| TSPC_GAP_2_2     |   True*    |
+| TSPC_GAP_2_3     |   True*    |
+| TSPC_GAP_2_4     |   False    |
+| TSPC_GAP_2_5     |   True*    |
+| TSPC_GAP_2_6     |   False    |
+| TSPC_GAP_2_7     |   True*    |
+| TSPC_GAP_2_8     |   True*    |
+| TSPC_GAP_2_9     |   True*    |
+| TSPC_GAP_2_10    |   False    |
+| TSPC_GAP_3_1     |   True*    |
+| TSPC_GAP_3_2     |   False    |
+| TSPC_GAP_3_3     |   True*    |
+| TSPC_GAP_3_4     |   True*    |
+| TSPC_GAP_3_5     |   True*    |
+| TSPC_GAP_3_6     |   True*    |
+| TSPC_GAP_4_1     |   True     |
+| TSPC_GAP_4_2     |   True     |
+| TSPC_GAP_4_3     |   True*    |
+| TSPC_GAP_4_4     |   True     |
+| TSPC_GAP_4_5     |   True*    |
+| TSPC_GAP_4_6     |   True*    |
+| TSPC_GAP_5_1     |   False*   |
+| TSPC_GAP_5_2     |   False    |
+| TSPC_GAP_5_3     |   False*   |
+| TSPC_GAP_5_4     |   True*    |
+| TSPC_GAP_6_1     |   False*   |
+| TSPC_GAP_6_2     |   False    |
+| TSPC_GAP_7_1     |   False*   |
+| TSPC_GAP_7_2     |   False*   |
+| TSPC_GAP_8_1     |   False*   |
+| TSPC_GAP_8_2     |   False    |
+| TSPC_GAP_8A_1    |   False    |
+| TSPC_GAP_8A_2    |   False    |
+| TSPC_GAP_8A_3    |   False*   |
+| TSPC_GAP_8A_4    |   False    |
+| TSPC_GAP_8A_5    |   False    |
+| TSPC_GAP_8A_6    |   False    |
+| TSPC_GAP_8A_7    |   False    |
+| TSPC_GAP_8A_8    |   False    |
+| TSPC_GAP_8A_9    |   False    |
+| TSPC_GAP_8A_10   |   False    |
+| TSPC_GAP_9_1     |   False*   |
+| TSPC_GAP_10_1    |   False*   |
+| TSPC_GAP_11_1    |   False    |
+| TSPC_GAP_11_2    |   False    |
+| TSPC_GAP_12_1    |   True     |
+| TSPC_GAP_12_2    |   False    |
+| TSPC_GAP_13_1    |   True     |
+| TSPC_GAP_13_2    |   True     |
+| TSPC_GAP_14_1    |   True     |
+| TSPC_GAP_14_2    |   False    |
+| TSPC_GAP_15_1    |   True     |
+| TSPC_GAP_16_1    |   True     |
+| TSPC_GAP_17_1    |   False    |
+| TSPC_GAP_17_2    |   False    |
+| TSPC_GAP_17_3    |   False    |
+| TSPC_GAP_17_4    |   False    |
+| TSPC_GAP_18_1    |   False    |
+| TSPC_GAP_18_2    |   False    |
+| TSPC_GAP_19_1    |   False    |
+| TSPC_GAP_19_2    |   False    |
+| TSPC_GAP_19_3    |   False    |
+| TSPC_GAP_20_1    |   False    |
+| TSPC_GAP_20_2    |   False    |
+| TSPC_GAP_20_3    |   False    |
+| TSPC_GAP_20_4    |   False    |
+| TSPC_GAP_20A_1   |   False    |
+| TSPC_GAP_20A_2   |   False    |
+| TSPC_GAP_20A_3   |   False    |
+| TSPC_GAP_20A_4   |   False    |
+| TSPC_GAP_20A_5   |   False    |
+| TSPC_GAP_20A_6   |   False    |
+| TSPC_GAP_20A_7   |   False    |
+| TSPC_GAP_20A_8   |   False    |
+| TSPC_GAP_20A_9   |   False    |
+| TSPC_GAP_20A_10  |   False    |
+| TSPC_GAP_21_1    |   False*   |
+| TSPC_GAP_21_2    |   False*   |
+| TSPC_GAP_21_3    |   False    |
+| TSPC_GAP_21_4    |   False*   |
+| TSPC_GAP_21_5    |   False*   |
+| TSPC_GAP_21_6    |   False*   |
+| TSPC_GAP_22_1    |   False    |
+| TSPC_GAP_22_2    |   False    |
+| TSPC_GAP_22_3    |   False    |
+| TSPC_GAP_22_4    |   False    |
+| TSPC_GAP_23_1    |   False    |
+| TSPC_GAP_23_2    |   False    |
+| TSPC_GAP_23_3    |   False    |
+| TSPC_GAP_23_4    |   False    |
+| TSPC_GAP_23_5    |   False    |
+| TSPC_GAP_24_1    |   False    |
+| TSPC_GAP_24_2    |   False    |
+| TSPC_GAP_24_3    |   False    |
+| TSPC_GAP_24_4    |   False    |
+| TSPC_GAP_25_1    |   False    |
+| TSPC_GAP_25_2    |   False    |
+| TSPC_GAP_25_3    |   False    |
+| TSPC_GAP_25_4    |   False    |
+| TSPC_GAP_25_5    |   False    |
+| TSPC_GAP_25_6    |   False    |
+| TSPC_GAP_25_7    |   False    |
+| TSPC_GAP_25_8    |   False    |
+| TSPC_GAP_26_1    |   False    |
+| TSPC_GAP_26_2    |   False    |
+| TSPC_GAP_26_3    |   False    |
+| TSPC_GAP_27_1    |   False*   |
+| TSPC_GAP_27_2    |   False*   |
+| TSPC_GAP_27_3    |   False    |
+| TSPC_GAP_27_4    |   False    |
+| TSPC_GAP_27_5    |   False    |
+| TSPC_GAP_27_6    |   False    |
+| TSPC_GAP_27_7    |   False    |
+| TSPC_GAP_27_8    |   False    |
+| TSPC_GAP_28_1    |   True*    |
+| TSPC_GAP_28_2    |   True*    |
+| TSPC_GAP_29_1    |   True*    |
+| TSPC_GAP_29_2    |   True*    |
+| TSPC_GAP_29_3    |   True*    |
+| TSPC_GAP_29_4    |   True*    |
+| TSPC_GAP_30_1    |   True*    |
+| TSPC_GAP_30_2    |   True*    |
+| TSPC_GAP_31_1    |   True*    |
+| TSPC_GAP_31_2    |   True*    |
+| TSPC_GAP_31_3    |   True*    |
+| TSPC_GAP_31_4    |   True*    |
+| TSPC_GAP_31_5    |   True*    |
+| TSPC_GAP_31_6    |   True*    |
+| TSPC_GAP_32_1    |   False    |
+| TSPC_GAP_32_2    |   True*    |
+| TSPC_GAP_32_3    |   True*    |
+| TSPC_GAP_33_1    |   True*    |
+| TSPC_GAP_33_2    |   True*    |
+| TSPC_GAP_33_3    |   True*    |
+| TSPC_GAP_33_4    |   True*    |
+| TSPC_GAP_33_5    |   True*    |
+| TSPC_GAP_33_6    |   True*    |
+| TSPC_GAP_34_1    |   False    |
+| TSPC_GAP_34_2    |   True*    |
+| TSPC_GAP_34_3    |   True*    |
+| TSPC_GAP_35_1    |   True*    |
+| TSPC_GAP_35_2    |   True*    |
+| TSPC_GAP_35_3    |   True*    |
+| TSPC_GAP_35_4    |   True*    |
+| TSPC_GAP_35_5    |   True*    |
+| TSPC_GAP_35_6    |   True*    |
+| TSPC_GAP_35_7    |   False    |
+| TSPC_GAP_35_8    |   False    |
+| TSPC_GAP_36_1    |   False    |
+| TSPC_GAP_36_2    |   False    |
+| TSPC_GAP_36_3    |   False    |
+| TSPC_GAP_36_4    |   False    |
+| TSPC_GAP_37_1    |   True*    |
+| TSPC_GAP_37_2    |   True*    |
+| TSPC_GAP_38_1    |   False    |
+| TSPC_GAP_38_2    |   True*    |
+| TSPC_GAP_38_3    |   False    |
+| TSPC_GAP_38_4    |   True*    |
+| TSPC_GAP_39_1    |   True*    |
+| TSPC_GAP_39_2    |   True*    |
+| TSPC_GAP_39_3    |   True*    |
+| TSPC_GAP_39_4    |   True     |
+| TSPC_GAP_39_5    |   False    |
+| TSPC_GAP_39_6    |   True*    |
+| TSPC_GAP_40_1    |   True*    |
+| TSPC_GAP_40_2    |   False    |
+| TSPC_GAP_40_3    |   True*    |
+| TSPC_GAP_40_4    |   True*    |
+| TSPC_GAP_40_5    |   True*    |
+| TSPC_GAP_41_1    |   True     |
+| TSPC_GAP_42_1    |   False    |
+| TSPC_GAP_42_2    |   False    |
+| TSPC_GAP_42_3    |   False    |
+| TSPC_GAP_42_4    |   False*   |
+| TSPC_GAP_42_5    |   False    |
+| TSPC_GAP_42_6    |   False    |
+| TSPC_GAP_43_1    |   False*   |
+| TSPC_SM_1_1      |   False    |
+| TSPC_SM_1_2      |   False    |
+| TSPC_SM_2_4      |   False    |
+| TSPC_ALL         |   False    |
++------------------+------------+
-- 
1.8.4.1


^ permalink raw reply related

* [PATCH 2/2] android: Add PTS PICS for HID
From: Jakub Tyszkowski @ 2013-11-14 13:26 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384435587-12427-1-git-send-email-jakub.tyszkowski@tieto.com>

PTS PICS for HID, targeting Android 4.4.

---
 android/pics-hid.txt | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 105 insertions(+)
 create mode 100644 android/pics-hid.txt

diff --git a/android/pics-hid.txt b/android/pics-hid.txt
new file mode 100644
index 0000000..36c49bf
--- /dev/null
+++ b/android/pics-hid.txt
@@ -0,0 +1,105 @@
+HID PICS for the PTS tool.
+
+* - different than PTS defaults
+
++------------------+------------+
+|  Parameter Name  |  Selected  |
++------------------+------------+
+| TSPC_HID_1_1     |   True*    |
+| TSPC_HID_1_2     |   False    |
+| TSPC_HID_1_3     |   False    |
+| TSPC_HID_2_1     |   True     |
+| TSPC_HID_2_2     |   True     |
+| TSPC_HID_2_3     |   True     |
+| TSPC_HID_2_4     |   True     |
+| TSPC_HID_2_5     |   True     |
+| TSPC_HID_2_6     |   True     |
+| TSPC_HID_2_7     |   True     |
+| TSPC_HID_2_8     |   True     |
+| TSPC_HID_2_9     |   True     |
+| TSPC_HID_2_10    |   False    |
+| TSPC_HID_2_11    |   False    |
+| TSPC_HID_2_12    |   False    |
+| TSPC_HID_2_13    |   False    |
+| TSPC_HID_2_14    |   False    |
+| TSPC_HID_2_15    |   False    |
+| TSPC_HID_3_1     |   False    |
+| TSPC_HID_3_2     |   True*    |
+| TSPC_HID_3_3     |   True*    |
+| TSPC_HID_3_4     |   False    |
+| TSPC_HID_4_1     |   False    |
+| TSPC_HID_4_2     |   False    |
+| TSPC_HID_4_3     |   True*    |
+| TSPC_HID_4_4     |   False    |
+| TSPC_HID_5_1     |   False    |
+| TSPC_HID_5_2     |   False    |
+| TSPC_HID_5_3     |   False    |
+| TSPC_HID_5_4     |   False    |
+| TSPC_HID_5_5     |   False*   |
+| TSPC_HID_5_6     |   False*   |
+| TSPC_HID_6_1     |   False    |
+| TSPC_HID_6_2     |   False    |
+| TSPC_HID_6_3     |   False    |
+| TSPC_HID_6_4     |   False    |
+| TSPC_HID_6_5     |   False    |
+| TSPC_HID_6_6     |   False    |
+| TSPC_HID_6_7     |   False    |
+| TSPC_HID_6_8     |   True     |
+| TSPC_HID_6_9     |   True     |
+| TSPC_HID_6_10    |   True     |
+| TSPC_HID_6_11    |   False    |
+| TSPC_HID_6_12    |   True     |
+| TSPC_HID_6_13    |   False    |
+| TSPC_HID_7_1     |   True     |
+| TSPC_HID_7_2     |   False*   |
+| TSPC_HID_8_1     |   False    |
+| TSPC_HID_8_2     |   False    |
+| TSPC_HID_8_3     |   False    |
+| TSPC_HID_8_4     |   False    |
+| TSPC_HID_9_1     |   False    |
+| TSPC_HID_9_2     |   False*   |
+| TSPC_HID_9_3     |   False    |
+| TSPC_HID_9_4     |   False*   |
+| TSPC_HID_9_5     |   False    |
+| TSPC_HID_9_6     |   False    |
+| TSPC_HID_9_7     |   False    |
+| TSPC_HID_9_8     |   False    |
+| TSPC_HID_9_9     |   False    |
+| TSPC_HID_9_10    |   False    |
+| TSPC_HID_9_11    |   False    |
+| TSPC_HID_9_12    |   False    |
+| TSPC_HID_9_13    |   False    |
+| TSPC_HID_9_14    |   False    |
+| TSPC_HID_9_15    |   False    |
+| TSPC_HID_9_16    |   False    |
+| TSPC_HID_10_1    |   False    |
+| TSPC_HID_10_2    |   False    |
+| TSPC_HID_10_3    |   False    |
+| TSPC_HID_10_4    |   False    |
+| TSPC_HID_11_1    |   False    |
+| TSPC_HID_11_2    |   False    |
+| TSPC_HID_11_3    |   False    |
+| TSPC_HID_11_4    |   False    |
+| TSPC_HID_12_1    |   False    |
+| TSPC_HID_12_2    |   False    |
+| TSPC_HID_12_3    |   False    |
+| TSPC_HID_12_4    |   False    |
+| TSPC_HID_12_5    |   False    |
+| TSPC_HID_12_6    |   False    |
+| TSPC_HID_13_1    |   False    |
+| TSPC_HID_13_2    |   False    |
+| TSPC_HID_13_3    |   False    |
+| TSPC_HID_13_4    |   False    |
+| TSPC_HID_13_5    |   False    |
+| TSPC_HID_13_6    |   False    |
+| TSPC_HID_13_7    |   False    |
+| TSPC_HID_13_8    |   False    |
+| TSPC_HID_13_9    |   False    |
+| TSPC_HID_13_10   |   False    |
+| TSPC_HID_13_11   |   False    |
+| TSPC_HID_13_12   |   False    |
+| TSPC_HID_13_13   |   False    |
+| TSPC_HID_14_1    |   False    |
+| TSPC_HID_14_2    |   False*   |
+| TSPC_ALL         |   False    |
++------------------+------------+
-- 
1.8.4.1


^ permalink raw reply related

* [PATCH BlueZ] android/a2dp: Add implementation of SDP record
From: Luiz Augusto von Dentz @ 2013-11-14 14:16 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This adds the following record:

Service Name: Audio Source
Service RecHandle: 0x10001
Service Class ID List:
  "Audio Source" (0x110a)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 25
  "AVDTP" (0x0019)
    uint16: 0x103
Profile Descriptor List:
  "Advanced Audio" (0x110d)
    Version: 0x0103
---
 android/a2dp.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/android/a2dp.c b/android/a2dp.c
index 32b6aa3..d8fe416 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -27,6 +27,7 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include <stdlib.h>
 #include <errno.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -34,18 +35,23 @@
 
 #include "btio/btio.h"
 #include "lib/bluetooth.h"
+#include "lib/sdp.h"
+#include "lib/sdp_lib.h"
 #include "log.h"
 #include "a2dp.h"
 #include "hal-msg.h"
 #include "ipc.h"
 #include "utils.h"
+#include "bluetooth.h"
 
 #define L2CAP_PSM_AVDTP 0x19
+#define SVC_HINT_CAPTURING 0x08
 
 static int notification_sk = -1;
 static GIOChannel *server = NULL;
 static GSList *devices = NULL;
 static bdaddr_t adapter_addr;
+static uint32_t record_id = 0;
 
 struct a2dp_device {
 	bdaddr_t	dst;
@@ -258,9 +264,71 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 	signaling_connect_cb(chan, err, dev);
 }
 
+static sdp_record_t *a2dp_record(void)
+{
+	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
+	uuid_t root_uuid, l2cap_uuid, avdtp_uuid, a2dp_uuid;
+	sdp_profile_desc_t profile[1];
+	sdp_list_t *aproto, *proto[2];
+	sdp_record_t *record;
+	sdp_data_t *psm, *version, *features;
+	uint16_t lp = AVDTP_UUID;
+	uint16_t a2dp_ver = 0x0103, avdtp_ver = 0x0103, feat = 0x000f;
+
+	record = sdp_record_alloc();
+	if (!record)
+		return NULL;
+
+	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
+	root = sdp_list_append(0, &root_uuid);
+	sdp_set_browse_groups(record, root);
+
+	sdp_uuid16_create(&a2dp_uuid, AUDIO_SOURCE_SVCLASS_ID);
+	svclass_id = sdp_list_append(0, &a2dp_uuid);
+	sdp_set_service_classes(record, svclass_id);
+
+	sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID);
+	profile[0].version = a2dp_ver;
+	pfseq = sdp_list_append(0, &profile[0]);
+	sdp_set_profile_descs(record, pfseq);
+
+	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
+	proto[0] = sdp_list_append(0, &l2cap_uuid);
+	psm = sdp_data_alloc(SDP_UINT16, &lp);
+	proto[0] = sdp_list_append(proto[0], psm);
+	apseq = sdp_list_append(0, proto[0]);
+
+	sdp_uuid16_create(&avdtp_uuid, AVDTP_UUID);
+	proto[1] = sdp_list_append(0, &avdtp_uuid);
+	version = sdp_data_alloc(SDP_UINT16, &avdtp_ver);
+	proto[1] = sdp_list_append(proto[1], version);
+	apseq = sdp_list_append(apseq, proto[1]);
+
+	aproto = sdp_list_append(0, apseq);
+	sdp_set_access_protos(record, aproto);
+
+	features = sdp_data_alloc(SDP_UINT16, &feat);
+	sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
+
+	sdp_set_info_attr(record, "Audio Source", 0, 0);
+
+	free(psm);
+	free(version);
+	sdp_list_free(proto[0], 0);
+	sdp_list_free(proto[1], 0);
+	sdp_list_free(apseq, 0);
+	sdp_list_free(pfseq, 0);
+	sdp_list_free(aproto, 0);
+	sdp_list_free(root, 0);
+	sdp_list_free(svclass_id, 0);
+
+	return record;
+}
+
 bool bt_a2dp_register(int sk, const bdaddr_t *addr)
 {
 	GError *err = NULL;
+	sdp_record_t *rec;
 
 	DBG("");
 
@@ -277,6 +345,16 @@ bool bt_a2dp_register(int sk, const bdaddr_t *addr)
 		return false;
 	}
 
+	rec = a2dp_record();
+	if (bt_adapter_add_record(rec, SVC_HINT_CAPTURING) < 0) {
+		error("Failed to register on A2DP record");
+		g_io_channel_shutdown(server, TRUE, NULL);
+		g_io_channel_unref(server);
+		server = NULL;
+		return false;
+	}
+	record_id = rec->handle;
+
 	notification_sk = sk;
 
 	return true;
@@ -288,6 +366,9 @@ void bt_a2dp_unregister(void)
 
 	notification_sk = -1;
 
+	bt_adapter_remove_record(record_id);
+	record_id = 0;
+
 	if (server) {
 		g_io_channel_shutdown(server, TRUE, NULL);
 		g_io_channel_unref(server);
-- 
1.8.3.1


^ permalink raw reply related

* Re: Adapter name reset on suspend/resume
From: Marcel Holtmann @ 2013-11-14 14:33 UTC (permalink / raw)
  To: Bastien Nocera; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1384421473.2229.1.camel@nuvo>

Hi Bastien,

>>> After suspending and resuming my laptop, hci0's name is reset to what
>>> looks like the factory name:
>>> $ hciconfig -a | grep Name
>>> 	Name: 'BCM20702A'
>>> 
>>> This is the device in question:
>>> Bus 001 Device 004: ID 0a5c:21e6 Broadcom Corp. BCM20702 Bluetooth 4.0 [ThinkPad]
>>> 
>>> And my laptop is a Lenovo X1 Carbon.
>>> 
>>> Neither udevadm nor btmon show the device going away on suspend and
>>> coming back on resume.
>> 
>> can you start btmon, call hciconfig hci0 name, then suspend, then
>> resume, call hciconfig hci0 name again.
> 
> Bluetooth monitor ver 5.10
> = New Index: F4:B7:E2:E8:99:E2 (BR/EDR,USB,hci0)                   [hci0] 0.176335
> < HCI Command: Read Local Name (0x03|0x0014) plen 0                [hci0] 9.797930
>> HCI Event: Command Complete (0x0e) plen 252                      [hci0] 9.813834
>      Read Local Name (0x03|0x0014) ncmd 1
>        Status: Success (0x00)
>        Name: nuvo
> < HCI Command: Read Local Name (0x03|0x0014) plen 0               [hci0] 33.109166
>> HCI Event: Command Complete (0x0e) plen 252                     [hci0] 33.125157
>      Read Local Name (0x03|0x0014) ncmd 1
>        Status: Success (0x00)
>        Name: BCM20702A
> 
>> I am wondering if for some reason the suspend/resume actually does a
>> HCI Reset without telling us. The name normally only gets reset to
>> BCM20702A when doing a full reset.
> 
> Looks like that's what it's doing.
> 
>> Another possibility is that we actually forgot to set it in the first
>> place. I am pretty sure I have intensively tested and that should not
>> happen, but you might just found a corner case.
> 
> It's set on a normal boot, it seems to be reset only when suspending.

I have no idea on how to fix this at the moment. The problem is actually that this kind of behavior with a silent HCI reset will break remote wakeup.

Regards

Marcel


^ permalink raw reply

* [PATCH v2 BlueZ] android/a2dp: Add implementation of SDP record
From: Luiz Augusto von Dentz @ 2013-11-14 15:01 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This adds the following record:

Service Name: Audio Source
Service RecHandle: 0x10001
Service Class ID List:
  "Audio Source" (0x110a)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 25
  "AVDTP" (0x0019)
    uint16: 0x103
Profile Descriptor List:
  "Advanced Audio" (0x110d)
    Version: 0x0103
---
v2: Fix leaking record if bt_adapter_add_record fails

 android/a2dp.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/android/a2dp.c b/android/a2dp.c
index 32b6aa3..936c28e 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -27,6 +27,7 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include <stdlib.h>
 #include <errno.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -34,18 +35,23 @@
 
 #include "btio/btio.h"
 #include "lib/bluetooth.h"
+#include "lib/sdp.h"
+#include "lib/sdp_lib.h"
 #include "log.h"
 #include "a2dp.h"
 #include "hal-msg.h"
 #include "ipc.h"
 #include "utils.h"
+#include "bluetooth.h"
 
 #define L2CAP_PSM_AVDTP 0x19
+#define SVC_HINT_CAPTURING 0x08
 
 static int notification_sk = -1;
 static GIOChannel *server = NULL;
 static GSList *devices = NULL;
 static bdaddr_t adapter_addr;
+static uint32_t record_id = 0;
 
 struct a2dp_device {
 	bdaddr_t	dst;
@@ -258,9 +264,71 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 	signaling_connect_cb(chan, err, dev);
 }
 
+static sdp_record_t *a2dp_record(void)
+{
+	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
+	uuid_t root_uuid, l2cap_uuid, avdtp_uuid, a2dp_uuid;
+	sdp_profile_desc_t profile[1];
+	sdp_list_t *aproto, *proto[2];
+	sdp_record_t *record;
+	sdp_data_t *psm, *version, *features;
+	uint16_t lp = AVDTP_UUID;
+	uint16_t a2dp_ver = 0x0103, avdtp_ver = 0x0103, feat = 0x000f;
+
+	record = sdp_record_alloc();
+	if (!record)
+		return NULL;
+
+	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
+	root = sdp_list_append(0, &root_uuid);
+	sdp_set_browse_groups(record, root);
+
+	sdp_uuid16_create(&a2dp_uuid, AUDIO_SOURCE_SVCLASS_ID);
+	svclass_id = sdp_list_append(0, &a2dp_uuid);
+	sdp_set_service_classes(record, svclass_id);
+
+	sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID);
+	profile[0].version = a2dp_ver;
+	pfseq = sdp_list_append(0, &profile[0]);
+	sdp_set_profile_descs(record, pfseq);
+
+	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
+	proto[0] = sdp_list_append(0, &l2cap_uuid);
+	psm = sdp_data_alloc(SDP_UINT16, &lp);
+	proto[0] = sdp_list_append(proto[0], psm);
+	apseq = sdp_list_append(0, proto[0]);
+
+	sdp_uuid16_create(&avdtp_uuid, AVDTP_UUID);
+	proto[1] = sdp_list_append(0, &avdtp_uuid);
+	version = sdp_data_alloc(SDP_UINT16, &avdtp_ver);
+	proto[1] = sdp_list_append(proto[1], version);
+	apseq = sdp_list_append(apseq, proto[1]);
+
+	aproto = sdp_list_append(0, apseq);
+	sdp_set_access_protos(record, aproto);
+
+	features = sdp_data_alloc(SDP_UINT16, &feat);
+	sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
+
+	sdp_set_info_attr(record, "Audio Source", 0, 0);
+
+	free(psm);
+	free(version);
+	sdp_list_free(proto[0], 0);
+	sdp_list_free(proto[1], 0);
+	sdp_list_free(apseq, 0);
+	sdp_list_free(pfseq, 0);
+	sdp_list_free(aproto, 0);
+	sdp_list_free(root, 0);
+	sdp_list_free(svclass_id, 0);
+
+	return record;
+}
+
 bool bt_a2dp_register(int sk, const bdaddr_t *addr)
 {
 	GError *err = NULL;
+	sdp_record_t *rec;
 
 	DBG("");
 
@@ -277,6 +345,17 @@ bool bt_a2dp_register(int sk, const bdaddr_t *addr)
 		return false;
 	}
 
+	rec = a2dp_record();
+	if (bt_adapter_add_record(rec, SVC_HINT_CAPTURING) < 0) {
+		error("Failed to register on A2DP record");
+		sdp_record_free(rec);
+		g_io_channel_shutdown(server, TRUE, NULL);
+		g_io_channel_unref(server);
+		server = NULL;
+		return false;
+	}
+	record_id = rec->handle;
+
 	notification_sk = sk;
 
 	return true;
@@ -288,6 +367,9 @@ void bt_a2dp_unregister(void)
 
 	notification_sk = -1;
 
+	bt_adapter_remove_record(record_id);
+	record_id = 0;
+
 	if (server) {
 		g_io_channel_shutdown(server, TRUE, NULL);
 		g_io_channel_unref(server);
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv1 00/16] Socket HAL
From: Andrei Emeltchenko @ 2013-11-14 15:11 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

This is initial code implementing socket HAL. Receiving files
through OPP currently works.

Changes:
	* v1: Rebased and use static src address, hal_fd removed from structure and closed after sent to framework,
	added connect calls and SDP parsing, added cleanup_rfcomm function, minor fixes.
	* RFC Initial

For tracking rfcomm sockets I use structure rfslot which has following
fields:
 - real_sock - real RFCOMM socket
 - fd - fd to communicate with Android framework
 - hal_fd - fd passed to Android framework with CMSG

Andrei Emeltchenko (16):
  android/hal-sock: Add debug flag printing
  android/hal-sock: Use static local adapter address
  android/hal-sock: Add connect signal to socket
  android/hal-sock: Define structures for socket HAL
  android/hal-sock: Initial listen handle
  android/hal-sock: Implement socket accepted event
  android/hal-sock: Implement Android RFCOMM stack events
  android/hal-sock: Implement RFCOMM events
  android/hal-sock: Implement accept signal over Android fd
  android/hal-sock: Write channel to Android fd
  android/hal-sock: Implement socket connect HAL method
  android/hal-sock: Parse SDP response and connect
  android/hal-sock: Implement HAL connect call
  android/hal-sock: Send RFCOMM channel to framework
  android/hal-sock: Send connect signal on connect
  android/hal-sock: Close file descriptor after sending

 android/hal-msg.h  |    2 +
 android/hal-sock.c |    8 +-
 android/socket.c   |  496 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 android/socket.h   |    7 +
 4 files changed, 505 insertions(+), 8 deletions(-)

-- 
1.7.10.4


^ permalink raw reply

* [PATCHv1 01/16] android/hal-sock: Add debug flag printing
From: Andrei Emeltchenko @ 2013-11-14 15:11 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384441915-23966-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

---
 android/hal-sock.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/android/hal-sock.c b/android/hal-sock.c
index b7bc88e..eafa451 100644
--- a/android/hal-sock.c
+++ b/android/hal-sock.c
@@ -55,8 +55,8 @@ static bt_status_t sock_listen(btsock_type_t type, const char *service_name,
 		return BT_STATUS_PARM_INVALID;
 	}
 
-	DBG("uuid %s chan %d sock %p type %d service_name %s",
-			btuuid2str(uuid), chan, sock, type, service_name);
+	DBG("uuid %s chan %d sock %p type %d service_name %s flags 0x%02x",
+		btuuid2str(uuid), chan, sock, type, service_name, flags);
 
 	switch (type) {
 	case BTSOCK_RFCOMM:
@@ -82,8 +82,8 @@ static bt_status_t sock_connect(const bt_bdaddr_t *bdaddr, btsock_type_t type,
 		return BT_STATUS_PARM_INVALID;
 	}
 
-	DBG("uuid %s chan %d sock %p type %d", btuuid2str(uuid), chan, sock,
-									type);
+	DBG("uuid %s chan %d sock %p type %d flags 0x%02x",
+		btuuid2str(uuid), chan, sock, type, flags);
 
 	if (type != BTSOCK_RFCOMM) {
 		error("Socket type %u not supported", type);
-- 
1.7.10.4


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox