Skip to contentSkip to conversation

Updated sco flow control feature

PATCH In review Fabien Chevalier 4 participants 15 messages Oct 12, 2006 – Oct 24, 2006

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Updated sco flow control feature

Marcel, Brad, Jose,

After a few very busy months at work i finally had the opportunity to go back to my bluez flow control patch i left in the middle of nowhere back in May. :-) You will find attached an updated version of the patch against 2.6.18-mh4, as well as a sample test program that shows the flow control stuff is really working.

Major changes compared to previous versions:
* Packets are queued in the core, and are dequeue from there.
* Flow control is achieved using high resolution timers. This means the code is really HZ independant, and things will even go better when the dyntick patch which has been in the air recently will be included in the mainline kernel.
* Fixed a stupid bug that would cause packets to be sent really too slowly when HZ was < 1000
* Should work with HZ = 100, 250, 1000, ... or whatever else. I tested with 250 HZ only for now.
* Wrote a test program, "headsettest". To run this program you will need an USB dongle that supports SCO, as well as a
headset. This program records your own voice for 30 seconds, then plays what it recorded in your ears for 30 seconds. Beware : Running it without the flow control patch is likely to crash your box !!
* The patch is cleaner. This is mainly due to the fact i am getting to a better understanding of Linux socket layer.

Random notes :
I tryed to enable number of completed packets events for synchronous connections, to get rid of all the timer stuff, however it didn't succeed.
This is achieved using hcitool command while there are no active connections :

tannat:/home/fchevalier/tmp/linux-2.6.18-mh4-fch# hcitool cmd 0x003 0X002F 0x01
< HCI Command: ogf 0x03, ocf 0x002f, plen 1
 01
Quoted 1 line

HCI Event: 0x0e plen 4

01 2F 0C 00

tannat:/home/fchevalier/tmp/linux-2.6.18-mh4-fch# hcitool cmd 0x003 0X002E
< HCI Command: ogf 0x03, ocf 0x002e, plen 0
Quoted 1 line

HCI Event: 0x0e plen 5

01 2E 0C 00 01

I tryed with 3 different USB dongles :
* one of them did not support this feature (old CSR 1.1 dongle)
* the two others supported the feature, however did never send any completed packets events for SCO packets (Broadcom BCM2035 and ISSC).

Due to this lack of working hardware i took the decision to stick with timers, even though it is not the best technical choice :-(

Limitations :
For now the flow control only works with CVSD air encoding
(ie 16 bit frames). If 8 bit frames are used, data will be sent twice too fast.

I am looking forward to your comments,

Cheers,

Fabien

home/fchevalier/tmp/linux-2.6.18-mh4-fch/include/net/bluetooth/hci.h renamed from home/fchevalier/tmp/linux-2.6.18-mh4/include/net/bluetooth/hci.h +7 -0
diff -rU 6 --exclude-from=kernelexcludes.txt --exclude='sco.*' /home/fchevalier/tmp/linux-2.6.18-mh4/include/net/bluetooth/hci.h /home/fchevalier/tmp/linux-2.6.18-mh4-fch/include/net/bluetooth/hci.h
@@ -764,12 +764,15 @@
 	__u32 sco_tx;
 	__u32 sco_rx;
 	__u32 byte_rx;
 	__u32 byte_tx;
 };
 
+/* Fields down there are mostly the same as hci_dev,
+   as this structure is meant to communicate info
+   to userspace */
 struct hci_dev_info {
 	__u16 dev_id;
 	char  name[8];
 
 	bdaddr_t bdaddr;
 
@@ -779,15 +782,19 @@
 	__u8  features[8];
 
 	__u32 pkt_type;
 	__u32 link_policy;
 	__u32 link_mode;
 
+	/* Maximum transmition unit for ACL packets */
 	__u16 acl_mtu;
+	/* Number of ACL packets the baseband is able to buffer */
 	__u16 acl_pkts;
+	/* Maximum transmition unit for SCO packets */
 	__u16 sco_mtu;
+	/* Number of SCO packets the baseband is able to buffer */
 	__u16 sco_pkts;
 
 	struct hci_dev_stats stat;
 };
 
 struct hci_conn_info {
home/fchevalier/tmp/linux-2.6.18-mh4-fch/include/net/bluetooth/hci_core.h renamed from home/fchevalier/tmp/linux-2.6.18-mh4/include/net/bluetooth/hci_core.h +28 -7
diff -rU 6 --exclude-from=kernelexcludes.txt --exclude='sco.*' /home/fchevalier/tmp/linux-2.6.18-mh4/include/net/bluetooth/hci_core.h /home/fchevalier/tmp/linux-2.6.18-mh4-fch/include/net/bluetooth/hci_core.h
@@ -22,12 +22,14 @@
    SOFTWARE IS DISCLAIMED.
 */
 
 #ifndef __HCI_CORE_H
 #define __HCI_CORE_H
 
+#include <linux/hrtimer.h>
+
 #include <net/bluetooth/hci.h>
 
 /* HCI upper protocols */
 #define HCI_PROTO_L2CAP	0
 #define HCI_PROTO_SCO	1
 
@@ -85,18 +87,24 @@
 	__u16		sniff_min_interval;
 	__u16		sniff_max_interval;
 
 	unsigned long	quirks;
 
 	atomic_t	cmd_cnt;
+	/* Number of available controller buffers for ACL packets */
 	unsigned int	acl_cnt;
-	unsigned int	sco_cnt;
+	/* Number of available controller buffers for SCO packets */
+	atomic_t	sco_cnt;
 
+	/* Maximum transmition unit for ACL packets */
 	unsigned int	acl_mtu;
+	/* Maximum transmition unit for SCO packets */
 	unsigned int	sco_mtu;
+	/* Maximum number of ACL packets the controller is able to buffer */
 	unsigned int	acl_pkts;
+	/* Maximum number of SCO packets the controller is able to buffer */
 	unsigned int	sco_pkts;
 
 	unsigned long	cmd_last_tx;
 	unsigned long	acl_last_tx;
 	unsigned long	sco_last_tx;
 
@@ -142,41 +150,51 @@
 };
 
 struct hci_conn {
 	struct list_head list;
 
 	atomic_t	 refcnt;
-	spinlock_t	 lock;
 
 	bdaddr_t	 dst;
 	__u16		 handle;
 	__u16		 state;
 	__u8             mode;
+ 	/* type : ACL or SCO */
 	__u8		 type;
 	__u8		 out;
 	__u8		 dev_class[3];
 	__u8             features[8];
 	__u16            interval;
 	__u16            link_policy;
 	__u32		 link_mode;
 	__u8             power_save;
 	unsigned long	 pend;
 
-	unsigned int	 sent;
-
-	struct sk_buff_head data_q;
-
+ 	/* sent represents the number of packets this connections
+            has "on the wire" : .... oh f.... there are no wire
+            with bluetooth. By on the wire, i mean packets that have been sent
+ 	   to the HCI device, and that are still in its buffers */
+	atomic_t	 sent;
+
+	struct sk_buff_head out_q;
+	/* This is only used for SCO for now */
+	void (*pkt_sent_cb)(struct hci_conn *conn);
+
+	/* tx timer : used only for SCO */
+	struct hrtimer tx_timer;
+	/* Disconnect timer */
 	struct timer_list disc_timer;
 	struct timer_list idle_timer;
 
 	struct work_struct work;
 
 	struct device	dev;
 
 	struct hci_dev	*hdev;
 	void		*l2cap_data;
+	/* private use for sco */
 	void		*sco_data;
 	void		*priv;
 
 	struct hci_conn	*link;
 };
 
@@ -610,13 +628,16 @@
 
 int hci_register_notifier(struct notifier_block *nb);
 int hci_unregister_notifier(struct notifier_block *nb);
 
 int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *param);
 int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
-int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
+int hci_send_sco(struct hci_conn *conn, 
+			struct sk_buff *skb, 
+			int sndbufsize, 
+			void (*send_complete_cb)(struct hci_conn *conn));
 
 void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 ogf, __u16 ocf);
 
 void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data);
 
 /* ----- HCI Sockets ----- */
home/fchevalier/tmp/linux-2.6.18-mh4-fch/net/bluetooth/hci_conn.c renamed from home/fchevalier/tmp/linux-2.6.18-mh4/net/bluetooth/hci_conn.c +9 -3
diff -rU 6 --exclude-from=kernelexcludes.txt --exclude='sco.*' /home/fchevalier/tmp/linux-2.6.18-mh4/net/bluetooth/hci_conn.c /home/fchevalier/tmp/linux-2.6.18-mh4-fch/net/bluetooth/hci_conn.c
@@ -179,23 +179,27 @@
 	conn->type   = type;
 	conn->mode   = HCI_CM_ACTIVE;
 	conn->state  = BT_OPEN;
 
 	conn->power_save = 1;
 
-	skb_queue_head_init(&conn->data_q);
+	conn->pkt_sent_cb = NULL;
+	skb_queue_head_init(&conn->out_q);
+
+	hrtimer_init(&conn->tx_timer, CLOCK_MONOTONIC, HRTIMER_NORESTART);
 
 	init_timer(&conn->disc_timer);
 	conn->disc_timer.function = hci_conn_timeout;
 	conn->disc_timer.data = (unsigned long) conn;
 
 	init_timer(&conn->idle_timer);
 	conn->idle_timer.function = hci_conn_idle;
 	conn->idle_timer.data = (unsigned long) conn;
 
 	atomic_set(&conn->refcnt, 0);
+	atomic_set(&conn->sent, 0);
 
 	hci_dev_hold(hdev);
 
 	tasklet_disable(&hdev->tx_task);
 
 	hci_conn_hash_add(hdev, conn);
@@ -216,38 +220,40 @@
 	BT_DBG("%s conn %p handle %d", hdev->name, conn, conn->handle);
 
 	del_timer(&conn->idle_timer);
 
 	del_timer(&conn->disc_timer);
 
+	hrtimer_cancel(&conn->tx_timer);
+
 	if (conn->type == SCO_LINK) {
 		struct hci_conn *acl = conn->link;
 		if (acl) {
 			acl->link = NULL;
 			hci_conn_put(acl);
 		}
 	} else {
 		struct hci_conn *sco = conn->link;
 		if (sco)
 			sco->link = NULL;
 
 		/* Unacked frames */
-		hdev->acl_cnt += conn->sent;
+		hdev->acl_cnt += atomic_read(&conn->sent);
 	}
 
 	tasklet_disable(&hdev->tx_task);
 
 	hci_conn_del_sysfs(conn);
 
 	hci_conn_hash_del(hdev, conn);
 	if (hdev->notify)
 		hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
 
 	tasklet_enable(&hdev->tx_task);
 
-	skb_queue_purge(&conn->data_q);
+	skb_queue_purge(&conn->out_q);
 
 	hci_dev_put(hdev);
 
 	/* will free via device release */
 	put_device(&conn->dev);
 
home/fchevalier/tmp/linux-2.6.18-mh4-fch/net/bluetooth/hci_core.c renamed from home/fchevalier/tmp/linux-2.6.18-mh4/net/bluetooth/hci_core.c +120 -50

310 lines not on this page · raw message

home/fchevalier/tmp/linux-2.6.18-mh4-fch/net/bluetooth/hci_event.c renamed from home/fchevalier/tmp/linux-2.6.18-mh4/net/bluetooth/hci_event.c +7 -7
diff -rU 6 --exclude-from=kernelexcludes.txt --exclude='sco.*' /home/fchevalier/tmp/linux-2.6.18-mh4/net/bluetooth/hci_event.c /home/fchevalier/tmp/linux-2.6.18-mh4-fch/net/bluetooth/hci_event.c
@@ -307,13 +307,13 @@
 
 	switch (ocf) {
 	case OCF_READ_LOCAL_VERSION:
 		lv = (struct hci_rp_read_loc_version *) skb->data;
 
 		if (lv->status) {
-			BT_DBG("%s READ_LOCAL_VERSION failed %d", hdev->name, lf->status);
+			BT_DBG("%s READ_LOCAL_VERSION failed %d", hdev->name, lv->status);
 			break;
 		}
 
 		hdev->hci_ver = lv->hci_ver;
 		hdev->hci_rev = btohs(lv->hci_rev);
 		hdev->manufacturer = btohs(lv->manufacturer);
@@ -369,13 +369,13 @@
 		if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
 			hdev->sco_mtu  = 64;
 			hdev->sco_pkts = 8;
 		}
 
 		hdev->acl_cnt = hdev->acl_pkts;
-		hdev->sco_cnt = hdev->sco_pkts;
+		atomic_set(&hdev->sco_cnt, hdev->sco_pkts);
 
 		BT_DBG("%s mtu: acl %d, sco %d max_pkt: acl %d, sco %d", hdev->name,
 			hdev->acl_mtu, hdev->sco_mtu, hdev->acl_pkts, hdev->sco_pkts);
 		break;
 
 	case OCF_READ_BD_ADDR:
@@ -858,21 +858,21 @@
 
 		handle = __le16_to_cpu(get_unaligned(ptr++));
 		count  = __le16_to_cpu(get_unaligned(ptr++));
 
 		conn = hci_conn_hash_lookup_handle(hdev, handle);
 		if (conn) {
-			conn->sent -= count;
+			atomic_sub(count, &conn->sent);
 
-			if (conn->type == SCO_LINK) {
-				if ((hdev->sco_cnt += count) > hdev->sco_pkts)
-					hdev->sco_cnt = hdev->sco_pkts;
-			} else {
+			if (conn->type == ACL_LINK) {
 				if ((hdev->acl_cnt += count) > hdev->acl_pkts)
 					hdev->acl_cnt = hdev->acl_pkts;
 			}
+			/* Note : we do not use the "number of completed packets" event
+			to increment hdev->sco_cnt, as this feature is only optionnally support
+			by bluetooth controllers. So there is no if branch for SCO_LINK packets */
 		}
 	}
 	hci_sched_tx(hdev);
 
 	tasklet_enable(&hdev->tx_task);
 }
home/fchevalier/tmp/linux-2.6.18-mh4-fch/include/net/bluetooth/sco.h renamed from home/fchevalier/tmp/linux-2.6.18-mh4/include/net/bluetooth/sco.h +3 -5
diff -rU 6 --exclude-from=kernelexcludes.txt --exclude='*hci*' --exclude='af_bluetooth.*' /home/fchevalier/tmp/linux-2.6.18-mh4/include/net/bluetooth/sco.h /home/fchevalier/tmp/linux-2.6.18-mh4-fch/include/net/bluetooth/sco.h
@@ -23,18 +23,13 @@
 */
 
 #ifndef __SCO_H
 #define __SCO_H
 
 /* SCO defaults */
-#define SCO_DEFAULT_MTU		500
-#define SCO_DEFAULT_FLUSH_TO	0xFFFF
-
 #define SCO_CONN_TIMEOUT	(HZ * 40)
-#define SCO_DISCONN_TIMEOUT	(HZ * 2)
-#define SCO_CONN_IDLE_TIMEOUT	(HZ * 60)
 
 /* SCO socket address */
 struct sockaddr_sco {
 	sa_family_t	sco_family;
 	bdaddr_t	sco_bdaddr;
 };
@@ -48,12 +43,15 @@
 #define SCO_CONNINFO	0x02
 struct sco_conninfo {
 	__u16 hci_handle;
 	__u8  dev_class[3];
 };
 
+#define SCO_TXBUFS	0x03
+#define SCO_RXBUFS	0x04
+
 /* ---- SCO connections ---- */
 struct sco_conn {
 	struct hci_conn	*hcon;
 
 	bdaddr_t 	*dst;
 	bdaddr_t 	*src;
home/fchevalier/tmp/linux-2.6.18-mh4-fch/net/bluetooth/sco.c renamed from home/fchevalier/tmp/linux-2.6.18-mh4/net/bluetooth/sco.c +143 -14

325 lines not on this page · raw message

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
#include <poll.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/poll.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/sco.h>
#include <bluetooth/rfcomm.h>

static int rfcomm_connect(bdaddr_t * dst, uint8_t channel)

{
	struct sockaddr_rc addr;
	int s;

	if ((s = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {
		return -1;
	}

	memset(&addr, 0, sizeof(addr));
	addr.rc_family = AF_BLUETOOTH;
	bacpy(&addr.rc_bdaddr, dst);
	addr.rc_channel = channel;
	if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
		close(s);
		return -1;
	}

	return s;
}

static int sco_connect(bdaddr_t * dst, uint16_t * handle,

		       uint16_t * mtu)
{
	struct sockaddr_sco addr;
	struct sco_conninfo conn;
	struct sco_options opts;
	int s;
	unsigned int size;

	if ((s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO)) < 0) {
		return -1;
	}

	memset(&addr, 0, sizeof(addr));
	addr.sco_family = AF_BLUETOOTH;
	bacpy(&addr.sco_bdaddr, dst);
	if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
		close(s);
		return -1;
	}

	size = sizeof(conn);
	if (getsockopt(s, SOL_SCO, SCO_CONNINFO, &conn, &size) < 0) {
		close(s);
		return -1;
	}

	size = sizeof(opts);
	if (getsockopt(s, SOL_SCO, SCO_OPTIONS, &opts, &size) < 0) {
		close(s);
		return -1;
	}

	if (handle)
		*handle = conn.hci_handle;

	if (mtu)
		*mtu = opts.mtu;

	return s;
}

#define PKT_SIZE 48

int main(int argc, char **argv)

{
	bdaddr_t remote;
	int rfcomm_socket;
	int sco_socket;
	int res;
	int channel;
	char buff[1024*1024];
	int i;
	struct pollfd pfd;

	if(argc != 3) {
		printf("usage: headsettest bdaddr rfcomm_channel\n");		
		printf("bdaddr = headet bd address\n");
		printf("rfcomm_channel = rfcomm channel used for headset control\n");		
		exit(1);
	}
	
	str2ba(argv[1], &remote);
	channel = atoi(argv[2]);
	
	rfcomm_socket = rfcomm_connect(&remote, channel);
	assert(rfcomm_socket != -1);
	res = write(rfcomm_socket, "RING\r\n", 6); 	
	assert(res == 6);
	memset(buff, 0, sizeof(buff));
	printf("RFCOMM control channel opened.\n");
	sco_socket = sco_connect(&remote, 0, 0);
	assert(res > 0);
	printf("SCO connected.\n");

	printf("Recording your own voice for 30 seconds, please speak loudly and clearly :-)\n");

	/* Reading 10000 packets*/
	
	pfd.fd = sco_socket;
	pfd.events = POLLIN;	
	
	for(i = 0; i < 10000; i++) {
		assert(poll(&pfd, 1 , -1) == 1);
		assert(pfd.revents & POLLIN);
		res = read(sco_socket, buff + i * PKT_SIZE, PKT_SIZE);
		assert(res > 0);
		printf(".");
		fflush(stdout);
	}

	printf("\nNow playing what has been recorded\n");

	/* Reading 3333 packets*/
	pfd.fd = sco_socket;
	pfd.events = POLLOUT;	
	for(i = 0; i < 10000; i++) {
		assert(poll(&pfd, 1, -1) == 1);
		assert(pfd.revents & POLLOUT);
		res = write(sco_socket, buff + i * PKT_SIZE, PKT_SIZE);
		assert(res > 0);
		printf(".");
		fflush(stdout);
	}
	
	return 0;
}

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel

#1 lore raw

Hi, Fabien,

I'll take a look at your patch. I've been working on one myself. As I mentioned earlier, I've taken a different approach that works well. I use the standard HCI synchronous flow control. Now since USB dongles don't generate this, I have the hci_usb_tx_complete generate a HCI_EV_NUM_COMP_PKTS for transfer. Then the existing system works fine. No timers are necessary. Only a small change to hci_sched_sco in hci_core.c was necessary.

The problem I'm running into now is with dynamic isochronous allocation. By default my driver sets interface 1 to use alternative 0 (i.e. no bandwidth). When the SCO is opened, this is changed to alternative 2. All this works great. It's when the SCO is closed or a second SCO is opened that causes problems as the bandwidth needs to be reallocated.

Jose

Quoted 60 lines · Chevalier

Marcel, Brad, Jose,

After a few very busy months at work i finally had the opportunity to go back to my bluez flow control patch i left in the middle of nowhere back in May. :-)
You will find attached an updated version of the patch against 2.6.18-mh4, as well as a sample test program that shows the flow control stuff is really working.

Major changes compared to previous versions:
* Packets are queued in the core, and are dequeue from there.
* Flow control is achieved using high resolution timers. This means the code is really HZ independant, and things will even go better when the dyntick patch which has been in the air recently will be included in the mainline kernel.
* Fixed a stupid bug that would cause packets to be sent really too slowly when HZ was < 1000
* Should work with HZ = 100, 250, 1000, ... or whatever else. I tested with 250 HZ only for now.
* Wrote a test program, "headsettest". To run this program you will need an USB dongle that supports SCO, as well as a
headset. This program records your own voice for 30 seconds, then plays what it recorded in your ears for 30 seconds. Beware : Running it without the flow control patch is likely to crash your box !!
* The patch is cleaner. This is mainly due to the fact i am getting to a better understanding of Linux socket layer.

Random notes :
I tryed to enable number of completed packets events for synchronous connections,
to get rid of all the timer stuff, however it didn't succeed. This is achieved using hcitool command while there are no active connections :

tannat:/home/fchevalier/tmp/linux-2.6.18-mh4-fch# hcitool cmd 0x003 
0X002F 0x01
< HCI Command: ogf 0x03, ocf 0x002f, plen 1
 01
Quoted 1 line

HCI Event: 0x0e plen 4

01 2F 0C 00

tannat:/home/fchevalier/tmp/linux-2.6.18-mh4-fch# hcitool cmd 0x003 
0X002E
< HCI Command: ogf 0x03, ocf 0x002e, plen 0
Quoted 1 line

HCI Event: 0x0e plen 5

01 2E 0C 00 01

I tryed with 3 different USB dongles :
* one of them did not support this feature (old CSR 1.1 dongle)
* the two others supported the feature, however did never send any completed packets events for SCO packets (Broadcom BCM2035 and ISSC).

Due to this lack of working hardware i took the decision to stick with timers, even though it is not the best technical choice :-(

Limitations :
For now the flow control only works with CVSD air encoding (ie 16 bit frames). If 8 bit frames are used, data will be sent twice too fast.

Quoted 5 lines

I am looking forward to your comments,

Cheers,

Fabien

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel

#2 lore raw

Jose

Quoted 6 lines

The problem I'm running into now is with dynamic isochronous allocation. By default my driver sets interface 1 to use alternative 0 (i.e. no bandwidth). When the SCO is opened, this is changed to alternative 2. All this works great. It's when the SCO is closed or a second SCO is opened that causes problems as the bandwidth needs to be reallocated.

You're encountering something we need to address anyway for multiple sco connections. I haven't had a very clear understanding of the alt setting. It seems that we were setting it to 2 and leaving it there but maybe it is actually going between 0 and 2 dynamically.

What is a decent uart-connected csr platform to test sco on? I have a gumstix and a csr module but I'm still struggling the specs at
http://www.semiconductorstore.com/pdf/Bluegiga/esite_wt12.pdf

Brad

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel

#3 lore raw

Hi Brad,
please find below a few additionnal notes

Quoted 9 lines

Jose

Quoted 6 lines

The problem I'm running into now is with dynamic isochronous allocation. By default my driver sets interface 1 to use alternative 0 (i.e. no bandwidth). When the SCO is opened, this is changed to alternative 2. All this works great. It's when the SCO is closed or a second SCO is opened that causes problems as the bandwidth needs to be reallocated.

Quoted 5 lines

You're encountering something we need to address anyway for multiple sco connections. I haven't had a very clear understanding of the alt setting. It seems that we were setting it to 2 and leaving it there but maybe it is actually going between 0 and 2 dynamically.

Alternate settings are used to have an isochronous USB endpoint working at the appropriate bandwidth. Isochronous endpoints in USB have a dedicated allocated bandwidth, so the bluetooth stack should select the proper alternate setting, given the number of SCO connections opened, and the bandwidth allocated to each one.

The table below sums up which alternate configuration must be used given the number of sco channels in use.

Nr of 8 bits SCO Nr of 16 bits SCO Alt. config. to use
0 0 0
1 0 1
2 0 2
3 0 3
0 1 2
0 2 4
0 3 5

Cheers,

Fabien

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel

#4 lore raw
In reply to Jose Vasconcellos

Hello Jose,

Quoted 9 lines

Hi, Fabien,

I'll take a look at your patch. I've been working on one myself. As I mentioned earlier, I've taken a different approach that works well. I use the standard HCI synchronous flow control. Now since USB dongles don't generate this, I have the hci_usb_tx_complete generate a HCI_EV_NUM_COMP_PKTS for transfer. Then the existing system works fine. No timers are necessary. Only a small change to hci_sched_sco in hci_core.c was necessary.

Yes this will work. The only issue i see with this approach is that it is hci USB centric. This works with USB because there is a dedicated USB channel to send SCO packets, and the bandwidth of this channel is precisely the one of the SCO stream. So when the USB controller acknowledges the transmitted packet, you know you can precisely send the next one, which is great. :-)

Now, for RS232 hci devices, there is only one physical channel, the RS232 link, which is shared for SCO/ACL/CMD packets. The bandwidth is typically as high as 921 kbit/s. This means when the R232 controller acknowledges the SCO packet, you have to wait a bit to send the next SCO packet, and thus rely a way or another on a timer. It's too bad, but i see no other way for now :-(

Thus, if we take into account the fact completed packets events are not send by bt controllers, and that the flow control stuff should work whatever controller driver is, it think we have to rely on timers ;-)

Quoted 7 lines

The problem I'm running into now is with dynamic isochronous allocation. By default my driver sets interface 1 to use alternative 0 (i.e. no bandwidth). When the SCO is opened, this is changed to alternative 2. All this works great. It's when the SCO is closed or a second SCO is opened that causes problems as the bandwidth needs to be reallocated.

Yes, i agree with you, this is something that needs to be handled properly. It could be done by adding some bits to the core so that it notifies the driver when a SCO connection is opened/closed, so that the usb-hci driver can select the right configuration. There already exists a notify function in the hci driver interface, maybe it could be extended to achieve this ?
I'm not gonna work on this however, as i still have some work to do on the sco alsa plugin next :-)

Cheers,

Fabien

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel

#5 lore raw
Quoted 28 lines · Fabien Chevalier

Hello Jose,

Quoted 10 lines

Hi, Fabien,

I'll take a look at your patch. I've been working on one myself. As I mentioned earlier, I've taken a different approach that works well. I use the standard HCI synchronous flow control. Now since USB dongles don't generate this, I have the hci_usb_tx_complete generate a HCI_EV_NUM_COMP_PKTS for transfer. Then the existing system works fine. No timers are necessary. Only a small change to hci_sched_sco in hci_core.c was necessary.

Yes this will work. The only issue i see with this approach is that it is hci USB centric. This works with USB because there is a dedicated USB channel to send SCO packets, and the bandwidth of this channel is precisely the one of the SCO stream. So when the USB controller acknowledges the transmitted packet, you know you can precisely send the next one, which is great. :-)

Now, for RS232 hci devices, there is only one physical channel, the RS232 link, which is shared for SCO/ACL/CMD packets. The bandwidth is typically as high as 921 kbit/s. This means when the R232 controller acknowledges the SCO packet, you have to wait a bit to send the next SCO packet, and thus rely a way or another on a timer. It's too bad, but i see no other way for now :-(

Quoted 5 lines

Thus, if we take into account the fact completed packets events are not send by bt controllers, and that the flow control stuff should work whatever controller driver is, it think we have to rely on timers ;-)

Hi Fabien,

So your issue is supporting synchronous channels on the UART interface. I think it's best to enable synchronous flow control. and have the hci_uart manage the transmit queue to minimize delay. This means that hci_uart can peek at the HCI_EV_NUM_COMP_PKTS received to determine if another synchronous packet needs to be sent.

Regards,

Jose

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel

#6 lore raw

Hi Jose,

Please see my comments below.

Quoted 4 lines

Hi Fabien,

So your issue is supporting synchronous channels on the UART interface.

Well, i would be better if this flow control issue was solved once and for all, for all kind of interfaces :-)

I think it's best to enable synchronous flow control.

Do you know if this feature is supported by bt controllers on the UART interface?

Cheers,

Fabien

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel

#7 lore raw
Quoted 13 lines · Fabien Chevalier

Hi Jose,

Please see my comments below.

Quoted 5 lines

Hi Fabien,

So your issue is supporting synchronous channels on the UART interface.

Well, i would be better if this flow control issue was solved once and for all, for all kind of interfaces :-)

Quoted 8 lines

I think it's best to enable synchronous flow control.

Do you know if this feature is supported by bt controllers on the UART interface?

Cheers,

Fabien

Hi Fabien,

It's my understanding from reading the IEEE spec that Bluetooth compliant devices with UART interface must support synchronous flow control if they support SCO channels. But I have no experience with such devices. Has anyone else used such a device?

Attached is a small patch to hci_core.c and hci_usb.c that make the SCO flow control work. This seems to work well for one SCO. I've also included a modified hstest.c from bluez-utils/test.

For UART interfaces and possibly for multiple SCO, maybe some additional changes are required. One issue is that only one queue is used to communicate with the hci driver. It would be much better if the synchronous traffic had a separate queue; this guarantees that the driver can easily access the next SCO packet to transmit.

Jose

drivers/bluetooth/hci_usb.c +26 -0
diff -rU 6 linux.source.2.6.15-orig/drivers/bluetooth/hci_usb.c linux.source.2.6.15/drivers/bluetooth/hci_usb.c
@@ -771,23 +771,49 @@
 			_urb->type, err);
 
 unlock:
 	read_unlock(&husb->completion_lock);
 }
 
+static inline int __sco_notify(struct hci_dev *hdev, void *handlep)
+{
+	struct sk_buff *skb;
+	unsigned char *p;
+	static const unsigned char data[] = {0x13, 0x05, 0x01, 0x00, 0x00, 0x01, 0x00};
+
+	skb = bt_skb_alloc(sizeof data, GFP_ATOMIC);
+	if (!skb) {
+		BT_ERR("%s no memory for the packet", hdev->name);
+		return -ENOMEM;
+	}
+	skb->dev = (void *) hdev;
+
+	BT_DBG("sco_notify handle: %x", *((__le16 *) handlep));
+	/* add handle to data */
+	p = skb_put(skb, sizeof(data));
+	memcpy(p, data, sizeof(data));
+	memcpy(p+3, handlep, sizeof(__le16));
+
+	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
+	hci_recv_frame(skb);
+	return 0;
+}
+
 static void hci_usb_tx_complete(struct urb *urb, struct pt_regs *regs)
 {
 	struct _urb *_urb = container_of(urb, struct _urb, urb);
 	struct hci_usb *husb = (void *) urb->context;
 	struct hci_dev *hdev = husb->hdev;
 
 	BT_DBG("%s urb %p status %d flags %x", hdev->name, urb,
 			urb->status, urb->transfer_flags);
 
 	atomic_dec(__pending_tx(husb, _urb->type));
 
+	if (_urb->type == HCI_SCODATA_PKT)
+		__sco_notify(hdev, ((struct sk_buff *)_urb->priv)->data);
 	urb->transfer_buffer = NULL;
 	kfree_skb((struct sk_buff *) _urb->priv);
 
 	if (!test_bit(HCI_RUNNING, &hdev->flags))
 		return;
 
net/bluetooth/hci_core.c +1 -2
diff -rU 6 linux.source.2.6.15-orig/net/bluetooth/hci_core.c linux.source.2.6.15/net/bluetooth/hci_core.c
@@ -1242,14 +1242,13 @@
 	while (hdev->sco_cnt && (conn = hci_low_sent(hdev, SCO_LINK, &quote))) {
 		while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
 			BT_DBG("skb %p len %d", skb, skb->len);
 			hci_send_frame(skb);
 
 			conn->sent++;
-			if (conn->sent == ~0)
-				conn->sent = 0;
+			hdev->sco_cnt--;
 		}
 	}
 }
 
 static void hci_tx_task(unsigned long arg)
 {

/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2002-2006 Marcel Holtmann <[email protected]> *
*

 *  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

*
*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <termios.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/socket.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/sco.h>
#include <bluetooth/rfcomm.h>

static volatile int terminate = 0;

static void sig_term(int sig) {
	terminate = 1;
}

static int rfcomm_connect(bdaddr_t *src, bdaddr_t *dst, uint8_t channel)

{
	struct sockaddr_rc addr;
	int s;

	if ((s = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {
		return -1;
	}

	memset(&addr, 0, sizeof(addr));
	addr.rc_family = AF_BLUETOOTH;
	bacpy(&addr.rc_bdaddr, src);
	addr.rc_channel = 0;
	if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
		close(s);
		return -1;
	}

	memset(&addr, 0, sizeof(addr));
	addr.rc_family = AF_BLUETOOTH;
	bacpy(&addr.rc_bdaddr, dst);
	addr.rc_channel = channel;
	if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0 ){
		close(s);
		return -1;
	}

	return s;
}

static int sco_connect(bdaddr_t *src, bdaddr_t *dst, uint16_t *handle, uint16_t *mtu)

{
	struct sockaddr_sco addr;
	struct sco_conninfo conn;
	struct sco_options opts;
	socklen_t size;
	int s;
	struct linger l;

	if ((s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO)) < 0) {
		return -1;
	}

	memset(&addr, 0, sizeof(addr));
	addr.sco_family = AF_BLUETOOTH;
	bacpy(&addr.sco_bdaddr, src);

	if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
		close(s);
		return -1;
	}

	memset(&addr, 0, sizeof(addr));
	addr.sco_family = AF_BLUETOOTH;
	bacpy(&addr.sco_bdaddr, dst);

	if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0 ){
		close(s);
		return -1;
	}

	l.l_onoff = 1;
	l.l_linger = 5;
	setsockopt(s, SOL_SOCKET, SO_LINGER, &l, sizeof l);

	memset(&conn, 0, sizeof(conn));
	size = sizeof(conn);

	if (getsockopt(s, SOL_SCO, SCO_CONNINFO, &conn, &size) < 0) {
		close(s);
		return -1;
	}

	memset(&opts, 0, sizeof(opts));
	size = sizeof(opts);

	if (getsockopt(s, SOL_SCO, SCO_OPTIONS, &opts, &size) < 0) {
		close(s);
		return -1;
	}

	if (handle)
		*handle = conn.hci_handle;

	if (mtu)
		*mtu = opts.mtu;

	return s;
}

static void usage(void)

{
	printf("Usage:\n"
		"\thstest play   <file> <bdaddr> [channel]\n"
		"\thstest record <file> <bdaddr> [channel]\n");
}

#define PLAY 1
#define RECORD 2

int main(int argc, char *argv[])

{
	struct sigaction sa;

	fd_set rfds, wfds, efds;
	struct timeval timeout;
	unsigned char buf[2048], *p;
	int maxfd, sel, rlen, wlen;

	bdaddr_t local;
	bdaddr_t bdaddr;
	uint8_t channel;

	char *filename;
	mode_t filemode;
	int err, mode = 0;
	int dd, rd, sd, fd;
	uint16_t sco_handle, sco_mtu, vs;
	int stream = 0;

	switch (argc) {
	case 4:
		str2ba(argv[3], &bdaddr);
		channel = 6;
		break;
	case 5:
		str2ba(argv[3], &bdaddr);
		channel = atoi(argv[4]);
		break;
	default:
		usage();
		exit(-1);
	}

	if (strncmp(argv[1], "play", 4) == 0) {
		mode = PLAY;
		filemode = O_RDONLY;
	} else if (strncmp(argv[1], "rec", 3) == 0) {
		mode = RECORD;
		filemode = O_WRONLY | O_CREAT | O_TRUNC;
	} else {
		usage();
		exit(-1);
	}

	filename = argv[2];

	hci_devba(0, &local);
#if 0
	dd = hci_open_dev(0);
	hci_read_voice_setting(dd, &vs, 1000);
	vs = htobs(vs);
	fprintf(stderr, "Voice setting: 0x%04x\n", vs);
	close(dd);
	if (vs != 0x0060) {
		fprintf(stderr, "The voice setting must be 0x0060\n");
		//return -1;
	}
#endif
	if (strcmp(filename, "-") == 0) {
		switch (mode) {
		case PLAY:
			fd = 0;
			break;
		case RECORD:
			fd = 1;
			break;
		default:
			return -1;
		}
	} else {
		if ((fd = open(filename, filemode)) < 0) {
			perror("Can't open input/output file");
			return -1;
		}
	}

	memset(&sa, 0, sizeof(sa));
	sa.sa_flags = SA_NOCLDSTOP;
	sa.sa_handler = sig_term;
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGINT,  &sa, NULL);

	sa.sa_handler = SIG_IGN;
	sigaction(SIGCHLD, &sa, NULL);
	sigaction(SIGPIPE, &sa, NULL);

	if ((rd = rfcomm_connect(&local, &bdaddr, channel)) < 0) {
		perror("Can't connect RFCOMM channel");
		return -1;
	}

	fprintf(stderr, "RFCOMM channel connected\n");

	if ((sd = sco_connect(&local, &bdaddr, &sco_handle, &sco_mtu)) < 0) {
		perror("Can't connect SCO audio channel");
		close(rd);
		return -1;
	}

	sco_mtu = 48;
	fprintf(stderr, "SCO audio channel connected (handle %d, mtu %d)\n", sco_handle, sco_mtu);

	if (mode == RECORD)
		err = write(rd, "RING\r\n", 6);

	maxfd = (rd > sd) ? rd : sd;

	while (!terminate) {

		FD_ZERO(&rfds);
		FD_ZERO(&wfds);
		FD_ZERO(&efds);
		FD_SET(rd, &rfds);
		if (stream) {
			if (mode == RECORD)
				FD_SET(sd, &rfds);
			else
				FD_SET(sd, &wfds);
		}
		FD_SET(rd, &efds);
		FD_SET(sd, &efds);

		timeout.tv_sec = 0;
		timeout.tv_usec = 1000000;

		if ((sel = select(maxfd + 1, &rfds, &wfds, &efds, &timeout)) > 0) {

			/* communications errors */
			if (FD_ISSET(sd, &efds)) {
				fprintf(stderr, "SCO error\n");
				break;
			}
			if (FD_ISSET(rd, &efds)) {
				fprintf(stderr, "RFCOMM error\n");
				break;
			}

			/* RFCOMM channel */
			if (FD_ISSET(rd, &rfds)) {
				rlen = read(rd, buf, sizeof(buf));
				if (rlen > 0) {
					if (strcmp((char*)buf,"AT+CKPD=200\r") == 0) {
						stream = 1;
						fprintf(stderr, "SCO started\n");
					}
					if (rlen < sizeof(buf))
						buf[rlen++] = '\n';
					fwrite(buf, 1, rlen, stderr);
					wlen = write(rd, "OK\r\n", 4);
				}
			}

			/* play samples */
			if (FD_ISSET(sd, &wfds)) {
				rlen = read(fd, buf, sco_mtu);
				if (rlen <= 0) {
					if (rlen < 0)
						perror("Unable to read file");
					break;
				}

				wlen = 0; 
				p = buf;
				while (rlen > sco_mtu) {
					wlen = write(sd, p, sco_mtu);
					rlen -= sco_mtu;
					p += sco_mtu;
				}
				wlen = write(sd, p, rlen);
			}

			/* record samples */
			if (FD_ISSET(sd, &rfds)) {
				rlen = read(sd, buf, sizeof(buf));
				if (rlen > 0)
					wlen = write(fd, buf, rlen);
			}

		}

	}

	close(fd);

	close(sd);
	sleep(1);
	close(rd);

	return 0;
}

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel

#8 lore raw

Hi Jose,

Quoted 3 lines

Hi Fabien,

It's my understanding from reading the IEEE spec that Bluetooth

Could you point me to what you refer to ?
I had a look to the following document
http://www.bluetooth.com/NR/rdonlyres/24C24181-5B5D-4566-BB4F-D4C302910B9D/1766/Volume4_SPEC.pdf
which describes bt transport over uart, but did not find any mention of synchronous flow control beeing mandatory :-(

Quoted 3 lines

compliant devices with UART interface must support synchronous flow control if they support SCO channels. But I have no experience with such devices. Has anyone else used such a device?

I don't either :-(

Cheers,

Fabien

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel

#9 lore raw

Hi Fabien,

You need to get the IEEE 802.15.1 specification. Go to here:
http://standards.ieee.org/getieee802/802.15.html
Section 11.4 talks about HCI flow control. I don't see that this facility is optional. In the case of USB, it's different because another mechanism exists for flow control.

Has anyone every used SCO with a UART link?

Jose

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel

#10 lore raw

Hello Jose,

The documents i used as reference are the ones from bluetooth SIG. I don't know who copied the others, but they are closely similar to the one from IEEE :-)
Concerning SCO flow control over UART link, it is stated nowhere it is mandatory nor optionnal. :-(

However, having a look at the Bluetooth 2.0+EDR spec (available on www.bluetooth.com), section 6.26 "Supported commands" describes the bitmask that lists the supported hci commands for a given implementation, stating that *It is implied that if a command is listed as supported, the feature underlying that command is also supported.*

And guess what ?.... in the bitmask there is a bit for the "Write Synchronous flow control enable" command. ;-)

*** cut here ***
0 Read Hold Mode Activity
1 Write Hold Mode Activity
2 Read Transmit Power Level
3 Read Synchronous Flow Control Enable
10
4 Write Synchronous Flow Control Enable
5 Set Host Controller To Host Flow Control
6 Host Buffer Size
7 Host Number Of Completed Packets
*** cut here ***

Having analysed all these informations, my guess is that it is synchronous flow control is 'optionnal', even for uart links.

Cheers,

Fabien

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel

#11 lore raw

Hi Fabien,

Very interesting. I interpreted this to mean that if synchronous channels are supported, then synchronous flow control is required. Some form of feedback from the HCI device is required to main synchronization. If you use timers you run occasional the risk of getting out of sync.

All this speculation can be clarified if someone with an actual UART dongle can speak up. The patch that I posted should work as long as the device implements synchronous flow control. Maybe the solution is to not support SCO on UART until someone can take responsibility.

One thing is clear, the current code is wrong. It allows application programs to easily cause Linux to panic. I'm very surprised that this condition has been allowed.

BTW, the IEEE spec is the base for bluetooth.

Jose

Quoted 29 lines · Fabien Chevalier

Hello Jose,

The documents i used as reference are the ones from bluetooth SIG. I don't know who copied the others, but they are closely similar to the one from IEEE :-)
Concerning SCO flow control over UART link, it is stated nowhere it is mandatory nor optionnal. :-(

However, having a look at the Bluetooth 2.0+EDR spec (available on www.bluetooth.com), section 6.26 "Supported commands" describes the bitmask that lists the supported hci commands for a given implementation, stating that *It is implied that if a command is listed as supported, the feature underlying that command is also supported.*

And guess what ?.... in the bitmask there is a bit for the "Write Synchronous flow control enable" command. ;-)

*** cut here ***
0 Read Hold Mode Activity
1 Write Hold Mode Activity
2 Read Transmit Power Level
3 Read Synchronous Flow Control Enable
10
4 Write Synchronous Flow Control Enable
5 Set Host Controller To Host Flow Control
6 Host Buffer Size
7 Host Number Of Completed Packets
*** cut here ***

Quoted 7 lines

Having analysed all these informations, my guess is that it is synchronous flow control is 'optionnal', even for uart links.

Cheers,

Fabien

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel

maintainer
#12 lore raw

Hi Jose,

Quoted 5 lines

Very interesting. I interpreted this to mean that if synchronous channels are supported, then synchronous flow control is required. Some form of feedback from the HCI device is required to main synchronization. If you use timers you run occasional the risk of getting out of sync.

that shouldn't be such a problem. It is only audio data.

Quoted 5 lines

All this speculation can be clarified if someone with an actual UART dongle can speak up. The patch that I posted should work as long as the device implements synchronous flow control. Maybe the solution is to not support SCO on UART until someone can take responsibility.

I have a couple of UART based development kits at home and I can actually test it. However you shouldn't think about the actual transport at all. This is the job of the driver and not the Bluetooth core. So it must work with SCO flow control enabled and disabled.

Quoted 1 line

BTW, the IEEE spec is the base for bluetooth.

That is wrong. The IEEE specification was written based on the Bluetooth specification. What gets released by the Bluetooth SIG at bluetooth.com is the specification that counts.

Regards

Marcel

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel

#13 lore raw
In reply to Fabien Chevalier

Fabien

Quoted 3 lines

You will find attached an updated version of the patch against 2.6.18-mh4, as well as a sample test program that shows the flow control stuff is really working.

I'm glad you're hacking at this still and I hope we are converging on something that everyone agrees on.

Quoted 4 lines

Random notes :
I tryed to enable number of completed packets events for synchronous connections,
to get rid of all the timer stuff, however it didn't succeed.

How does this idea that didn't work out compare to the approach Jose is discussing? From what I've seen they both seem to be considering the problem at a lower level.

FYI, on the topic of plugins... I am writing up new documentation (using the ubuntu wiki for now... don't hate me). I'm moving emphasis away from the old "btsco" daemon method for sco audio. The sco alsa plugin detail in the wiki is only a placeholder currently but I want to flesh it out soon.

https://help.ubuntu.com/community/BluetoothAudio

Brad

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel

#14 lore raw
In reply to Fabien Chevalier

Fabien

I would like to better document how to try this patch and use it with the alsa sco plugin. I've started it in

https://help.ubuntu.com/community/BluetoothAudio

Is the sco plugin in our cvs current and will it enable your flow control?

Brad

Quoted 17 lines

After a few very busy months at work i finally had the opportunity to go back to my bluez flow control patch i left in the middle of nowhere back in May. :-)
You will find attached an updated version of the patch against 2.6.18-mh4, as well as a sample test program that shows the flow control stuff is really working.

Major changes compared to previous versions:
* Packets are queued in the core, and are dequeue from there.
* Flow control is achieved using high resolution timers. This means the code is really HZ independant, and things will even go better when the dyntick patch which has been in the air recently will be included in the mainline kernel.
* Fixed a stupid bug that would cause packets to be sent really too slowly when HZ was < 1000
* Should work with HZ = 100, 250, 1000, ... or whatever else. I tested with 250 HZ only for now.

Quoted 8 lines

* Wrote a test program, "headsettest". To run this program you will need an USB dongle that supports SCO, as well as a
headset. This program records your own voice for 30 seconds, then plays what it recorded in your ears for 30 seconds. Beware : Running it without the flow control patch is likely to crash your box !!
* The patch is cleaner. This is mainly due to the fact i am getting to a better understanding of Linux socket layer.DEFAULT_SCO_RXBUFS; sk->sk_sndtime

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel