public inbox for linux-bluetooth@vger.kernel.org
 help / color / mirror / Atom feed
From: Sumeet VERMA <sumeet.verma@st.com>
To: "'BlueZ users'" <bluez-users@lists.sourceforge.net>
Subject: Re: [Bluez-users] How to enable eSCO in linux 2.6.18?
Date: Wed, 26 Mar 2008 09:38:41 +0530	[thread overview]
Message-ID: <00e801c88ef7$1381d040$832fc70a@dlh.st.com> (raw)
In-Reply-To: <BAY117-W512E12E372AF6367AFF61C0FC0@phx.gbl>

[-- Attachment #1: Type: text/plain, Size: 896 bytes --]

Hi 
Please find attached the esco patch for 2.6.18

Sumeet 

-----Original Message-----
From: bluez-users-bounces@lists.sourceforge.net
[mailto:bluez-users-bounces@lists.sourceforge.net] On Behalf Of \x11
Sent: Tuesday, March 25, 2008 11:41 AM
To: bluez-users@lists.sourceforge.net
Subject: [Bluez-users] How to enable eSCO in linux 2.6.18?


Hi All:
        I want to enable eSCO function in linux 2.6.18 for a certain
reason.... I know that 2.6.23 with the bluez-2.6.23mh1 patch can enable
simple eSCO support. But since i can't upgrade my kernel to 2.6.23+ , is
there any patches that can be applied on a 2.6.18 kernel in order to make
eSCO connections ?



Thanks




semiyd





_________________________________________________________________
News, entertainment and everything you care about at Live.com. Get it now!
http://www.live.com/getstarted.aspx


[-- Attachment #2: 2.6.18_esco.patch --]
[-- Type: application/octet-stream, Size: 19133 bytes --]

diff -urN tmp/linux-2.6.18/include/net/bluetooth/bluetooth.h linux-2.6.18/include/net/bluetooth/bluetooth.h
--- tmp/linux-2.6.18/include/net/bluetooth/bluetooth.h	2006-09-20 09:12:06.000000000 +0530
+++ linux-2.6.18/include/net/bluetooth/bluetooth.h	2007-09-20 21:14:06.000000000 +0530
@@ -53,6 +53,23 @@
 #define SOL_SCO		17
 #define SOL_RFCOMM	18
 
+#if 0 
+/* Debugging */
+#define CONFIG_BT_BLUEZ_DEBUG
+
+#ifdef CONFIG_BT_BLUEZ_DEBUG
+#define CONFIG_BT_SOCK_DEBUG		1
+#define CONFIG_BT_HCI_CORE_DEBUG	1
+#define CONFIG_BT_HCI_SOCK_DEBUG	1
+#define CONFIG_BT_RFCOMM_DEBUG 		1
+#define CONFIG_BT_L2CAP_DEBUG		1
+#define CONFIG_BT_SCO_DEBUG		1
+
+#define CONFIG_BT_HCIUART_DEBUG		1
+#define CONFIG_BT_HCIVHCI_DEBUG		1
+#endif /* CONFIG_BT_BLUEZ_DEBUG */
+#endif 
+
 #define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg)
 #define BT_DBG(fmt, arg...)  printk(KERN_INFO "%s: " fmt "\n" , __FUNCTION__ , ## arg)
 #define BT_ERR(fmt, arg...)  printk(KERN_ERR  "%s: " fmt "\n" , __FUNCTION__ , ## arg)
diff -urN tmp/linux-2.6.18/include/net/bluetooth/hci_core.h linux-2.6.18/include/net/bluetooth/hci_core.h
--- tmp/linux-2.6.18/include/net/bluetooth/hci_core.h	2006-09-20 09:12:06.000000000 +0530
+++ linux-2.6.18/include/net/bluetooth/hci_core.h	2007-11-19 21:56:06.000000000 +0530
@@ -75,6 +75,7 @@
 	__u16		voice_setting;
 
 	__u16		pkt_type;
+	__u16		esco_pkt_type;
 	__u16		link_policy;
 	__u16		link_mode;
 
@@ -413,6 +414,8 @@
 int hci_register_sysfs(struct hci_dev *hdev);
 void hci_unregister_sysfs(struct hci_dev *hdev);
 
+
+
 #define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->parent = (pdev))
 
 /* ----- LMP capabilities ----- */
@@ -420,6 +423,7 @@
 #define lmp_encrypt_capable(dev)   ((dev)->features[0] & LMP_ENCRYPT)
 #define lmp_sniff_capable(dev)     ((dev)->features[0] & LMP_SNIFF)
 #define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
+#define lmp_esco_capable(dev)      ((dev)->features[3] & LMP_ESCO)
 
 /* ----- HCI protocols ----- */
 struct hci_proto {
diff -urN tmp/linux-2.6.18/include/net/bluetooth/hci.h linux-2.6.18/include/net/bluetooth/hci.h
--- tmp/linux-2.6.18/include/net/bluetooth/hci.h	2006-09-20 09:12:06.000000000 +0530
+++ linux-2.6.18/include/net/bluetooth/hci.h	2007-11-06 02:02:32.000000000 +0530
@@ -128,6 +128,19 @@
 #define SCO_PTYPE_MASK	(HCI_HV1 | HCI_HV2 | HCI_HV3)
 #define ACL_PTYPE_MASK	(~SCO_PTYPE_MASK)
 
+/* eSCO packet types */
+#define HCI_ESCO_HV1	0x0001
+#define HCI_ESCO_HV2	0x0002
+#define HCI_ESCO_HV3	0x0004
+#define HCI_ESCO_EV3	0x0008
+#define HCI_ESCO_EV4	0x0010
+#define HCI_ESCO_EV5	0x0020
+
+/* Some devices seem to have trouble establishing EV* packet connections */
+/* with other devices.  For this reason we mask out the eSCO packets */ 
+/* for now.  Might need to address this later */
+#define ESCO_PTYPE_MASK	(HCI_ESCO_HV1 | HCI_ESCO_HV2 | HCI_ESCO_HV3)
+
 /* ACL flags */
 #define ACL_CONT		0x01
 #define ACL_START		0x02
@@ -137,6 +150,7 @@
 /* Baseband links */
 #define SCO_LINK	0x00
 #define ACL_LINK	0x01
+#define ESCO_LINK	0x02
 
 /* LMP features */
 #define LMP_3SLOT	0x01
@@ -157,6 +171,11 @@
 #define LMP_ULAW	0x40
 #define LMP_ALAW	0x80
 
+/* eSCO support and packets */
+#define LMP_ESCO	0x80
+#define LMP_EV4		0x01
+#define LMP_EV5		0x02
+
 #define LMP_CVSD	0x01
 #define LMP_PSCHEME	0x02
 #define LMP_PCONTROL	0x04
@@ -312,12 +331,29 @@
 	__u8     role;
 } __attribute__ ((packed));
 
+#define OCF_ACCEPT_SYNC_CONN_REQ	0x0029
+struct hci_cp_accept_sync_conn_req {
+	bdaddr_t	bdaddr;
+	__le32		tx_rate;
+	__le32		rx_rate;
+	__le16		max_latency;
+	__le16		voice_setting;
+	__u8		retrans_effort;
+	__le16		pkt_type;
+} __attribute__((packed));
+
 #define OCF_REJECT_CONN_REQ	0x000a
 struct hci_cp_reject_conn_req {
 	bdaddr_t bdaddr;
 	__u8     reason;
 } __attribute__ ((packed));
 
+#define OCF_REJECT_SYNC_CONN_REQ	0x002a
+struct hci_cp_reject_sync_conn_req {
+	bdaddr_t 	bdaddr;
+	__u8		reason;
+} __attribute__ ((packed));
+
 #define OCF_DISCONNECT	0x0006
 struct hci_cp_disconnect {
 	__le16   handle;
@@ -330,6 +366,17 @@
 	__le16   pkt_type;
 } __attribute__ ((packed));
 
+#define OCF_SETUP_SYNC_CONN	0x0028
+struct hci_cp_setup_sync_conn {
+	__le16	handle;
+	__le32 	tx_rate;
+	__le32	rx_rate;
+	__le16	latency;
+	__le16	voice_setting;
+	__u8	retrans_effort;
+	__le16	pkt_type;
+} __attribute__ ((packed));
+
 #define OCF_INQUIRY		0x0001
 struct hci_cp_inquiry {
 	__u8     lap[3];
@@ -516,6 +563,29 @@
 	__u8     encr_mode;
 } __attribute__ ((packed));
 
+#define HCI_EV_SYNC_CONN_COMPLETE	0x2C
+struct hci_ev_sync_conn_complete {
+	__u8 		status;
+	__le16		handle;
+	bdaddr_t	bdaddr;
+	__u8		link_type;
+	__u8		trans_interval;
+	__u8		retrans_window;
+	__le16		rx_pkt_len;
+	__le16		tx_pkt_len;
+	__u8		air_mode;
+} __attribute__ ((packed));
+
+#define HCI_EV_SYNC_CONN_CHANGED       0x2D
+struct hci_ev_sync_conn_changed {
+	__u8		status;
+	__le16		handle;
+	__u8		trans_interval;
+	__u8		retrans_window;
+	__le16		rx_pkt_len;
+	__le16		tx_pkt_len;
+} __attribute__ ((packed));
+
 #define HCI_EV_CONN_REQUEST	0x04
 struct hci_ev_conn_request {
 	bdaddr_t bdaddr;
diff -urN tmp/linux-2.6.18/net/bluetooth/hci_conn.c linux-2.6.18/net/bluetooth/hci_conn.c
--- tmp/linux-2.6.18/net/bluetooth/hci_conn.c	2006-09-20 09:12:06.000000000 +0530
+++ linux-2.6.18/net/bluetooth/hci_conn.c	2007-11-19 22:00:17.000000000 +0530
@@ -100,17 +100,33 @@
 void hci_add_sco(struct hci_conn *conn, __u16 handle)
 {
 	struct hci_dev *hdev = conn->hdev;
-	struct hci_cp_add_sco cp;
 
 	BT_DBG("%p", conn);
 
 	conn->state = BT_CONNECT;
 	conn->out = 1;
 
-	cp.pkt_type = __cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);
-	cp.handle   = __cpu_to_le16(handle);
+	/* Devices that support 1.2 should be using the eSCO */
+	/* commands.  Add SCO commands were deprecated in 1.2 */
 
-	hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ADD_SCO, sizeof(cp), &cp);
+	if (lmp_esco_capable(hdev)) {
+		struct hci_cp_setup_sync_conn cp;
+		cp.handle = __cpu_to_le16(handle);
+		cp.tx_rate = __cpu_to_le32(0x1f40);
+		cp.rx_rate = __cpu_to_le32(0x1f40);
+		cp.latency = __cpu_to_le16(0xffff);
+		cp.voice_setting = __cpu_to_le16(hdev->voice_setting);
+		cp.retrans_effort = 0xff;
+		cp.pkt_type = __cpu_to_le16(hdev->esco_pkt_type & ESCO_PTYPE_MASK);
+	
+		hci_send_cmd(hdev, OGF_LINK_CTL, OCF_SETUP_SYNC_CONN, sizeof(cp), &cp);
+	} else {
+		struct hci_cp_add_sco cp;
+		cp.pkt_type = __cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);
+		cp.handle   = __cpu_to_le16(handle);
+
+		hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ADD_SCO, sizeof(cp), &cp);
+	}
 }
 
 static void hci_conn_timeout(unsigned long arg)
@@ -194,23 +210,25 @@
 
 	del_timer(&conn->disc_timer);
 
-	if (conn->type == SCO_LINK) {
-		struct hci_conn *acl = conn->link;
-		if (acl) {
-			acl->link = NULL;
-			hci_conn_put(acl);
-		}
-	} else {
+	if (conn->type == ACL_LINK) {
 		struct hci_conn *sco = conn->link;
 		if (sco)
 			sco->link = NULL;
 
 		/* Unacked frames */
 		hdev->acl_cnt += conn->sent;
+	} else {
+		struct hci_conn *acl = conn->link;
+		if (acl) {
+			acl->link = NULL;
+			hci_conn_put(acl);
+		}
 	}
 
 	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);
@@ -270,6 +288,7 @@
 struct hci_conn * hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
 {
 	struct hci_conn *acl;
+	struct hci_conn *sco;
 
 	BT_DBG("%s dst %s", hdev->name, batostr(dst));
 
@@ -283,28 +302,25 @@
 	if (acl->state == BT_OPEN || acl->state == BT_CLOSED)
 		hci_acl_connect(acl);
 
-	if (type == SCO_LINK) {
-		struct hci_conn *sco;
+	if (type == ACL_LINK)
+		return acl;
 
-		if (!(sco = hci_conn_hash_lookup_ba(hdev, SCO_LINK, dst))) {
-			if (!(sco = hci_conn_add(hdev, SCO_LINK, dst))) {
-				hci_conn_put(acl);
-				return NULL;
-			}
+	if (!(sco = hci_conn_hash_lookup_ba(hdev, type, dst))) {
+		if (!(sco = hci_conn_add(hdev, type, dst))) {
+			hci_conn_put(acl);
+			return NULL;
 		}
-		acl->link = sco;
-		sco->link = acl;
+	}
+	acl->link = sco;
+	sco->link = acl;
 
-		hci_conn_hold(sco);
+	hci_conn_hold(sco);
 
-		if (acl->state == BT_CONNECTED && 
-				(sco->state == BT_OPEN || sco->state == BT_CLOSED))
-			hci_add_sco(sco, acl->handle);
+	if (acl->state == BT_CONNECTED && 
+			(sco->state == BT_OPEN || sco->state == BT_CLOSED))
+		hci_add_sco(sco, acl->handle);
 
-		return sco;
-	} else {
-		return acl;
-	}
+	return sco;
 }
 EXPORT_SYMBOL(hci_connect);
 
diff -urN tmp/linux-2.6.18/net/bluetooth/hci_core.c linux-2.6.18/net/bluetooth/hci_core.c
--- tmp/linux-2.6.18/net/bluetooth/hci_core.c	2006-09-20 09:12:06.000000000 +0530
+++ linux-2.6.18/net/bluetooth/hci_core.c	2008-01-29 01:01:32.000000000 +0530
@@ -848,6 +848,7 @@
 
 	hdev->flags = 0;
 	hdev->pkt_type  = (HCI_DM1 | HCI_DH1 | HCI_HV1);
+	hdev->esco_pkt_type = HCI_ESCO_HV1;
 	hdev->link_mode = (HCI_LM_ACCEPT);
 
 	hdev->idle_timeout = 0;
@@ -1390,6 +1391,7 @@
 		/* Process frame */
 		switch (bt_cb(skb)->pkt_type) {
 		case HCI_EVENT_PKT:
+			BT_DBG("%s HCI event packet", hdev->name);
 			hci_event_packet(hdev, skb);
 			break;
 
@@ -1404,6 +1406,7 @@
 			break;
 
 		default:
+			BT_DBG("%s Invalid packet", hdev->name);
 			kfree_skb(skb);
 			break;
 		}
diff -urN tmp/linux-2.6.18/net/bluetooth/hci_event.c linux-2.6.18/net/bluetooth/hci_event.c
--- tmp/linux-2.6.18/net/bluetooth/hci_event.c	2006-09-20 09:12:06.000000000 +0530
+++ linux-2.6.18/net/bluetooth/hci_event.c	2008-01-29 01:02:54.000000000 +0530
@@ -322,13 +322,30 @@
 		if (hdev->features[0] & LMP_5SLOT)
 			hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
 
-		if (hdev->features[1] & LMP_HV2)
-			hdev->pkt_type |= (HCI_HV2);
+		if (hdev->features[1] & LMP_HV2) {
+			hdev->pkt_type  |= HCI_HV2;
+			hdev->esco_pkt_type |= HCI_ESCO_HV2;
+		}
+
+		if (hdev->features[1] & LMP_HV3) {
+			hdev->pkt_type  |= HCI_HV3;
+			hdev->esco_pkt_type |= HCI_ESCO_HV3;
+		}
+
+		if (hdev->features[3] & LMP_ESCO)
+			hdev->esco_pkt_type |= HCI_ESCO_EV3;
+
+		if (hdev->features[4] & LMP_EV4)
+			hdev->esco_pkt_type |= HCI_ESCO_EV4;
+
+		if (hdev->features[4] & LMP_EV5)
+			hdev->esco_pkt_type |= HCI_ESCO_EV5;
+
+		BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name,
+				lf->features[0], lf->features[1], lf->features[2]);
 
-		if (hdev->features[1] & LMP_HV3)
-			hdev->pkt_type |= (HCI_HV3);
 
-		BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name, lf->features[0], lf->features[1], lf->features[2]);
+		BT_DBG("%s: eSco packets: 0x%x", hdev->name, hdev->esco_pkt_type);
 
 		break;
 
@@ -412,40 +429,76 @@
 	hci_dev_unlock(hdev);
 }
 
-static void hci_cs_link_ctl(struct hci_dev *hdev, __u16 ocf, __u8 status)
+static inline void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
 {
-	BT_DBG("%s ocf 0x%x", hdev->name, ocf);
+	struct hci_conn *acl, *sco;
+	struct hci_cp_add_sco *cp = hci_sent_cmd_data(hdev, OGF_LINK_CTL, OCF_ADD_SCO);
 
-	switch (ocf) {
-	case OCF_CREATE_CONN:
-		hci_cs_create_conn(hdev, status);
-		break;
+	if (!cp)
+		return;	
 
-	case OCF_ADD_SCO:
-		if (status) {
-			struct hci_conn *acl, *sco;
-			struct hci_cp_add_sco *cp = hci_sent_cmd_data(hdev, OGF_LINK_CTL, OCF_ADD_SCO);
-			__u16 handle;
+	hci_dev_lock(hdev);
 
-			if (!cp)
-				break;
+	if (status) {
+		__u16 handle = __le16_to_cpu(cp->handle);
 
-			handle = __le16_to_cpu(cp->handle);
+		BT_DBG("%s Add SCO error: handle %d status 0x%x", hdev->name, handle, status);
 
-			BT_DBG("%s Add SCO error: handle %d status 0x%x", hdev->name, handle, status);
+		acl = hci_conn_hash_lookup_handle(hdev, handle);
+		if (acl && (sco = acl->link)) {
+			sco->state = BT_CLOSED;
 
-			hci_dev_lock(hdev);
+			hci_proto_connect_cfm(sco, status);
+			hci_conn_del(sco);
+		}
+	}
 
-			acl = hci_conn_hash_lookup_handle(hdev, handle);
-			if (acl && (sco = acl->link)) {
-				sco->state = BT_CLOSED;
+	hci_dev_unlock(hdev);
+}
 
-				hci_proto_connect_cfm(sco, status);
-				hci_conn_del(sco);
-			}
+static inline void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
+{
+	struct hci_conn *acl, *sco;
+	struct hci_cp_setup_sync_conn *cp = hci_sent_cmd_data(hdev, OGF_LINK_CTL, OCF_SETUP_SYNC_CONN);
 
-			hci_dev_unlock(hdev);
+	if (!cp)
+		return;	
+
+	hci_dev_lock(hdev);
+
+	if (status) {
+		__u16 handle = __le16_to_cpu(cp->handle);
+
+		BT_DBG("%s eSCO conn setup error: handle %d status 0x%x",
+			hdev->name, handle, status);
+
+		acl = hci_conn_hash_lookup_handle(hdev, handle);
+		if (acl && (sco = acl->link)) {
+			sco->state = BT_CLOSED;
+
+			hci_proto_connect_cfm(sco, status);
+			hci_conn_del(sco);
 		}
+	}
+
+	hci_dev_unlock(hdev);	
+}
+
+static void hci_cs_link_ctl(struct hci_dev *hdev, __u16 ocf, __u8 status)
+{
+	BT_DBG("%s ocf 0x%x", hdev->name, ocf);
+	
+	switch (ocf) {
+	case OCF_CREATE_CONN:
+		hci_cs_create_conn(hdev, status);
+		break;
+
+	case OCF_ADD_SCO:
+		hci_cs_add_sco(hdev, status);
+		break;
+
+	case OCF_SETUP_SYNC_CONN:
+		hci_cs_setup_sync_conn(hdev, status);
 		break;
 
 	case OCF_INQUIRY:
@@ -669,7 +722,6 @@
 	if (mask & HCI_LM_ACCEPT) {
 		/* Connection accepted */
 		struct hci_conn *conn;
-		struct hci_cp_accept_conn_req cp;
 
 		hci_dev_lock(hdev);
 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
@@ -684,23 +736,51 @@
 		conn->state = BT_CONNECT;
 		hci_dev_unlock(hdev);
 
-		bacpy(&cp.bdaddr, &ev->bdaddr);
+		if ((ev->link_type == ACL_LINK) || (!lmp_esco_capable(hdev))) {
+			struct hci_cp_accept_conn_req cp;
+			bacpy(&cp.bdaddr, &ev->bdaddr);
 
-		if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
-			cp.role = 0x00; /* Become master */
-		else
-			cp.role = 0x01; /* Remain slave */
+			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
+				cp.role = 0x00; /* Become master */
+			else
+				cp.role = 0x01; /* Remain slave */
 
-		hci_send_cmd(hdev, OGF_LINK_CTL,
-				OCF_ACCEPT_CONN_REQ, sizeof(cp), &cp);
+			hci_send_cmd(hdev, OGF_LINK_CTL,
+					OCF_ACCEPT_CONN_REQ, sizeof(cp), &cp);
+		} else {
+			/* Send the Accept Sync Connection Command */
+			struct hci_cp_accept_sync_conn_req cp;
+			
+			bacpy(&cp.bdaddr, &ev->bdaddr);
+			cp.tx_rate = __cpu_to_le32(0x1f40);
+			cp.rx_rate = __cpu_to_le32(0x1f40);
+			cp.max_latency = __cpu_to_le16(0xffff);
+			cp.voice_setting = __cpu_to_le16(hdev->voice_setting);
+			cp.retrans_effort = 0xff;
+			cp.pkt_type = __cpu_to_le16(hdev->esco_pkt_type & ESCO_PTYPE_MASK);
+
+			hci_send_cmd(hdev, OGF_LINK_CTL,
+					OCF_ACCEPT_SYNC_CONN_REQ, sizeof(cp), &cp);
+		}
 	} else {
 		/* Connection rejected */
-		struct hci_cp_reject_conn_req cp;
 
-		bacpy(&cp.bdaddr, &ev->bdaddr);
-		cp.reason = 0x0f;
-		hci_send_cmd(hdev, OGF_LINK_CTL,
-				OCF_REJECT_CONN_REQ, sizeof(cp), &cp);
+		if ((ev->link_type == ACL_LINK) || (!lmp_esco_capable(hdev))) {
+			struct hci_cp_reject_conn_req cp;
+
+			bacpy(&cp.bdaddr, &ev->bdaddr);
+			cp.reason = 0x0f;
+			hci_send_cmd(hdev, OGF_LINK_CTL,
+					OCF_REJECT_CONN_REQ, sizeof(cp), &cp);
+		} else {
+			struct hci_cp_reject_sync_conn_req cp;
+			
+			bacpy(&cp.bdaddr, &ev->bdaddr);
+			cp.reason = 0x0f;
+
+			hci_send_cmd(hdev, OGF_LINK_CTL,
+					OCF_REJECT_SYNC_CONN_REQ, sizeof(cp), &cp);
+		}
 	}
 }
 
@@ -780,6 +860,57 @@
 	hci_dev_unlock(hdev);
 }
 
+/* eSCO Connect Complete */
+static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_ev_sync_conn_complete *ev = (struct hci_ev_sync_conn_complete *) skb->data;
+	struct hci_conn *conn;
+
+	BT_DBG("%s", hdev->name);
+
+	hci_dev_lock(hdev);
+
+	/* There are two possibilities here.  We establish an outgoing ESCO link and get */
+	/* back a SCO link.  Or we got a connect request with a SCO/ESCO link type and */
+	/* arrived here once it was established */
+	conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
+	if (!conn) {
+		/* Incoming SCO case */
+		conn = hci_conn_hash_lookup_ba(hdev, SCO_LINK, &ev->bdaddr);
+		if (!conn) {
+			hci_dev_unlock(hdev);
+			return;
+		}
+
+		if (conn->out) {
+			BT_DBG("ended up with a SCO link");
+			hci_conn_del(conn);
+			hci_dev_unlock(hdev);
+			return;
+		}
+	}
+
+	if (!ev->status) {
+		conn->handle = __le16_to_cpu(ev->handle);
+		conn->type = ev->link_type;
+		conn->state  = BT_CONNECTED;
+
+		if (conn->out) {
+			/* Update disconnect timer */
+			hci_conn_hold(conn);
+			hci_conn_put(conn);
+		}
+	} else
+		conn->state = BT_CLOSED;
+
+	hci_proto_connect_cfm(conn, ev->status);
+	if (ev->status)
+		hci_conn_del(conn);
+
+	hci_dev_unlock(hdev);
+}
+
+
 /* Disconnect Complete */
 static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
@@ -832,12 +963,12 @@
 		if (conn) {
 			conn->sent -= count;
 
-			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;
+			} else {
+				if ((hdev->sco_cnt += count) > hdev->sco_pkts)
+					hdev->sco_cnt = hdev->sco_pkts;
 			}
 		}
 	}
@@ -1116,6 +1247,10 @@
 		hci_conn_complete_evt(hdev, skb);
 		break;
 
+	case HCI_EV_SYNC_CONN_COMPLETE:
+		hci_sync_conn_complete_evt(hdev, skb);
+		break;
+
 	case HCI_EV_DISCONN_COMPLETE:
 		hci_disconn_complete_evt(hdev, skb);
 		break;
diff -urN tmp/linux-2.6.18/net/bluetooth/sco.c linux-2.6.18/net/bluetooth/sco.c
--- tmp/linux-2.6.18/net/bluetooth/sco.c	2006-09-20 09:12:06.000000000 +0530
+++ linux-2.6.18/net/bluetooth/sco.c	2007-11-06 19:55:38.000000000 +0530
@@ -189,7 +189,7 @@
 	struct sco_conn *conn;
 	struct hci_conn *hcon;
 	struct hci_dev  *hdev;
-	int err = 0;
+	int err, type;
 
 	BT_DBG("%s -> %s", batostr(src), batostr(dst));
 
@@ -200,7 +200,9 @@
 
 	err = -ENOMEM;
 
-	hcon = hci_connect(hdev, SCO_LINK, dst);
+	type = lmp_esco_capable(hdev) ? ESCO_LINK : SCO_LINK;
+
+	hcon = hci_connect(hdev, type, dst);
 	if (!hcon)
 		goto done;
 
@@ -837,6 +839,9 @@
 {
 	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
 
+	if (type != SCO_LINK && type != ESCO_LINK)
+		return 0;
+
 	/* Always accept connection */
 	return HCI_LM_ACCEPT;
 }
@@ -845,7 +850,7 @@
 {
 	BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
 
-	if (hcon->type != SCO_LINK)
+	if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
 		return 0;
 
 	if (!status) {
@@ -864,7 +869,7 @@
 {
 	BT_DBG("hcon %p reason %d", hcon, reason);
 
-	if (hcon->type != SCO_LINK)
+	if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
 		return 0;
 
 	sco_conn_del(hcon, bt_err(reason));

[-- Attachment #3: Type: text/plain, Size: 278 bytes --]

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace

[-- Attachment #4: Type: text/plain, Size: 164 bytes --]

_______________________________________________
Bluez-users mailing list
Bluez-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-users

  reply	other threads:[~2008-03-26  4:08 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-03-25  6:11 [Bluez-users] How to enable eSCO in linux 2.6.18? \x11
2008-03-26  4:08 ` Sumeet VERMA [this message]
2008-03-26  6:00   ` dong yan
2008-03-26  6:31     ` Sumeet VERMA
2008-03-26  7:04       ` dong yan
2008-04-11  8:26       ` dong yan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='00e801c88ef7$1381d040$832fc70a@dlh.st.com' \
    --to=sumeet.verma@st.com \
    --cc=bluez-users@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox