linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* RE: [RFC] Release Plan for ERTM, Streaming Mode, FCS and SAR on L2CAP
From: Mike Tsai @ 2010-03-23 23:36 UTC (permalink / raw)
  To: Gustavo F. Padovan, linux-bluetooth@vger.kernel.org; +Cc: marcel@holtmann.org
In-Reply-To: <20100323203903.GA13897@vigoh>

Hi Gus,

	My comments will be that it is probably better to implement eRTM mode first because many existing implementations do not support stream mode but definitely support eRTM mode. 

	You shall be able to verify the testing with Bluetooth SIG PTS,

Thanks,

Mike

-----Original Message-----
From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth-owner@vger.kernel.org] On Behalf Of Gustavo F. Padovan
Sent: Tuesday, March 23, 2010 1:39 PM
To: linux-bluetooth@vger.kernel.org
Cc: marcel@holtmann.org
Subject: [RFC] Release Plan for ERTM, Streaming Mode, FCS and SAR on L2CAP

Hi People,

I was thinking about a release plan for Enhanced Retransmission Mode,
Streaming Mode, Frame Check Sequence(FCS) and Segmentation and
Reassembly(SAR).

2.6.35: Upstream Streaming Mode, FCS, SAR and add a sub-menu option
to L2CAP at Kconfig for ERTM with an EXPERIMENTAL flag. So we will have
a chance to test ERTM more intensively.

2.6.36: Upstream ERTM. After that ERTM will be the default mode with
SOCK_STREAM and also enabled by default under L2CAP. If you think it's
not worth release Streaming Mode, FCS and SAR without ERTM we can
upstream them together on 2.6.36.

Comments, ideas?

-- 
Gustavo F. Padovan
http://padovan.org
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [RFC] Release Plan for ERTM, Streaming Mode, FCS and SAR on L2CAP
From: Gustavo F. Padovan @ 2010-03-24  0:57 UTC (permalink / raw)
  To: Mike Tsai; +Cc: linux-bluetooth@vger.kernel.org, marcel@holtmann.org
In-Reply-To: <35B17FE5076C7040809188FBE7913F983A1DDCF3F4@SC1EXMB-MBCL.global.atheros.com>

Hi Mike,

Again, no top posting, please. ;)

* Mike Tsai <Mike.Tsai@Atheros.com> [2010-03-23 16:36:46 -0700]:

> Hi Gus,
> 
> 	My comments will be that it is probably better to implement eRTM mode first because many existing implementations do not support stream mode but definitely support eRTM mode. 

They are under development already. Streaming Mode, FCS and SAR is
implemented and need some stabilization, heavy tests and bug fixes only.
ERTM is not completely done and need some work on it already. That's why
I wanna delay ERTM's upstream.

> 
> 	You shall be able to verify the testing with Bluetooth SIG PTS,

Sure. The code will be tested with PTS before go upstream.

> 
> Thanks,
> 
> Mike
> 
> -----Original Message-----
> From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth-owner@vger.kernel.org] On Behalf Of Gustavo F. Padovan
> Sent: Tuesday, March 23, 2010 1:39 PM
> To: linux-bluetooth@vger.kernel.org
> Cc: marcel@holtmann.org
> Subject: [RFC] Release Plan for ERTM, Streaming Mode, FCS and SAR on L2CAP
> 
> Hi People,
> 
> I was thinking about a release plan for Enhanced Retransmission Mode,
> Streaming Mode, Frame Check Sequence(FCS) and Segmentation and
> Reassembly(SAR).
> 
> 2.6.35: Upstream Streaming Mode, FCS, SAR and add a sub-menu option
> to L2CAP at Kconfig for ERTM with an EXPERIMENTAL flag. So we will have
> a chance to test ERTM more intensively.
> 
> 2.6.36: Upstream ERTM. After that ERTM will be the default mode with
> SOCK_STREAM and also enabled by default under L2CAP. If you think it's
> not worth release Streaming Mode, FCS and SAR without ERTM we can
> upstream them together on 2.6.36.
> 
> Comments, ideas?
> 
> -- 
> Gustavo F. Padovan
> http://padovan.org
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Gustavo F. Padovan
http://padovan.org

^ permalink raw reply

* Re: [PATCH] Added support for Atheros AR300x Bluetooth Chip
From: suraj @ 2010-03-24  5:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, Luis.Rodriguez, Jothikumar.Mothilal
In-Reply-To: <1268629296.21425.23.camel@atheros013-desktop>

On Mon, 2010-03-15 at 10:31 +0530, suraj wrote:
> This protocol implements support for power management feature provided by AR300x chip.
> This lets the controller chip go to sleep mode if there is no Bluetooth activity for some time.
> It then wakes up the chip in case of a Bluetooth activity.
> 
> 
>  Signed-off-by: Suraj <suraj@atheros.com>
> 
> ---
>  drivers/bluetooth/Kconfig     |   11 ++
>  drivers/bluetooth/Makefile    |    1 +
>  drivers/bluetooth/hci_ath.c   |  353 +++++++++++++++++++++++++++++++++++++++++
>  drivers/bluetooth/hci_ldisc.c |    6 +
>  drivers/bluetooth/hci_uart.h  |    8 +-
>  5 files changed, 378 insertions(+), 1 deletions(-)
>  create mode 100755 drivers/bluetooth/hci_ath.c
> 
> diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
> index 058fbcc..81abeff 100644
> --- a/drivers/bluetooth/Kconfig
> +++ b/drivers/bluetooth/Kconfig
> @@ -58,6 +58,17 @@ config BT_HCIUART_BCSP
>  
>  	  Say Y here to compile support for HCI BCSP protocol.
>  
> +config BT_HCIUART_ATH
> +	bool "Atheros AR300x Board support"
> +	depends on BT_HCIUART
> +	help
> +	  HCIATH (HCI Atheros) is a serial protocol for communication
> +	  between Bluetooth device and host with support for Atheros AR300x
> +	  power management feature. This protocol is required for
> +	  serial Bluetooth devices that are based on Atheros AR300x chips.
> +
> +	  Say Y here to compile support for HCIATH protocol.
> +
>  config BT_HCIUART_LL
>  	bool "HCILL protocol support"
>  	depends on BT_HCIUART
> diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
> index 7e5aed5..1481faa 100644
> --- a/drivers/bluetooth/Makefile
> +++ b/drivers/bluetooth/Makefile
> @@ -26,4 +26,5 @@ hci_uart-y				:= hci_ldisc.o
>  hci_uart-$(CONFIG_BT_HCIUART_H4)	+= hci_h4.o
>  hci_uart-$(CONFIG_BT_HCIUART_BCSP)	+= hci_bcsp.o
>  hci_uart-$(CONFIG_BT_HCIUART_LL)	+= hci_ll.o
> +hci_uart-$(CONFIG_BT_HCIUART_ATH)	+= hci_ath.o
>  hci_uart-objs				:= $(hci_uart-y)
> diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
> new file mode 100755
> index 0000000..13e4404
> --- /dev/null
> +++ b/drivers/bluetooth/hci_ath.c
> @@ -0,0 +1,353 @@
> +/*
> + * Copyright (c) 2009-2010 Atheros Communications Inc.
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation; either version 2 of the License, or
> + *  (at your option) any later version.
> + *
> + *  This program is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with this program; if not, write to the Free Software
> + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +
> +#include <linux/init.h>
> +#include <linux/slab.h>
> +#include <linux/tty.h>
> +#include <linux/errno.h>
> +#include <linux/ioctl.h>
> +#include <linux/skbuff.h>
> +
> +#include <net/bluetooth/bluetooth.h>
> +#include <net/bluetooth/hci_core.h>
> +
> +#include "hci_uart.h"
> +
> +
> +/* HCIATH receiver States */
> +#define HCIATH_W4_PACKET_TYPE			0
> +#define HCIATH_W4_EVENT_HDR			1
> +#define HCIATH_W4_ACL_HDR			2
> +#define HCIATH_W4_SCO_HDR			3
> +#define HCIATH_W4_DATA				4
> +
> +struct ath_struct {
> +	struct hci_uart *hu;
> +	unsigned int rx_state;
> +	unsigned int rx_count;
> +	unsigned int cur_sleep;
> +
> +	spinlock_t hciath_lock;
> +	struct sk_buff *rx_skb;
> +	struct sk_buff_head txq;
> +	wait_queue_head_t wqevt;
> +	struct work_struct ctxtsw;
> +};
> +
> +int ath_wakeup_ar3001(struct tty_struct *tty)
> +{
> +	struct termios settings;
> +	int status = 0x00;
> +	mm_segment_t oldfs;
> +	status = tty->driver->ops->tiocmget(tty, NULL);
> +
> +	if ((status & TIOCM_CTS))
> +		return status;
> +
> +	oldfs = get_fs();
> +	set_fs(KERNEL_DS);
> +	n_tty_ioctl_helper(tty, NULL, TCGETS, (unsigned long)&settings);
> +
> +	settings.c_cflag &= ~CRTSCTS;
> +	n_tty_ioctl_helper(tty, NULL, TCSETS, (unsigned long)&settings);
> +	set_fs(oldfs);
> +	status = tty->driver->ops->tiocmget(tty, NULL);
> +
> +	/* Wake up board */
> +	tty->driver->ops->tiocmset(tty, NULL, 0x00, TIOCM_RTS);
> +	mdelay(20);
> +
> +	status = tty->driver->ops->tiocmget(tty, NULL);
> +
> +	tty->driver->ops->tiocmset(tty, NULL, TIOCM_RTS, 0x00);
> +	mdelay(20);
> +
> +	status = tty->driver->ops->tiocmget(tty, NULL);
> +	oldfs = get_fs();
> +	set_fs(KERNEL_DS);
> +	n_tty_ioctl_helper(tty, NULL, TCGETS, (unsigned long)&settings);
> +
> +	settings.c_cflag |= CRTSCTS;
> +	n_tty_ioctl_helper(tty, NULL, TCSETS, (unsigned long)&settings);
> +	set_fs(oldfs);
> +	return status;
> +}
> +
> +static void ath_context_switch(struct work_struct *work)
> +{
> +	int status;
> +	struct ath_struct *ath;
> +	struct hci_uart *hu;
> +	struct tty_struct *tty;
> +
> +	ath = container_of(work, struct ath_struct, ctxtsw);
> +
> +	hu = ath->hu;
> +	tty = hu->tty;
> +
> +	/* verify and wake up controller */
> +	if (ath->cur_sleep) {
> +
> +		status = ath_wakeup_ar3001(tty);
> +		if (!(status & TIOCM_CTS))
> +			return;
> +	}
> +
> +	/* Ready to send Data */
> +	clear_bit(HCI_UART_SENDING, &hu->tx_state);
> +	hci_uart_tx_wakeup(hu);
> +}
> +
> +int ath_check_sleep_cmd(struct ath_struct *ath, unsigned char *packet)
> +{
> +	if (packet[0] == 0x04 && packet[1] == 0xFC)
> +		ath->cur_sleep = packet[3];
> +
> +	return 0;
> +}
> +
> +
> +/* Initialize protocol */
> +static int ath_open(struct hci_uart *hu)
> +{
> +	struct ath_struct *ath;
> +	BT_DBG("hu %p", hu);
> +
> +	ath = kzalloc(sizeof(*ath), GFP_ATOMIC);
> +	if (!ath)
> +		return -ENOMEM;
> +
> +	skb_queue_head_init(&ath->txq);
> +	spin_lock_init(&ath->hciath_lock);
> +
> +	ath->cur_sleep = 0;
> +	hu->priv = ath;
> +	ath->hu = hu;
> +
> +	init_waitqueue_head(&ath->wqevt);
> +	INIT_WORK(&ath->ctxtsw, ath_context_switch);
> +	return 0;
> +}
> +
> +/* Flush protocol data */
> +static int ath_flush(struct hci_uart *hu)
> +{
> +	struct ath_struct *ath = hu->priv;
> +	BT_DBG("hu %p", hu);
> +	skb_queue_purge(&ath->txq);
> +
> +	return 0;
> +}
> +
> +/* Close protocol */
> +static int ath_close(struct hci_uart *hu)
> +{
> +	struct ath_struct *ath = hu->priv;
> +	BT_DBG("hu %p", hu);
> +
> +	skb_queue_purge(&ath->txq);
> +
> +	if (ath->rx_skb)
> +		kfree_skb(ath->rx_skb);
> +
> +	wake_up_interruptible(&ath->wqevt);
> +	hu->priv = NULL;
> +	kfree(ath);
> +	return 0;
> +}
> +
> +/* Enqueue frame for transmittion */
> +static int ath_enqueue(struct hci_uart *hu, struct sk_buff *skb)
> +{
> +	struct ath_struct *ath = hu->priv;
> +	if (bt_cb(skb)->pkt_type == HCI_SCODATA_PKT) {
> +
> +		/* Discard SCO packet.AR3001 does not support SCO over HCI */
> +		BT_DBG("SCO Packet over HCI received Dropping\n");
> +		kfree(skb);
> +		return 0;
> +	}
> +	BT_DBG("hu %p skb %p", hu, skb);
> +
> +	/* Prepend skb with frame type */
> +	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
> +
> +	skb_queue_tail(&ath->txq, skb);
> +	set_bit(HCI_UART_SENDING, &hu->tx_state);
> +
> +	schedule_work(&ath->ctxtsw);
> +	return 0;
> +}
> +
> +static struct sk_buff *ath_dequeue(struct hci_uart *hu)
> +{
> +	struct ath_struct *ath = hu->priv;
> +	struct sk_buff *skbuf;
> +
> +	skbuf = skb_dequeue(&ath->txq);
> +	if (skbuf != NULL)
> +		ath_check_sleep_cmd(ath, &skbuf->data[1]);
> +
> +	return skbuf;
> +}
> +
> +static inline int ath_check_data_len(struct ath_struct *ath, int len)
> +{
> +	register int room = skb_tailroom(ath->rx_skb);
> +	BT_DBG("len %d room %d", len, room);
> +
> +	if (len > room) {
> +		BT_ERR("Data length is too large");
> +		kfree_skb(ath->rx_skb);
> +		ath->rx_state = HCIATH_W4_PACKET_TYPE;
> +		ath->rx_skb = NULL;
> +		ath->rx_count = 0;
> +	} else {
> +		ath->rx_state = HCIATH_W4_DATA;
> +		ath->rx_count = len;
> +		return len;
> +	}
> +
> +	return 0;
> +}
> +
> +/* Recv data */
> +static int ath_recv(struct hci_uart *hu, void *data, int count)
> +{
> +	struct ath_struct *ath = hu->priv;
> +	register char *ptr;
> +	struct hci_event_hdr *eh;
> +	struct hci_acl_hdr *ah;
> +	struct hci_sco_hdr *sh;
> +	struct sk_buff *skbuf;
> +	register int len, type, dlen;
> +
> +	skbuf = NULL;
> +	BT_DBG("hu %p count %d rx_state %d rx_count %d", hu, count,
> +	       ath->rx_state, ath->rx_count);
> +	ptr = data;
> +	while (count) {
> +		if (ath->rx_count) {
> +
> +			len = min_t(unsigned int, ath->rx_count, count);
> +			memcpy(skb_put(ath->rx_skb, len), ptr, len);
> +			ath->rx_count -= len;
> +			count -= len;
> +			ptr += len;
> +
> +			if (ath->rx_count)
> +				continue;
> +			switch (ath->rx_state) {
> +			case HCIATH_W4_DATA:
> +				hci_recv_frame(ath->rx_skb);
> +				ath->rx_state = HCIATH_W4_PACKET_TYPE;
> +				ath->rx_skb = NULL;
> +				ath->rx_count = 0;
> +				continue;
> +			case HCIATH_W4_EVENT_HDR:
> +				eh = (struct hci_event_hdr *)ath->rx_skb->data;
> +				BT_DBG("Event header: evt 0x%2.2x plen %d",
> +				       eh->evt, eh->plen);
> +				ath_check_data_len(ath, eh->plen);
> +				continue;
> +			case HCIATH_W4_ACL_HDR:
> +				ah = (struct hci_acl_hdr *)ath->rx_skb->data;
> +				dlen = __le16_to_cpu(ah->dlen);
> +				BT_DBG("ACL header: dlen %d", dlen);
> +				ath_check_data_len(ath, dlen);
> +				continue;
> +			case HCIATH_W4_SCO_HDR:
> +				sh = (struct hci_sco_hdr *)ath->rx_skb->data;
> +				BT_DBG("SCO header: dlen %d", sh->dlen);
> +				ath_check_data_len(ath, sh->dlen);
> +				continue;
> +			}
> +		}
> +
> +		/* HCIATH_W4_PACKET_TYPE */
> +		switch (*ptr) {
> +		case HCI_EVENT_PKT:
> +			BT_DBG("Event packet");
> +			ath->rx_state = HCIATH_W4_EVENT_HDR;
> +			ath->rx_count = HCI_EVENT_HDR_SIZE;
> +			type = HCI_EVENT_PKT;
> +			break;
> +		case HCI_ACLDATA_PKT:
> +			BT_DBG("ACL packet");
> +			ath->rx_state = HCIATH_W4_ACL_HDR;
> +			ath->rx_count = HCI_ACL_HDR_SIZE;
> +			type = HCI_ACLDATA_PKT;
> +			break;
> +		case HCI_SCODATA_PKT:
> +			BT_DBG("SCO packet");
> +			ath->rx_state = HCIATH_W4_SCO_HDR;
> +			ath->rx_count = HCI_SCO_HDR_SIZE;
> +			type = HCI_SCODATA_PKT;
> +			break;
> +		default:
> +			BT_ERR("Unknown HCI packet type %2.2x", (__u8) *ptr);
> +			hu->hdev->stat.err_rx++;
> +			ptr++;
> +			count--;
> +			continue;
> +		};
> +		ptr++;
> +		count--;
> +
> +		/* Allocate packet */
> +		ath->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
> +		if (!ath->rx_skb) {
> +			BT_ERR("Can't allocate mem for new packet");
> +			ath->rx_state = HCIATH_W4_PACKET_TYPE;
> +			ath->rx_count = 0;
> +			return -ENOMEM;
> +		}
> +		ath->rx_skb->dev = (void *)hu->hdev;
> +		bt_cb(ath->rx_skb)->pkt_type = type;
> +	} return count;
> +}
> +
> +static struct hci_uart_proto athp = {
> +	.id = HCI_UART_ATH,
> +	.open = ath_open,
> +	.close = ath_close,
> +	.recv = ath_recv,
> +	.enqueue = ath_enqueue,
> +	.dequeue = ath_dequeue,
> +	.flush = ath_flush,
> +};
> +
> +int ath_init(void)
> +{
> +	int err = hci_uart_register_proto(&athp);
> +	if (!err)
> +		BT_INFO("HCIATH protocol initialized");
> +
> +	else
> +		BT_ERR("HCIATH protocol registration failed");
> +	return err;
> +}
> +
> +int ath_deinit(void)
> +{
> +	return hci_uart_unregister_proto(&athp);
> +}
> diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
> index 76a1abb..7dd76d1 100644
> --- a/drivers/bluetooth/hci_ldisc.c
> +++ b/drivers/bluetooth/hci_ldisc.c
> @@ -542,6 +542,9 @@ static int __init hci_uart_init(void)
>  #ifdef CONFIG_BT_HCIUART_LL
>  	ll_init();
>  #endif
> +#ifdef CONFIG_BT_HCIUART_ATH
> +	ath_init();
> +#endif
>  
>  	return 0;
>  }
> @@ -559,6 +562,9 @@ static void __exit hci_uart_exit(void)
>  #ifdef CONFIG_BT_HCIUART_LL
>  	ll_deinit();
>  #endif
> +#ifdef CONFIG_BT_HCIUART_ATH
> +	ath_deinit();
> +#endif
>  
>  	/* Release tty registration of line discipline */
>  	if ((err = tty_unregister_ldisc(N_HCI)))
> diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
> index 50113db..385537f 100644
> --- a/drivers/bluetooth/hci_uart.h
> +++ b/drivers/bluetooth/hci_uart.h
> @@ -33,13 +33,14 @@
>  #define HCIUARTGETDEVICE	_IOR('U', 202, int)
>  
>  /* UART protocols */
> -#define HCI_UART_MAX_PROTO	5
> +#define HCI_UART_MAX_PROTO	6
>  
>  #define HCI_UART_H4	0
>  #define HCI_UART_BCSP	1
>  #define HCI_UART_3WIRE	2
>  #define HCI_UART_H4DS	3
>  #define HCI_UART_LL	4
> +#define HCI_UART_ATH	5
>  
>  struct hci_uart;
>  
> @@ -91,3 +92,8 @@ int bcsp_deinit(void);
>  int ll_init(void);
>  int ll_deinit(void);
>  #endif
> +
> +#ifdef CONFIG_BT_HCIUART_ATH
> +int ath_init(void);
> +int ath_deinit(void);
> +#endif

Hi Marcel,

Can you please give your comments regarding the patch that I have sent
you?

Regards
Suraj

^ permalink raw reply

* [PATCH] Report local services(UUIDs) through DBus
From: Francisco Alecrim @ 2010-03-24 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Francisco Alecrim

Include UUIDs field to method GetProperties(org.bluez.Adapter).
Applications can get local services(UUIDs) available through DBus.
---
 doc/adapter-api.txt |    5 +++++
 src/adapter.c       |   20 +++++++++++++++++++-
 src/sdpd-database.c |   21 +++++++++++++++++++++
 src/sdpd.h          |    1 +
 test/list-devices   |    3 +++
 5 files changed, 49 insertions(+), 1 deletions(-)

diff --git a/doc/adapter-api.txt b/doc/adapter-api.txt
index 48cab40..6098c76 100644
--- a/doc/adapter-api.txt
+++ b/doc/adapter-api.txt
@@ -270,3 +270,8 @@ Properties	string Address [readonly]
 		array{object} Devices [readonly]
 
 			List of device object paths.
+
+		array{string} UUIDs [readonly]
+
+			List of 128-bit UUIDs that represents the available
+			local services.
diff --git a/src/adapter.c b/src/adapter.c
index 5fd0736..2027484 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -37,6 +37,7 @@
 #include <bluetooth/hci.h>
 #include <bluetooth/hci_lib.h>
 #include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
@@ -1196,7 +1197,8 @@ static DBusMessage *get_properties(DBusConnection *conn,
 	DBusMessageIter dict;
 	char str[MAX_NAME_LENGTH + 1], srcaddr[18];
 	gboolean value;
-	char **devices;
+	char **devices, **uuids;
+	sdp_list_t *list, *lfree;
 	int i;
 	GSList *l;
 
@@ -1270,6 +1272,22 @@ static DBusMessage *get_properties(DBusConnection *conn,
 								&devices, i);
 	g_free(devices);
 
+	/* UUIDs */
+	list = sdp_get_record_list_by_device(&adapter->bdaddr);
+	lfree = list; /* keep head to prevent leak */
+	uuids = g_new0(char *, sdp_list_len(list) + 1);
+
+	for (i = 0; list; list = list->next, i++) {
+		sdp_record_t *rec = list->data;
+		uuids[i] = bt_uuid2string(&rec->svclass);
+	}
+	dict_append_array(&dict, "UUIDs", DBUS_TYPE_STRING, &uuids, i);
+
+	sdp_list_free(lfree, NULL);
+	for (i = 0; uuids[i]; i++)
+		g_free(uuids[i]);
+	g_free(uuids);
+
 	dbus_message_iter_close_container(&iter, &dict);
 
 	return reply;
diff --git a/src/sdpd-database.c b/src/sdpd-database.c
index 07a0bc3..b07aa97 100644
--- a/src/sdpd-database.c
+++ b/src/sdpd-database.c
@@ -273,6 +273,27 @@ sdp_list_t *sdp_get_access_list(void)
 	return access_db;
 }
 
+sdp_list_t *sdp_get_record_list_by_device(const bdaddr_t *device)
+{
+	sdp_list_t *list, *acc;
+
+	acc = access_db;
+	list = NULL;
+	for (; acc; acc = acc->next) {
+		sdp_access_t *a = acc->data;
+		sdp_record_t *rec = sdp_record_find(a->handle);
+		if (!rec)
+			continue;
+
+		if (bacmp(&a->device, device) == 0 ||
+				bacmp(&a->device, BDADDR_ANY) == 0)
+
+		list = sdp_list_append(list, rec);
+	}
+
+	return list;
+}
+
 int sdp_check_access(uint32_t handle, bdaddr_t *device)
 {
 	sdp_list_t *p = access_locate(handle);
diff --git a/src/sdpd.h b/src/sdpd.h
index 1352a83..15e163b 100644
--- a/src/sdpd.h
+++ b/src/sdpd.h
@@ -79,6 +79,7 @@ void sdp_record_add(const bdaddr_t *device, sdp_record_t *rec);
 int sdp_record_remove(uint32_t handle);
 sdp_list_t *sdp_get_record_list(void);
 sdp_list_t *sdp_get_access_list(void);
+sdp_list_t *sdp_get_record_list_by_device(const bdaddr_t *device);
 int sdp_check_access(uint32_t handle, bdaddr_t *device);
 uint32_t sdp_next_handle(void);
 
diff --git a/test/list-devices b/test/list-devices
index 511d0cf..9120714 100755
--- a/test/list-devices
+++ b/test/list-devices
@@ -40,6 +40,9 @@ for i in adapter_list:
 		if (key == "Devices"):
 			list = extract_objects(value)
 			print "    %s = %s" % (key, list)
+		elif (key == "UUIDs"):
+			list = extract_uuids(value)
+			print "    %s = %s" % (key, list)
 		else:
 			print "    %s = %s" % (key, value)
 
-- 
1.6.3.3


^ permalink raw reply related

* Re: [PATCH] Print pkt_type when decoding Setup Synchronous Connection command.
From: Marcel Holtmann @ 2010-03-24 21:03 UTC (permalink / raw)
  To: Nick Pelly; +Cc: linux-bluetooth
In-Reply-To: <1265764049-2709-1-git-send-email-npelly@google.com>

Hi Nick,

> diff --git a/parser/hci.c b/parser/hci.c
> index c0ca27e..958cd38 100644
> --- a/parser/hci.c
> +++ b/parser/hci.c
> @@ -917,8 +917,9 @@ static inline void setup_sync_conn_dump(int level, struct frame *frm)
>  	setup_sync_conn_cp *cp = frm->ptr;
>  
>  	p_indent(level, frm);
> -	printf("handle %d voice setting 0x%4.4x\n", btohs(cp->handle),
> -						btohs(cp->voice_setting));
> +	printf("handle %d voice setting 0x%4.4x pkt_type 0x%4.4x\n",
> +		btohs(cp->handle), btohs(cp->voice_setting),
> +		btohs(cp->pkt_type));
>  }

I renamed it to ptype instead of pkt_type to be consistent, but
otherwise, patch has been applied. Thanks.

Regards

Marcel



^ permalink raw reply

* RE: A strange compatible problem for eSCO audio with CSR USB Bluetooth dongle
From: Cooper Xu @ 2010-03-24 21:08 UTC (permalink / raw)
  To: 'Marcel Holtmann'; +Cc: linux-bluetooth
In-Reply-To: <1268707083.2700.14.camel@localhost.localdomain>

Hi Marcel,

Do you have any clue what happened? I tried the same test with the latest
Linux 2.6.34-rc2 kernel and had the same result. This seemed to be easily
reproducible with two CSR USB dongles of LMP Subver 0xc5c.

Thanks

Cooper 



-----Original Message-----
From: Marcel Holtmann [mailto:marcel@holtmann.org] 
Sent: Monday, March 15, 2010 10:38 PM
To: Cooper Xu
Cc: linux-bluetooth@vger.kernel.org
Subject: RE: A strange compatible problem for eSCO audio with CSR USB
Bluetooth dongle

Hi Cooper,

no top posting on this mailing list. We do proper inline quoting.

> I used the attached scotest.c to do the test for both client and server.
> This file is from Bluez 4.58. I modified a little because the original is
> sending packets too fast. I turned off eSCO according to Nick's
suggestion.

the scotest.c tool is just for basic testing. There is no guarantee that
it does the right job. Some devices might send silence if the Headset or
Handsfree profile is not fully setup.

Regards

Marcel

^ permalink raw reply

* [PATCH 1/1] bluetooth: BT driver using ST for TI combo devices
From: pavan_savoy @ 2010-03-24 21:37 UTC (permalink / raw)
  To: marcel; +Cc: pavan_savoy, linux-kernel, linux-bluetooth, Pavan Savoy

From: Pavan Savoy <pavan_savoy@ti.com>

This is BlueZ driver making use of Shared Transport line
discipline to communicate with the chip.

Signed-off-by: Pavan Savoy <pavan_savoy@ti.com>
---
 drivers/staging/ti-st/bt_drv.c |  502 ++++++++++++++++++++++++++++++++++++++++
 drivers/staging/ti-st/bt_drv.h |   61 +++++
 2 files changed, 563 insertions(+), 0 deletions(-)
 create mode 100644 drivers/staging/ti-st/bt_drv.c
 create mode 100644 drivers/staging/ti-st/bt_drv.h

diff --git a/drivers/staging/ti-st/bt_drv.c b/drivers/staging/ti-st/bt_drv.c
new file mode 100644
index 0000000..d8420b5
--- /dev/null
+++ b/drivers/staging/ti-st/bt_drv.c
@@ -0,0 +1,502 @@
+/*
+ *  Texas Instrument's Bluetooth Driver For Shared Transport.
+ *
+ *  Bluetooth Driver acts as interface between HCI CORE and
+ *  TI Shared Transport Layer.
+ *
+ *  Copyright (C) 2009 Texas Instruments
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+#include "st.h"
+#include "bt_drv.h"
+
+/* Define this macro to get debug msg */
+#undef DEBUG
+
+#ifdef DEBUG
+#define BT_DRV_DBG(fmt, arg...)  printk(KERN_INFO "(btdrv):"fmt"\n" , ## arg)
+#define BTDRV_API_START()        printk(KERN_INFO "(btdrv): %s Start\n", \
+	__func__)
+#define BTDRV_API_EXIT(errno)    printk(KERN_INFO "(btdrv): %s Exit(%d)\n", \
+	__func__, errno)
+#else
+#define BT_DRV_DBG(fmt, arg...)
+#define BTDRV_API_START()
+#define BTDRV_API_EXIT(errno)
+#endif
+
+#define BT_DRV_ERR(fmt, arg...)  printk(KERN_ERR "(btdrv):"fmt"\n" , ## arg)
+
+static int reset;
+static struct hci_st *hst;
+
+/* Increments HCI counters based on pocket ID (cmd,acl,sco) */
+static inline void hci_st_tx_complete(struct hci_st *hst, int pkt_type)
+{
+	struct hci_dev *hdev;
+
+	BTDRV_API_START();
+
+	hdev = hst->hdev;
+
+	/* Update HCI stat counters */
+	switch (pkt_type) {
+	case HCI_COMMAND_PKT:
+		hdev->stat.cmd_tx++;
+		break;
+
+	case HCI_ACLDATA_PKT:
+		hdev->stat.acl_tx++;
+		break;
+
+	case HCI_SCODATA_PKT:
+		hdev->stat.cmd_tx++;
+		break;
+	}
+
+	BTDRV_API_EXIT(0);
+}
+
+/* ------- Interfaces to Shared Transport ------ */
+
+/* Called by ST layer to indicate protocol registration completion
+ * status.hci_st_open() function will wait for signal from this
+ * API when st_register() function returns ST_PENDING.
+ */
+static void hci_st_registration_completion_cb(char data)
+{
+	BTDRV_API_START();
+
+	/* hci_st_open() function needs value of 'data' to know
+	 * the registration status(success/fail),So have a back
+	 * up of it.
+	 */
+	hst->streg_cbdata = data;
+
+	/* Got a feedback from ST for BT driver registration
+	 * request.Wackup hci_st_open() function to continue
+	 * it's open operation.
+	 */
+	complete(&hst->wait_for_btdrv_reg_completion);
+
+	BTDRV_API_EXIT(0);
+}
+
+/* Called by Shared Transport layer when receive data is
+ * available */
+static long hci_st_receive(struct sk_buff *skb)
+{
+	int err;
+	int len;
+
+	BTDRV_API_START();
+
+	err = 0;
+	len = 0;
+
+	if (skb == NULL) {
+		BT_DRV_ERR("Invalid SKB received from ST");
+		BTDRV_API_EXIT(-EFAULT);
+		return -EFAULT;
+	}
+	if (!hst) {
+		kfree_skb(skb);
+		BT_DRV_ERR("Invalid hci_st memory,freeing SKB");
+		BTDRV_API_EXIT(-EFAULT);
+		return -EFAULT;
+	}
+	if (!test_bit(BT_DRV_RUNNING, &hst->flags)) {
+		kfree_skb(skb);
+		BT_DRV_ERR("Device is not running,freeing SKB");
+		BTDRV_API_EXIT(-EINVAL);
+		return -EINVAL;
+	}
+
+	len = skb->len;
+	skb->dev = (struct net_device *)hst->hdev;
+
+	/* Forward skb to HCI CORE layer */
+	err = hci_recv_frame(skb);
+	if (err) {
+		kfree_skb(skb);
+		BT_DRV_ERR("Unable to push skb to HCI CORE(%d),freeing SKB",
+			   err);
+		BTDRV_API_EXIT(err);
+		return err;
+	}
+	hst->hdev->stat.byte_rx += len;
+
+	BTDRV_API_EXIT(0);
+	return 0;
+}
+
+/* ------- Interfaces to HCI layer ------ */
+
+/* Called from HCI core to initialize the device */
+static int hci_st_open(struct hci_dev *hdev)
+{
+	static struct st_proto_s hci_st_proto;
+	unsigned long timeleft;
+	int err;
+
+	BTDRV_API_START();
+
+	err = 0;
+
+	BT_DRV_DBG("%s %p", hdev->name, hdev);
+
+	/* Already registered with ST ? */
+	if (test_bit(BT_ST_REGISTERED, &hst->flags)) {
+		BT_DRV_ERR("Registered with ST already,open called again?");
+		BTDRV_API_EXIT(0);
+		return 0;
+	}
+
+	/* Populate BT driver info required by ST */
+	memset(&hci_st_proto, 0, sizeof(hci_st_proto));
+
+	/* BT driver ID */
+	hci_st_proto.type = ST_BT;
+
+	/* Receive function which called from ST */
+	hci_st_proto.recv = hci_st_receive;
+
+	/* Packet match function may used in future */
+	hci_st_proto.match_packet = NULL;
+
+	/* Callback to be called when registration is pending */
+	hci_st_proto.reg_complete_cb = hci_st_registration_completion_cb;
+
+	/* This is write function pointer of ST. BT driver will make use of this
+	 * for sending any packets to chip. ST will assign and give to us, so
+	 * make it as NULL */
+	hci_st_proto.write = NULL;
+
+	/* Register with ST layer */
+	err = st_register(&hci_st_proto);
+	if (err == ST_ERR_PENDING) {
+		/* Prepare wait-for-completion handler data structures.
+		 * Needed to syncronize this and st_registration_completion_cb()
+		 * functions.
+		 */
+		init_completion(&hst->wait_for_btdrv_reg_completion);
+
+		/* Reset ST registration callback status flag , this value
+		 * will be updated in hci_st_registration_completion_cb()
+		 * function whenever it called from ST driver.
+		 */
+		hst->streg_cbdata = -EINPROGRESS;
+
+		/* ST is busy with other protocol registration(may be busy with
+		 * firmware download).So,Wait till the registration callback
+		 * (passed as a argument to st_register() function) getting
+		 * called from ST.
+		 */
+		BT_DRV_DBG(" %s waiting for reg completion signal from ST",
+			   __func__);
+
+		timeleft =
+		    wait_for_completion_timeout
+		    (&hst->wait_for_btdrv_reg_completion,
+		     msecs_to_jiffies(BT_REGISTER_TIMEOUT));
+		if (!timeleft) {
+			BT_DRV_ERR("Timeout(%ld sec),didn't get reg"
+				   "completion signal from ST",
+				   BT_REGISTER_TIMEOUT / 1000);
+			BTDRV_API_EXIT(-ETIMEDOUT);
+			return -ETIMEDOUT;
+		}
+
+		/* Is ST registration callback called with ERROR value? */
+		if (hst->streg_cbdata != 0) {
+			BT_DRV_ERR("ST reg completion CB called with invalid"
+				   "status %d", hst->streg_cbdata);
+			BTDRV_API_EXIT(-EAGAIN);
+			return -EAGAIN;
+		}
+		err = 0;
+	} else if (err == ST_ERR_FAILURE) {
+		BT_DRV_ERR("st_register failed %d", err);
+		BTDRV_API_EXIT(-EAGAIN);
+		return -EAGAIN;
+	}
+
+	/* Do we have proper ST write function? */
+	if (hci_st_proto.write != NULL) {
+		/* We need this pointer for sending any Bluetooth pkts */
+		hst->st_write = hci_st_proto.write;
+	} else {
+		BT_DRV_ERR("failed to get ST write func pointer");
+
+		/* Undo registration with ST */
+		err = st_unregister(ST_BT);
+		if (err < 0)
+			BT_DRV_ERR("st_unregister failed %d", err);
+
+		hst->st_write = NULL;
+		BTDRV_API_EXIT(-EAGAIN);
+		return -EAGAIN;
+	}
+
+	/* Registration with ST layer is completed successfully,
+	 * now chip is ready to accept commands from HCI CORE.
+	 * Mark HCI Device flag as RUNNING
+	 */
+	set_bit(HCI_RUNNING, &hdev->flags);
+
+	/* Registration with ST successful */
+	set_bit(BT_ST_REGISTERED, &hst->flags);
+
+	BTDRV_API_EXIT(err);
+	return err;
+}
+
+/* Close device */
+static int hci_st_close(struct hci_dev *hdev)
+{
+	int err;
+
+	BTDRV_API_START();
+
+	err = 0;
+
+	/* Unregister from ST layer */
+	if (test_and_clear_bit(BT_ST_REGISTERED, &hst->flags)) {
+		err = st_unregister(ST_BT);
+		if (err != ST_SUCCESS) {
+			BT_DRV_ERR("st_unregister failed %d", err);
+			BTDRV_API_EXIT(-EBUSY);
+			return -EBUSY;
+		}
+	}
+
+	hst->st_write = NULL;
+
+	/* ST layer would have moved chip to inactive state.
+	 * So,clear HCI device RUNNING flag.
+	 */
+	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) {
+		BTDRV_API_EXIT(0);
+		return 0;
+	}
+
+	BTDRV_API_EXIT(err);
+	return err;
+}
+
+/* Called from HCI CORE , Sends frames to Shared Transport */
+static int hci_st_send_frame(struct sk_buff *skb)
+{
+	struct hci_dev *hdev;
+	struct hci_st *hst;
+	long len;
+
+	BTDRV_API_START();
+
+	if (skb == NULL) {
+		BT_DRV_ERR("Invalid skb received from HCI CORE");
+		BTDRV_API_EXIT(-ENOMEM);
+		return -ENOMEM;
+	}
+	hdev = (struct hci_dev *)skb->dev;
+	if (!hdev) {
+		BT_DRV_ERR("SKB received for invalid HCI Device (hdev=NULL)");
+		BTDRV_API_EXIT(-ENODEV);
+		return -ENODEV;
+	}
+	if (!test_bit(HCI_RUNNING, &hdev->flags)) {
+		BT_DRV_ERR("Device is not running");
+		BTDRV_API_EXIT(-EBUSY);
+		return -EBUSY;
+	}
+
+	hst = (struct hci_st *)hdev->driver_data;
+
+	/* Prepend skb with frame type */
+	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
+
+	BT_DRV_DBG(" %s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type,
+		   skb->len);
+
+	/* Insert skb to shared transport layer's transmit queue.
+	 * Freeing skb memory is taken care in shared transport layer,
+	 * so don't free skb memory here.
+	 */
+	if (!hst->st_write) {
+		kfree_skb(skb);
+		BT_DRV_ERR(" Can't write to ST, st_write null?");
+		BTDRV_API_EXIT(-EAGAIN);
+		return -EAGAIN;
+	}
+	len = hst->st_write(skb);
+	if (len < 0) {
+		/* Something went wrong in st write , free skb memory */
+		kfree_skb(skb);
+		BT_DRV_ERR(" ST write failed (%ld)", len);
+		BTDRV_API_EXIT(-EAGAIN);
+		return -EAGAIN;
+	}
+
+	/* ST accepted our skb. So, Go ahead and do rest */
+	hdev->stat.byte_tx += len;
+	hci_st_tx_complete(hst, bt_cb(skb)->pkt_type);
+
+	BTDRV_API_EXIT(0);
+	return 0;
+}
+
+static void hci_st_destruct(struct hci_dev *hdev)
+{
+	BTDRV_API_START();
+
+	if (!hdev) {
+		BT_DRV_ERR("Destruct called with invalid HCI Device"
+			   "(hdev=NULL)");
+		BTDRV_API_EXIT(0);
+		return;
+	}
+
+	BT_DRV_DBG("%s", hdev->name);
+
+	/* free hci_st memory */
+	if (hdev->driver_data != NULL)
+		kfree(hdev->driver_data);
+
+	BTDRV_API_EXIT(0);
+	return;
+}
+
+/* Creates new HCI device */
+static int hci_st_register_dev(struct hci_st *hst)
+{
+	struct hci_dev *hdev;
+
+	BTDRV_API_START();
+
+	/* Initialize and register HCI device */
+	hdev = hci_alloc_dev();
+	if (!hdev) {
+		BT_DRV_ERR("Can't allocate HCI device");
+		BTDRV_API_EXIT(-ENOMEM);
+		return -ENOMEM;
+	}
+	BT_DRV_DBG(" HCI device allocated. hdev= %p", hdev);
+
+	hst->hdev = hdev;
+	hdev->bus = HCI_UART;
+	hdev->driver_data = hst;
+	hdev->open = hci_st_open;
+	hdev->close = hci_st_close;
+	hdev->flush = NULL;
+	hdev->send = hci_st_send_frame;
+	hdev->destruct = hci_st_destruct;
+	hdev->owner = THIS_MODULE;
+
+	if (reset)
+		set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
+
+	if (hci_register_dev(hdev) < 0) {
+		BT_DRV_ERR("Can't register HCI device");
+		hci_free_dev(hdev);
+		BTDRV_API_EXIT(-ENODEV);
+		return -ENODEV;
+	}
+
+	BT_DRV_DBG(" HCI device registered. hdev= %p", hdev);
+	BTDRV_API_EXIT(0);
+	return 0;
+}
+
+/* ------- Module Init interface ------ */
+
+static int __init bt_drv_init(void)
+{
+	int err;
+
+	BTDRV_API_START();
+
+	err = 0;
+
+	BT_DRV_DBG(" Bluetooth Driver Version %s", VERSION);
+
+	/* Allocate local resource memory */
+	hst = kzalloc(sizeof(struct hci_st), GFP_KERNEL);
+	if (!hst) {
+		BT_DRV_ERR("Can't allocate control structure");
+		BTDRV_API_EXIT(-ENFILE);
+		return -ENFILE;
+	}
+
+	/* Expose "hciX" device to user space */
+	err = hci_st_register_dev(hst);
+	if (err) {
+		/* Release local resource memory */
+		kfree(hst);
+
+		BT_DRV_ERR("Unable to expose hci0 device(%d)", err);
+		BTDRV_API_EXIT(err);
+		return err;
+	}
+	set_bit(BT_DRV_RUNNING, &hst->flags);
+
+	BTDRV_API_EXIT(err);
+	return err;
+}
+
+/* ------- Module Exit interface ------ */
+
+static void __exit bt_drv_exit(void)
+{
+	BTDRV_API_START();
+
+	/* Deallocate local resource's memory  */
+	if (hst) {
+		struct hci_dev *hdev = hst->hdev;
+
+		if (hdev == NULL) {
+			BT_DRV_ERR("Invalid hdev memory");
+			kfree(hst);
+		} else {
+			hci_st_close(hdev);
+			if (test_and_clear_bit(BT_DRV_RUNNING, &hst->flags)) {
+				/* Remove HCI device (hciX) created
+				 * in module init.
+				 */
+				hci_unregister_dev(hdev);
+
+				/* Free HCI device memory */
+				hci_free_dev(hdev);
+			}
+		}
+	}
+	BTDRV_API_EXIT(0);
+}
+
+module_init(bt_drv_init);
+module_exit(bt_drv_exit);
+
+/* ------ Module Info ------ */
+
+module_param(reset, bool, 0644);
+MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
+MODULE_AUTHOR("Raja Mani <raja_mani@ti.com>");
+MODULE_DESCRIPTION("Bluetooth Driver for TI Shared Transport" VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/ti-st/bt_drv.h b/drivers/staging/ti-st/bt_drv.h
new file mode 100644
index 0000000..a0beebe
--- /dev/null
+++ b/drivers/staging/ti-st/bt_drv.h
@@ -0,0 +1,61 @@
+/*
+ *  Texas Instrument's Bluetooth Driver For Shared Transport.
+ *
+ *  Bluetooth Driver acts as interface between HCI CORE and
+ *  TI Shared Transport Layer.
+ *
+ *  Copyright (C) 2009 Texas Instruments
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _BT_DRV_H
+#define _BT_DRV_H
+
+/* Bluetooth Driver Version */
+#define VERSION               "1.0"
+
+/* Defines number of seconds to wait for reg completion
+ * callback getting called from ST (in case,registration
+ * with ST returns PENDING status)
+ */
+#define BT_REGISTER_TIMEOUT   msecs_to_jiffies(6000)	/* 6 sec */
+
+/* BT driver's local status */
+#define BT_DRV_RUNNING        0
+#define BT_ST_REGISTERED      1
+
+/* BT driver operation structure */
+struct hci_st {
+
+	/* hci device pointer which binds to bt driver */
+	struct hci_dev *hdev;
+
+	/* used locally,to maintain various BT driver status */
+	unsigned long flags;
+
+	/* to hold ST registration callback  status */
+	char streg_cbdata;
+
+	/* write function pointer of ST driver */
+	long (*st_write) (struct sk_buff *);
+
+	/* Wait on comepletion handler needed to synchronize
+	 * hci_st_open() and hci_st_registration_completion_cb()
+	 * functions.*/
+	struct completion wait_for_btdrv_reg_completion;
+};
+
+#endif
-- 
1.5.4.3

^ permalink raw reply related

* Re: [PATCH] Report local services(UUIDs) through DBus
From: Johan Hedberg @ 2010-03-24 21:53 UTC (permalink / raw)
  To: Francisco Alecrim; +Cc: linux-bluetooth
In-Reply-To: <1269462368-14079-1-git-send-email-francisco.alecrim@openbossa.org>

Hi,

On Wed, Mar 24, 2010, Francisco Alecrim wrote:
> Include UUIDs field to method GetProperties(org.bluez.Adapter).
> Applications can get local services(UUIDs) available through DBus.
> ---
>  doc/adapter-api.txt |    5 +++++
>  src/adapter.c       |   20 +++++++++++++++++++-
>  src/sdpd-database.c |   21 +++++++++++++++++++++
>  src/sdpd.h          |    1 +
>  test/list-devices   |    3 +++
>  5 files changed, 49 insertions(+), 1 deletions(-)

Thanks for the patch! It looks quite nice and clean :)

However, since it doesn't implement the PropertyChanged signals for the
new property I'll wait until Marcel gets the next release out the door
before pushing this one upstream (so we don't get a new BlueZ release
with a partially implemented API)

Johan

^ permalink raw reply

* Re: [PATCH] Set voice_call.watch in correct way
From: Johan Hedberg @ 2010-03-25 10:12 UTC (permalink / raw)
  To: Forrest Zhao; +Cc: linux-bluetooth, forrest.zhao
In-Reply-To: <1269534610-1138-1-git-send-email-forrest.zhao@intel.com>

Hi Forrest,

On Thu, Mar 25, 2010, Forrest Zhao wrote:
> It was set wrongly to device_watch.
> ---
>  audio/telephony-ofono.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/audio/telephony-ofono.c b/audio/telephony-ofono.c
> index c19e6ee..45c3905 100644
> --- a/audio/telephony-ofono.c
> +++ b/audio/telephony-ofono.c
> @@ -850,7 +850,7 @@ static gboolean handle_vcmanager_property_changed(DBusConnection *conn,
>  			vc_new = g_new0(struct voice_call, 1);
>  			vc_new->obj_path = g_strdup(vc_obj_path);
>  			calls = g_slist_append(calls, vc_new);
> -			device_watch = g_dbus_add_signal_watch(connection,
> +			vc_new->watch = g_dbus_add_signal_watch(connection,
>  					NULL, vc_obj_path,
>  					OFONO_VC_INTERFACE,
>  					"PropertyChanged",

Pushed upstream. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH] Support relative path on send-files example
From: Johan Hedberg @ 2010-03-25 13:13 UTC (permalink / raw)
  To: Danilo Cesar Lemes de Paula; +Cc: linux-bluetooth, Danilo Cesar Lemes de Paula
In-Reply-To: <1267814806-6806-1-git-send-email-danilo.cesar@openbossa.org>

Hi Danilo,

On Fri, Mar 05, 2010, Danilo Cesar Lemes de Paula wrote:
> Agent should receive the absolute path as it runs on a different CWD
> ---
>  test/send-files |    4 +++-
>  1 files changed, 3 insertions(+), 1 deletions(-)

This patch has now been pushed upstream. Thanks.

Johan

^ permalink raw reply

* Re: 2.6.34-rc1: bluetooth oops
From: Pavel Machek @ 2010-03-25 14:26 UTC (permalink / raw)
  To: Marcel Holtmann, netdev, Rafael J. Wysocki
  Cc: kernel list, linux-bluetooth, Rafael J. Wysocki
In-Reply-To: <20100314204434.GB5208@elf.ucw.cz>

On Sun 2010-03-14 21:44:34, Pavel Machek wrote:
> Hi!
> 
> > > I got this after trying to use bnep for few minutes... Machine locked
> > > after that, not sure if it is related.
> > 
> > I can't explain it since we haven't changed the BNEP code. So that might
> > be a problem in the networking layer. So posting it to netdev might be a
> > good idea.
> 
> Ok, I'll try using bnep some more. I had bad problems with cellphone
> connection at that point, so maybe it is not easy to repeat, and it
> the fact I have not seen it before may not mean much...

So it seems to repeat about twice a week, definitely a regression :-(.

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply

* Problems with bt_io_listen
From: José Antonio Santos Cadenas @ 2010-03-25 14:45 UTC (permalink / raw)
  To: linux-bluetooth

Hi all,

We are developing an implementation of HDP and MCAP for bluez. We are triying 
to perform many connections between two devices but when we make the second 
connection it is not created correctly.

We are using a defer connection (we passed a confirm callback to the 
bt_io_listen function) and we think that we are missing something but  we 
can't find what. If we used the connection callback (not defer) all the 
connections are done successfully.

We are listening with the following code:

static void confirm_cb(GIOChannel *chan, gpointer user_data)
{
	...
	node->chan = g_io_channel_ref(chan);
	...
	/* All is ok */
	return;
drop:
	/* Connection refused */
	g_io_channel_shutdown(chan, TRUE, NULL);
}

....
chan = bt_io_listen(BT_IO_L2CAP, NULL, confirm_cb, NULL,
				NULL, &gerr,
				BT_IO_OPT_SOURCE_BDADDR, &src,
				BT_IO_OPT_PSM, 0x1001,
				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
				BT_IO_OPT_INVALID);
...

Any ideas?

Regards and thank.

Jose.

^ permalink raw reply

* Re: Problems with bt_io_listen
From: Luiz Augusto von Dentz @ 2010-03-25 15:22 UTC (permalink / raw)
  To: jcaden; +Cc: linux-bluetooth
In-Reply-To: <201003251545.52988.jcaden@libresoft.es>

Hi,

On Thu, Mar 25, 2010 at 4:45 PM, José Antonio Santos Cadenas
<jcaden@libresoft.es> wrote:
> Hi all,
>
> We are developing an implementation of HDP and MCAP for bluez. We are triying
> to perform many connections between two devices but when we make the second
> connection it is not created correctly.
>
> We are using a defer connection (we passed a confirm callback to the
> bt_io_listen function) and we think that we are missing something but  we
> can't find what. If we used the connection callback (not defer) all the
> connections are done successfully.
>
> We are listening with the following code:
>
> static void confirm_cb(GIOChannel *chan, gpointer user_data)
> {
>        ...
>        node->chan = g_io_channel_ref(chan);
>        ...
>        /* All is ok */
>        return;
> drop:
>        /* Connection refused */
>        g_io_channel_shutdown(chan, TRUE, NULL);
> }

Im not really sure what is the problem but maybe it is the missing
bt_io_accept, but of course it can be that you just hide it in those
...

> ....
> chan = bt_io_listen(BT_IO_L2CAP, NULL, confirm_cb, NULL,
>                                NULL, &gerr,
>                                BT_IO_OPT_SOURCE_BDADDR, &src,
>                                BT_IO_OPT_PSM, 0x1001,
>                                BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
>                                BT_IO_OPT_INVALID);
> ...

The listen part at least seems ok.


-- 
Luiz Augusto von Dentz
Computer Engineer

^ permalink raw reply

* Re: Problems with bt_io_listen
From: sancane @ 2010-03-25 16:13 UTC (permalink / raw)
  Cc: linux-bluetooth
In-Reply-To: <2d5a2c101003250822g34187992m8509e17e825f50c8@mail.gmail.com>

Hello,

> Hi,
> 
> On Thu, Mar 25, 2010 at 4:45 PM, José Antonio Santos Cadenas
> <jcaden@libresoft.es> wrote:
>> Hi all,
>>
>> We are developing an implementation of HDP and MCAP for bluez. We are triying
>> to perform many connections between two devices but when we make the second
>> connection it is not created correctly.
>>
>> We are using a defer connection (we passed a confirm callback to the
>> bt_io_listen function) and we think that we are missing something but  we
>> can't find what. If we used the connection callback (not defer) all the
>> connections are done successfully.
>>
>> We are listening with the following code:
>>
>> static void confirm_cb(GIOChannel *chan, gpointer user_data)
>> {
>>        ...
>>        node->chan = g_io_channel_ref(chan);
>>        ...
>>        /* All is ok */
>>        return;
>> drop:
>>        /* Connection refused */
>>        g_io_channel_shutdown(chan, TRUE, NULL);
>> }
> 
> Im not really sure what is the problem but maybe it is the missing
> bt_io_accept, but of course it can be that you just hide it in those
> ...

You're rigth, we forgot the bt_io_accept call.

> 
>> ....
>> chan = bt_io_listen(BT_IO_L2CAP, NULL, confirm_cb, NULL,
>>                                NULL, &gerr,
>>                                BT_IO_OPT_SOURCE_BDADDR, &src,
>>                                BT_IO_OPT_PSM, 0x1001,
>>                                BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
>>                                BT_IO_OPT_INVALID);
>> ...
> 
> The listen part at least seems ok.
> 
> 
Thanks.

^ permalink raw reply

* [PATCH] Set voice_call.watch in correct way
From: Forrest Zhao @ 2010-03-25 16:30 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth, forrest.zhao, Forrest Zhao

It was set wrongly to device_watch.
---
 audio/telephony-ofono.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/audio/telephony-ofono.c b/audio/telephony-ofono.c
index c19e6ee..45c3905 100644
--- a/audio/telephony-ofono.c
+++ b/audio/telephony-ofono.c
@@ -850,7 +850,7 @@ static gboolean handle_vcmanager_property_changed(DBusConnection *conn,
 			vc_new = g_new0(struct voice_call, 1);
 			vc_new->obj_path = g_strdup(vc_obj_path);
 			calls = g_slist_append(calls, vc_new);
-			device_watch = g_dbus_add_signal_watch(connection,
+			vc_new->watch = g_dbus_add_signal_watch(connection,
 					NULL, vc_obj_path,
 					OFONO_VC_INTERFACE,
 					"PropertyChanged",
-- 
1.6.1.3


^ permalink raw reply related

* Small issue to receive "org.bluez.AudioSource" dbus message
From: dove xia @ 2010-03-26  3:12 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-kernel, linux-bluetooth

Hi,

	This is Dove as a new comer to Linux-bluetooth group.
	
	Currently, I am developing BlueZ stack works as A2DP Sink. After the
BlueZ runs, it works smoothly. I have developed a program run on Linux
user space to catch the BlueZ DBus messages. But the program can't
receive DBus messages from "org.bluez.AudioSource".
	I have test the BlueZ works as source before, I can receive DBus
messages from  "org.bluez.AudioSink".
	
	The test step is:
	1. Update the audio.conf to set the bluetooth works as A2DP Sink.
	2. Set the bluetooth into discoverable mode.
	3. Use another bluetooth device (a mobile), search and connect BlueZ.
	3. Play music from mobile.
	4. use a test program on Linux user space to catch the BlueZ
AudioSource DBus messages.
	The test case will expect the test program can catch the AudioSource
dbus messages, but it failed.
	
	I have traced the BlueZ source code, found a little clew in
audio/a2dp.c, the function sbc_setconf_ind() and mpeg_setconf_ind()
have not called source_new_stream() while the a2dp_sep->type is
AVDTP_SEP_TYPE_SINK, I patched code to call source_new_stream().
base on BlueZ 4.62, in audio/a2dp.c

@@ -341,6 +341,8 @@

 	if (a2dp_sep->type == AVDTP_SEP_TYPE_SOURCE)
 		sink_new_stream(dev, session, stream);
+	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
+		source_new_stream(dev, session, stream);

 	return TRUE;
 }
@@ -445,6 +447,8 @@

 	if (a2dp_sep->type == AVDTP_SEP_TYPE_SOURCE)
 		sink_new_stream(dev, session, stream);
+	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
+		source_new_stream(dev, session, stream);

 	return TRUE;
 }

	After I patched the code, my test program can receive the
"org.bluez.AudioSource" DBus messages. the BlueZ work smoothly as
before. so I think this is a correct fix.

	Need your confirm.
	
-- 
BR
Dove

^ permalink raw reply

* [PATCH 1/6] Bluetooth: Ignore Tx Window value with Streaming mode
From: Gustavo F. Padovan @ 2010-03-26 19:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo
In-Reply-To: <1269373726-13209-20-git-send-email-padovan@profusion.mobi>

Tx Window value shall not be used with Streaming Mode and the receiver
of the config Request shall ignore its value.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 net/bluetooth/l2cap.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 8c8b5d9..2cfad45 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -2491,7 +2491,6 @@ done:
 			break;
 
 		case L2CAP_MODE_STREAMING:
-			pi->remote_tx_win = rfc.txwin_size;
 			pi->max_pdu_size = rfc.max_pdu_size;
 
 			pi->conf_state |= L2CAP_CONF_MODE_DONE;
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 2/6] Bluetooth: Read RFC conf option on a successful Conf RSP
From: Gustavo F. Padovan @ 2010-03-26 19:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo
In-Reply-To: <1269631159-20750-1-git-send-email-padovan@profusion.mobi>

On Enhanced Retransmission Mode and Streaming Mode a entity can send, on
a successful Conf RSP, new values for the RFC fields. For example, the
entity can send txWindow and MPS values less than the value received on
a Conf REQ.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 net/bluetooth/l2cap.c |   39 ++++++++++++++++++++++++++++++++++++++-
 1 files changed, 38 insertions(+), 1 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 2cfad45..40aff8d 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -2598,6 +2598,42 @@ static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 fla
 	return ptr - data;
 }
 
+static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	int type, olen;
+	unsigned long val;
+	struct l2cap_conf_rfc rfc;
+
+	BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
+
+	if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
+		return;
+
+	while (len >= L2CAP_CONF_OPT_SIZE) {
+		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
+
+		switch (type) {
+		case L2CAP_CONF_RFC:
+			if (olen == sizeof(rfc))
+				memcpy(&rfc, (void *)val, olen);
+			goto done;
+		}
+	}
+
+done:
+	switch (rfc.mode) {
+	case L2CAP_MODE_ERTM:
+		pi->remote_tx_win   = rfc.txwin_size;
+		pi->retrans_timeout = rfc.retrans_timeout;
+		pi->monitor_timeout = rfc.monitor_timeout;
+		pi->mps    = le16_to_cpu(rfc.max_pdu_size);
+		break;
+	case L2CAP_MODE_STREAMING:
+		pi->mps    = le16_to_cpu(rfc.max_pdu_size);
+	}
+}
+
 static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
 {
 	struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
@@ -2877,6 +2913,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
 	u16 scid, flags, result;
 	struct sock *sk;
+	int len = cmd->len - sizeof(*rsp);
 
 	scid   = __le16_to_cpu(rsp->scid);
 	flags  = __le16_to_cpu(rsp->flags);
@@ -2891,11 +2928,11 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 
 	switch (result) {
 	case L2CAP_CONF_SUCCESS:
+		l2cap_conf_rfc_get(sk, rsp->data, len);
 		break;
 
 	case L2CAP_CONF_UNACCEPT:
 		if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
-			int len = cmd->len - sizeof(*rsp);
 			char req[64];
 
 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 3/6] Bluetooth: Fix configuration of the MPS value
From: Gustavo F. Padovan @ 2010-03-26 19:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo
In-Reply-To: <1269631159-20750-2-git-send-email-padovan@profusion.mobi>

We were accepting values bigger than we can accept. This was leading
ERTM to drop packets because of wrong FCS checks.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 include/net/bluetooth/l2cap.h |    3 ++-
 net/bluetooth/l2cap.c         |   36 ++++++++++++++++++++----------------
 2 files changed, 22 insertions(+), 17 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 48f10f4..0f4e423 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -343,7 +343,8 @@ struct l2cap_pinfo {
 	__u8		remote_max_tx;
 	__u16		retrans_timeout;
 	__u16		monitor_timeout;
-	__u16		max_pdu_size;
+	__u16		remote_mps;
+	__u16		mps;
 
 	__le16		sport;
 
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 40aff8d..4c98e3c 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1605,21 +1605,21 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, siz
 
 	__skb_queue_head_init(&sar_queue);
 	control = L2CAP_SDU_START;
-	skb = l2cap_create_iframe_pdu(sk, msg, pi->max_pdu_size, control, len);
+	skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
 	if (IS_ERR(skb))
 		return PTR_ERR(skb);
 
 	__skb_queue_tail(&sar_queue, skb);
-	len -= pi->max_pdu_size;
-	size +=pi->max_pdu_size;
+	len -= pi->remote_mps;
+	size +=pi->remote_mps;
 	control = 0;
 
 	while (len > 0) {
 		size_t buflen;
 
-		if (len > pi->max_pdu_size) {
+		if (len > pi->remote_mps) {
 			control |= L2CAP_SDU_CONTINUE;
-			buflen = pi->max_pdu_size;
+			buflen = pi->remote_mps;
 		} else {
 			control |= L2CAP_SDU_END;
 			buflen = len;
@@ -1697,7 +1697,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
 	case L2CAP_MODE_ERTM:
 	case L2CAP_MODE_STREAMING:
 		/* Entire SDU fits into one PDU */
-		if (len <= pi->max_pdu_size) {
+		if (len <= pi->remote_mps) {
 			control = L2CAP_SDU_UNSEGMENTED;
 			skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0);
 			if (IS_ERR(skb)) {
@@ -2326,7 +2326,7 @@ done:
 		rfc.monitor_timeout = 0;
 		rfc.max_pdu_size    = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
 		if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
-			rfc.max_pdu_size = pi->conn->mtu - 10;
+			rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
 
 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
 					sizeof(rfc), (unsigned long) &rfc);
@@ -2349,7 +2349,7 @@ done:
 		rfc.monitor_timeout = 0;
 		rfc.max_pdu_size    = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
 		if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
-			rfc.max_pdu_size = pi->conn->mtu - 10;
+			rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
 
 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
 					sizeof(rfc), (unsigned long) &rfc);
@@ -2478,7 +2478,10 @@ done:
 		case L2CAP_MODE_ERTM:
 			pi->remote_tx_win = rfc.txwin_size;
 			pi->remote_max_tx = rfc.max_transmit;
-			pi->max_pdu_size = rfc.max_pdu_size;
+			if (rfc.max_pdu_size > pi->conn->mtu - 10)
+				rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10);
+
+			pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
 
 			rfc.retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
 			rfc.monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
@@ -2491,7 +2494,10 @@ done:
 			break;
 
 		case L2CAP_MODE_STREAMING:
-			pi->max_pdu_size = rfc.max_pdu_size;
+			if (rfc.max_pdu_size > pi->conn->mtu - 10)
+				rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10);
+
+			pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
 
 			pi->conf_state |= L2CAP_CONF_MODE_DONE;
 
@@ -2570,11 +2576,10 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data,
 			pi->remote_tx_win   = rfc.txwin_size;
 			pi->retrans_timeout = rfc.retrans_timeout;
 			pi->monitor_timeout = rfc.monitor_timeout;
-			pi->max_pdu_size    = le16_to_cpu(rfc.max_pdu_size);
+			pi->mps    = le16_to_cpu(rfc.max_pdu_size);
 			break;
 		case L2CAP_MODE_STREAMING:
-			pi->max_pdu_size    = le16_to_cpu(rfc.max_pdu_size);
-			break;
+			pi->mps    = le16_to_cpu(rfc.max_pdu_size);
 		}
 	}
 
@@ -3758,7 +3763,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 		 * Receiver will miss it and start proper recovery
 		 * procedures and ask retransmission.
 		 */
-		if (len > L2CAP_DEFAULT_MAX_PDU_SIZE)
+		if (len > pi->mps)
 			goto drop;
 
 		if (l2cap_check_fcs(pi, skb))
@@ -3789,8 +3794,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 		if (pi->fcs == L2CAP_FCS_CRC16)
 			len -= 2;
 
-		if (len > L2CAP_DEFAULT_MAX_PDU_SIZE || len < 4
-				|| __is_sframe(control))
+		if (len > pi->mps || len < 4 || __is_sframe(control))
 			goto drop;
 
 		if (l2cap_check_fcs(pi, skb))
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 4/6] Bluetooth: Add le16 macro to Retransmission and Monitor Timeouts values
From: Gustavo F. Padovan @ 2010-03-26 19:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo
In-Reply-To: <1269631159-20750-3-git-send-email-padovan@profusion.mobi>

Fix a possible problem with Big Endian machines.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 net/bluetooth/l2cap.c |   14 ++++++++------
 1 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 4c98e3c..e6e2351 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -2483,8 +2483,10 @@ done:
 
 			pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
 
-			rfc.retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
-			rfc.monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
+			rfc.retrans_timeout =
+				le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
+			rfc.monitor_timeout =
+				le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
 
 			pi->conf_state |= L2CAP_CONF_MODE_DONE;
 
@@ -2574,8 +2576,8 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data,
 		switch (rfc.mode) {
 		case L2CAP_MODE_ERTM:
 			pi->remote_tx_win   = rfc.txwin_size;
-			pi->retrans_timeout = rfc.retrans_timeout;
-			pi->monitor_timeout = rfc.monitor_timeout;
+			pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
+			pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
 			pi->mps    = le16_to_cpu(rfc.max_pdu_size);
 			break;
 		case L2CAP_MODE_STREAMING:
@@ -2630,8 +2632,8 @@ done:
 	switch (rfc.mode) {
 	case L2CAP_MODE_ERTM:
 		pi->remote_tx_win   = rfc.txwin_size;
-		pi->retrans_timeout = rfc.retrans_timeout;
-		pi->monitor_timeout = rfc.monitor_timeout;
+		pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
+		pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
 		pi->mps    = le16_to_cpu(rfc.max_pdu_size);
 		break;
 	case L2CAP_MODE_STREAMING:
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 5/6] Bluetooth: Check the SDU size against the MTU value
From: Gustavo F. Padovan @ 2010-03-26 19:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo
In-Reply-To: <1269631159-20750-4-git-send-email-padovan@profusion.mobi>

If the SDU size is greater than the MTU something is wrong, so report
an error.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 net/bluetooth/l2cap.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index e6e2351..20c3f53 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3335,6 +3335,9 @@ static int l2cap_sar_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 co
 		pi->sdu_len = get_unaligned_le16(skb->data);
 		skb_pull(skb, 2);
 
+		if (pi->sdu_len > pi->imtu)
+			break;
+
 		pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
 		if (!pi->sdu) {
 			err = -ENOMEM;
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 6/6] Bluetooth: Close channel when an invalid ReqSeq is received
From: Gustavo F. Padovan @ 2010-03-26 19:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo
In-Reply-To: <1269631159-20750-5-git-send-email-padovan@profusion.mobi>

When we receive a frame With-Invalid-ReqSeq and
With-Invalid-ReqSeq-Retrans we shall close the channel.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 net/bluetooth/l2cap.c |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 20c3f53..b978782 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3460,6 +3460,13 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
 
 	BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
 
+	if ((req_seq - pi->expected_ack_seq) % 64 >
+			(pi->next_tx_seq - pi->expected_ack_seq) % 64) {
+		kfree_skb(skb);
+		l2cap_send_disconn_req(pi->conn, sk);
+		return 0;
+	}
+
 	if (L2CAP_CTRL_FINAL & rx_control) {
 		del_timer(&pi->monitor_timer);
 		if (pi->unacked_frames > 0)
@@ -3687,8 +3694,18 @@ static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
 
 static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
 {
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	u8 tx_seq = __get_reqseq(rx_control);
+
 	BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
 
+	if ((tx_seq - pi->expected_ack_seq) % 64 >
+			(pi->next_tx_seq - pi->expected_ack_seq) % 64) {
+		kfree_skb(skb);
+		l2cap_send_disconn_req(pi->conn, sk);
+		return 0;
+	}
+
 	if (L2CAP_CTRL_FINAL & rx_control) {
 		del_timer(&l2cap_pi(sk)->monitor_timer);
 		if (l2cap_pi(sk)->unacked_frames > 0)
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH v2 1/2] Report local services(UUIDs) through DBus
From: Francisco Alecrim @ 2010-03-26 22:54 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Francisco Alecrim

Include UUIDs field to method GetProperties(org.bluez.Adapter).
Applications can get local services(UUIDs) available through DBus.
---
 doc/adapter-api.txt |    5 +++++
 src/adapter.c       |   20 +++++++++++++++++++-
 src/sdpd-database.c |   20 ++++++++++++++++++++
 src/sdpd.h          |    1 +
 test/list-devices   |    3 +++
 5 files changed, 48 insertions(+), 1 deletions(-)

diff --git a/doc/adapter-api.txt b/doc/adapter-api.txt
index 48cab40..6098c76 100644
--- a/doc/adapter-api.txt
+++ b/doc/adapter-api.txt
@@ -270,3 +270,8 @@ Properties	string Address [readonly]
 		array{object} Devices [readonly]
 
 			List of device object paths.
+
+		array{string} UUIDs [readonly]
+
+			List of 128-bit UUIDs that represents the available
+			local services.
diff --git a/src/adapter.c b/src/adapter.c
index 5fd0736..2027484 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -37,6 +37,7 @@
 #include <bluetooth/hci.h>
 #include <bluetooth/hci_lib.h>
 #include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
@@ -1196,7 +1197,8 @@ static DBusMessage *get_properties(DBusConnection *conn,
 	DBusMessageIter dict;
 	char str[MAX_NAME_LENGTH + 1], srcaddr[18];
 	gboolean value;
-	char **devices;
+	char **devices, **uuids;
+	sdp_list_t *list, *lfree;
 	int i;
 	GSList *l;
 
@@ -1270,6 +1272,22 @@ static DBusMessage *get_properties(DBusConnection *conn,
 								&devices, i);
 	g_free(devices);
 
+	/* UUIDs */
+	list = sdp_get_record_list_by_device(&adapter->bdaddr);
+	lfree = list; /* keep head to prevent leak */
+	uuids = g_new0(char *, sdp_list_len(list) + 1);
+
+	for (i = 0; list; list = list->next, i++) {
+		sdp_record_t *rec = list->data;
+		uuids[i] = bt_uuid2string(&rec->svclass);
+	}
+	dict_append_array(&dict, "UUIDs", DBUS_TYPE_STRING, &uuids, i);
+
+	sdp_list_free(lfree, NULL);
+	for (i = 0; uuids[i]; i++)
+		g_free(uuids[i]);
+	g_free(uuids);
+
 	dbus_message_iter_close_container(&iter, &dict);
 
 	return reply;
diff --git a/src/sdpd-database.c b/src/sdpd-database.c
index 07a0bc3..8f99758 100644
--- a/src/sdpd-database.c
+++ b/src/sdpd-database.c
@@ -273,6 +273,26 @@ sdp_list_t *sdp_get_access_list(void)
 	return access_db;
 }
 
+sdp_list_t *sdp_get_record_list_by_device(const bdaddr_t *device)
+{
+	sdp_list_t *list, *acc;
+
+	acc = access_db;
+	list = NULL;
+	for (; acc; acc = acc->next) {
+		sdp_access_t *a = acc->data;
+		sdp_record_t *rec = sdp_record_find(a->handle);
+		if (!rec)
+			continue;
+
+		if (bacmp(&a->device, device) == 0 ||
+				bacmp(&a->device, BDADDR_ANY) == 0)
+			list = sdp_list_append(list, rec);
+	}
+
+	return list;
+}
+
 int sdp_check_access(uint32_t handle, bdaddr_t *device)
 {
 	sdp_list_t *p = access_locate(handle);
diff --git a/src/sdpd.h b/src/sdpd.h
index 1352a83..15e163b 100644
--- a/src/sdpd.h
+++ b/src/sdpd.h
@@ -79,6 +79,7 @@ void sdp_record_add(const bdaddr_t *device, sdp_record_t *rec);
 int sdp_record_remove(uint32_t handle);
 sdp_list_t *sdp_get_record_list(void);
 sdp_list_t *sdp_get_access_list(void);
+sdp_list_t *sdp_get_record_list_by_device(const bdaddr_t *device);
 int sdp_check_access(uint32_t handle, bdaddr_t *device);
 uint32_t sdp_next_handle(void);
 
diff --git a/test/list-devices b/test/list-devices
index 511d0cf..9120714 100755
--- a/test/list-devices
+++ b/test/list-devices
@@ -40,6 +40,9 @@ for i in adapter_list:
 		if (key == "Devices"):
 			list = extract_objects(value)
 			print "    %s = %s" % (key, list)
+		elif (key == "UUIDs"):
+			list = extract_uuids(value)
+			print "    %s = %s" % (key, list)
 		else:
 			print "    %s = %s" % (key, value)
 
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH v2 2/2] Emit Adapter.PropertyChanged when UUIDs change
From: Francisco Alecrim @ 2010-03-26 22:54 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Francisco Alecrim
In-Reply-To: <1269644076-10544-1-git-send-email-francisco.alecrim@openbossa.org>

Emitting Adapter.PropertyChanged signal when UUIDs change. D-Bus message
to inform that adapter properties changed.
---
 src/adapter.c       |   75 ++++++++++++++++++++++++++++++++++++++++++++------
 src/adapter.h       |    1 +
 src/sdpd-database.c |    3 ++
 3 files changed, 70 insertions(+), 9 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 2027484..884762f 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1034,6 +1034,71 @@ static void adapter_update_devices(struct btd_adapter *adapter)
 	g_free(devices);
 }
 
+static char **adapter_get_uuids(struct btd_adapter *adapter)
+{
+	char **uuids;
+	sdp_list_t *list, *lfree;
+	int i;
+
+	list = sdp_get_record_list_by_device(&adapter->bdaddr);
+	if (!list)
+		return NULL;
+
+	/* Keep head to prevent leak */
+	lfree = list;
+	uuids = g_new0(char *, sdp_list_len(list) + 1);
+	for (i = 0; list; list = list->next, i++) {
+		sdp_record_t *rec = list->data;
+		uuids[i] = bt_uuid2string(&rec->svclass);
+	}
+
+	sdp_list_free(lfree, NULL);
+	return uuids;
+}
+
+static void adapter_emit_uuids_updated(struct btd_adapter *adapter)
+{
+	char **uuids;
+	int i;
+
+	uuids = adapter_get_uuids(adapter);
+	if (!uuids)
+		return;
+
+	emit_array_property_changed(connection, adapter->path,
+			ADAPTER_INTERFACE, "UUIDs",
+			DBUS_TYPE_STRING, &uuids);
+
+	for (i = 0; uuids[i]; i++)
+		g_free(uuids[i]);
+	g_free(uuids);
+}
+
+void adapter_uuids_updated(const bdaddr_t *bdaddr)
+{
+	GSList *adapters;
+	struct btd_adapter *adapter;
+
+	if (bacmp(bdaddr, BDADDR_ANY) != 0) {
+		/* Only one adapter */
+		adapter = manager_find_adapter(bdaddr);
+		if (!adapter)
+			return;
+
+		adapter_emit_uuids_updated(adapter);
+
+		return;
+	}
+
+	/* Emit D-Bus msg to all adapters */
+	adapters = manager_get_adapters();
+
+	for (; adapters; adapters = adapters->next) {
+		adapter = adapters->data;
+		adapter_emit_uuids_updated(adapter);
+	}
+}
+
 struct btd_device *adapter_create_device(DBusConnection *conn,
 						struct btd_adapter *adapter,
 						const char *address)
@@ -1198,7 +1263,6 @@ static DBusMessage *get_properties(DBusConnection *conn,
 	char str[MAX_NAME_LENGTH + 1], srcaddr[18];
 	gboolean value;
 	char **devices, **uuids;
-	sdp_list_t *list, *lfree;
 	int i;
 	GSList *l;
 
@@ -1273,17 +1337,10 @@ static DBusMessage *get_properties(DBusConnection *conn,
 	g_free(devices);
 
 	/* UUIDs */
-	list = sdp_get_record_list_by_device(&adapter->bdaddr);
-	lfree = list; /* keep head to prevent leak */
-	uuids = g_new0(char *, sdp_list_len(list) + 1);
+	uuids = adapter_get_uuids(adapter);
 
-	for (i = 0; list; list = list->next, i++) {
-		sdp_record_t *rec = list->data;
-		uuids[i] = bt_uuid2string(&rec->svclass);
-	}
 	dict_append_array(&dict, "UUIDs", DBUS_TYPE_STRING, &uuids, i);
 
-	sdp_list_free(lfree, NULL);
 	for (i = 0; uuids[i]; i++)
 		g_free(uuids[i]);
 	g_free(uuids);
diff --git a/src/adapter.h b/src/adapter.h
index 9b4ce10..e453eff 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -121,6 +121,7 @@ void adapter_mode_changed(struct btd_adapter *adapter, uint8_t scan_mode);
 void adapter_setname_complete(bdaddr_t *local, uint8_t status);
 void adapter_update_tx_power(bdaddr_t *bdaddr, uint8_t status, void *ptr);
 void adapter_update_local_name(bdaddr_t *bdaddr, uint8_t status, void *ptr);
+void adapter_uuids_updated(const bdaddr_t *bdaddr);
 void adapter_set_class_complete(bdaddr_t *bdaddr, uint8_t status);
 
 struct agent *adapter_get_agent(struct btd_adapter *adapter);
diff --git a/src/sdpd-database.c b/src/sdpd-database.c
index 8f99758..97befe0 100644
--- a/src/sdpd-database.c
+++ b/src/sdpd-database.c
@@ -40,6 +40,7 @@
 
 #include "sdpd.h"
 #include "logging.h"
+#include "adapter.h"
 
 static sdp_list_t *service_db;
 static sdp_list_t *access_db;
@@ -183,6 +184,7 @@ void sdp_record_add(const bdaddr_t *device, sdp_record_t *rec)
 	dev->handle = rec->handle;
 
 	access_db = sdp_list_insert_sorted(access_db, dev, access_sort);
+	adapter_uuids_updated(device);
 }
 
 static sdp_list_t *record_locate(uint32_t handle)
@@ -253,6 +255,7 @@ int sdp_record_remove(uint32_t handle)
 		a = (sdp_access_t *) p->data;
 		if (a) {
 			access_db = sdp_list_remove(access_db, a);
+			adapter_uuids_updated(&a->device);
 			access_free(a);
 		}
 	}
-- 
1.6.3.3


^ permalink raw reply related

* Re: [PATCH] Fix display of last device classes in hciconfig
From: Daniel Abraham @ 2010-03-27  8:28 UTC (permalink / raw)
  To: Vinicius Gomes; +Cc: linux-bluetooth
In-Reply-To: <2a9506371003221436s1cf1b465r907f726797b4f251@mail.gmail.com>

> > ---
> >  tools/hciconfig.c |   30 ++++++++++++++++++++++++++----
> >  1 files changed, 26 insertions(+), 4 deletions(-)
> >
> > diff --git a/tools/hciconfig.c b/tools/hciconfig.c
> > index 3f687e0..c97ce44 100644
> > --- a/tools/hciconfig.c
> > +++ b/tools/hciconfig.c
> > @@ -645,8 +645,26 @@ static char *get_minor_device_name(int major, int minor)
> >                        return "Game";
> >                }
> >                break;
> > -       case 63:        /* uncategorised */
> > -               return "";
> 
> I think that the test for the "Uncategorised" (which seems to be
> misspelled in many places) device class would be better staying here,
> because the same code is used inside hcitool.c. Fixing there would be
> nice too.
> 
> Another thing, looks like this "case 63:" is wrong,  major device
> class is a 5 bit number, and the uncategorized device class is defined
> as 31. Looks like a legacy from ancient times ;-)

That's exactly why I changed it: the original check below whether to
enter this function ("if ((cls[1] & 0x1f) >= ...") meant <no. of
categories + 1> where +1 meant "Unrecognized", but this is mistaken as
you wrote.

I don't mind fixing it in "hcitool.c" as well, but see followup question
at the bottom.

> > +       case 9: /* health */
> > +               switch(minor) {
> > +               case 0:
> > +                       return "Undefined";
> > +               case 1:
> > +                       return "Blood Pressure Monitor";
> > +               case 2:
> > +                       return "Thermometer";
> > +               case 3:
> > +                       return "Weighing Scale";
> > +               case 4:
> > +                       return "Glucose Meter";
> > +               case 5:
> > +                       return "Pulse Oximeter";
> > +               case 6:
> > +                       return "Heart/Pulse Rate Monitor";
> > +               case 7:
> > +                       return "Health Data Display";
> > +               }
> > +               break;
> >        }
> >        return "Unknown (reserved) minor device class";
> >  }
> > @@ -668,7 +686,9 @@ static void cmd_class(int ctl, int hdev, char *opt)
> >                                        "Audio/Video",
> >                                        "Peripheral",
> >                                        "Imaging",
> > -                                       "Uncategorized" };
> > +                                       "Wearable",
> > +                                       "Toy",
> > +                                       "Health" };
> >        int s = hci_open_dev(hdev);
> >
> >        if (s < 0) {
> > @@ -706,7 +726,9 @@ static void cmd_class(int ctl, int hdev, char *opt)
> >                } else
> >                        printf("Unspecified");
> >                printf("\n\tDevice Class: ");
> > -               if ((cls[1] & 0x1f) >= sizeof(major_devices) / sizeof(*major_devices))
> > +               if (0x1f == cls[1])
> 
> This test is inverted, in BlueZ code we use the form: (variable
> operator constant)
> 
> > +                       printf("Uncategorized\n");
> > +               else if ((cls[1] & 0x1f) >= sizeof(major_devices) / sizeof(*major_devices))
> 
> See above.

Will fix both.

> >                        printf("Invalid Device Class!\n");
> >                else
> >                        printf("%s, %s\n", major_devices[cls[1] & 0x1f],
> > --
> > 1.6.6.1
> > --
> >
> 
> 
> Cheers,

Thanks for the comments! I'll send a fixed patch.

But here's a followup question: what's the convention for submitting a
change to a patch - another patch on top of it, or a full replacement
patch? As a reply to this thread, or as new message?


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).