Sniff mode issues regarding Sony Ericsson headsets: kernel patch proposal.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




Hi Marcel,

Due to job requirement, I recently fined tuned a kernel to work well with some Sony Erisson A2DP Headsets (namely Motorola HBH-DS970 and HBH-DS980): this means making sure to force the other side to exit sniff mode early on before the AVDTP signalling comes into play.

If i remember well we had a talk a while ago about the way the sniff mode was handled by the kernel due to various issues with some bluetooth keyboards. The conclusion we had at that time, the best way to handle this issue was to add a socket option on an L2CAP channel to force the other side to exit sniff mode even if it was the one who initially entered the sniff mode.

I used this approach and wrote & tested a patch against 2.6.26-mh3. Patch is attached and seems to solve the issue.

*but*

During validation testing we found yet another issue that seems to be related to the way we handle the sniff mode. The syndrom is that if the user screws up at enterring the pin code during pairing bluez fails to close the acl connection properly, which means subsequent attempts result in a "connection already exist" error. From the user point of view it is impossible to try to pair again to the same headset...which is quite annoying.
Below is an hci trace of the issue:
< ACL data: handle 1 flags 0x02 dlen 12
   L2CAP(s): Connect req: psm 25 scid 0x0040
> HCI Event: Number of Completed Packets (0x13) plen 5
   handle 1 packets 1
> ACL data: handle 1 flags 0x02 dlen 16
   L2CAP(s): Connect rsp: dcid 0x0051 scid 0x0040 result 1 status 1
     Connection pending - Authentication pending
> HCI Event: PIN Code Request (0x16) plen 6
   bdaddr 00:1C:A4:2C:FA:4A
< HCI Command: PIN Code Request Reply (0x01|0x000d) plen 23
   bdaddr 00:1C:A4:2C:FA:4A len 4 pin '1111'
> HCI Event: Command Complete (0x0e) plen 10
   PIN Code Request Reply (0x01|0x000d) ncmd 2
   status 0x00 bdaddr 00:1C:A4:2C:FA:4A
> ACL data: handle 1 flags 0x02 dlen 16
   L2CAP(s): Connect rsp: dcid 0x0051 scid 0x0040 result 3 status 0
     Connection refused - security block
> HCI Event: Mode Change (0x14) plen 6
   status 0x00 handle 1 mode 0x02 interval 2048
   Mode: Sniff
< HCI Command: Disconnect (0x01|0x0006) plen 3
   handle 1 reason 0x13
   Reason: Remote User Terminated Connection
> HCI Event: Command Status (0x0f) plen 4
   Disconnect (0x01|0x0006) status 0x00 ncmd 1
> HCI Event: Disconn Complete (0x05) plen 4
   status 0x0c handle 1 reason 0x1f
   Error: Command Disallowed
> HCI Event: Command Status (0x0f) plen 4
   Unknown (0x00|0x0000) status 0x00 ncmd 2

I hacked the kernel to try to see if forcing the headset to exit sniff mode before sending disconnect would solve the issue.... well it did :-)
Trace below shows this working:
< ACL data: handle 1 flags 0x02 dlen 12
   L2CAP(s): Connect req: psm 25 scid 0x0040
> HCI Event: Read Remote Supported Features (0x0b) plen 11
   status 0x00 handle 1
   Features: 0xff 0x2e 0x2d 0xfa 0x98 0x39 0x00 0x80
> HCI Event: Command Status (0x0f) plen 4
   Unknown (0x00|0x0000) status 0x00 ncmd 1
> HCI Event: Command Complete (0x0e) plen 6
   Write Link Policy Settings (0x02|0x000d) ncmd 2
   status 0x00 handle 1
> HCI Event: Number of Completed Packets (0x13) plen 5
   handle 1 packets 1
> ACL data: handle 1 flags 0x02 dlen 16
   L2CAP(s): Connect rsp: dcid 0x0053 scid 0x0040 result 1 status 1
     Connection pending - Authentication pending
> HCI Event: PIN Code Request (0x16) plen 6
   bdaddr 00:1C:A4:2C:FA:4A
< HCI Command: PIN Code Request Reply (0x01|0x000d) plen 23
   bdaddr 00:1C:A4:2C:FA:4A len 4 pin '1111'
> HCI Event: Command Complete (0x0e) plen 10
   PIN Code Request Reply (0x01|0x000d) ncmd 2
   status 0x00 bdaddr 00:1C:A4:2C:FA:4A
> ACL data: handle 1 flags 0x02 dlen 16
   L2CAP(s): Connect rsp: dcid 0x0053 scid 0x0040 result 3 status 0
     Connection refused - security block
> HCI Event: Mode Change (0x14) plen 6
   status 0x00 handle 1 mode 0x02 interval 2048
   Mode: Sniff
< HCI Command: Exit Sniff Mode (0x02|0x0004) plen 2
   handle 1
> HCI Event: Command Status (0x0f) plen 4
   Exit Sniff Mode (0x02|0x0004) status 0x00 ncmd 1
< HCI Command: Disconnect (0x01|0x0006) plen 3
   handle 1 reason 0x13
   Reason: Remote User Terminated Connection
> HCI Event: Command Status (0x0f) plen 4
   Disconnect (0x01|0x0006) status 0x00 ncmd 0
> HCI Event: Mode Change (0x14) plen 6
   status 0x00 handle 1 mode 0x00 interval 0
   Mode: Active
> HCI Event: Command Status (0x0f) plen 4
   Unknown (0x00|0x0000) status 0x00 ncmd 1
> HCI Event: Disconn Complete (0x05) plen 4
   status 0x00 handle 1 reason 0x16
   Reason: Connection Terminated by Local Host
> HCI Event: Command Status (0x0f) plen 4
   Unknown (0x00|0x0000) status 0x00 ncmd 2

Conclusion: to have those bloody Sony Erisson headsets working we have to change two things in the kernel: 1) Provide a way for a L2CAP socket user to alter sniff mode exit behaviour
 2) Make sure we exit sniff mode before to disconnect

Question 1: Are you interested in reviewing then merging my patches if i try to fix thoses issues ? Question 2: I have the gut feeling that we should change default behaviour to the behaviour required by those headsets, and provide a socket option for the bluetooth HID, rather than the other way round. What do you think ?

If we can come on an agreement on the proper way to fix this issue then i should come with a patch in a 3-4 days timeframe.

Regards,

Fabien



diff -ru -x '*.so' -x '*.lds' -x '*.a' -x '*.elf' -x '.*' -x '*.order' -x '*.ko' -x '*.mod.c' -x '*.o' -x '*.cmd' linux-2.6.26/include/net/bluetooth/hci_core.h linux-2.6.26+mh3+fch/include/net/bluetooth/hci_core.h
--- linux-2.6.26/include/net/bluetooth/hci_core.h	2008-09-01 17:06:22.000000000 +0200
+++ linux-2.6.26+mh3+fch/include/net/bluetooth/hci_core.h	2008-09-01 12:22:36.000000000 +0200
@@ -170,6 +170,7 @@
 	__u32		 link_mode;
 	__u8             auth_type;
 	__u8             power_save;
+	__u8             force_active_mode;
 	unsigned long	 pend;
 
 	unsigned int	 sent;
diff -ru -x '*.so' -x '*.lds' -x '*.a' -x '*.elf' -x '.*' -x '*.order' -x '*.ko' -x '*.mod.c' -x '*.o' -x '*.cmd' linux-2.6.26/include/net/bluetooth/l2cap.h linux-2.6.26+mh3+fch/include/net/bluetooth/l2cap.h
--- linux-2.6.26/include/net/bluetooth/l2cap.h	2008-07-13 23:51:29.000000000 +0200
+++ linux-2.6.26+mh3+fch/include/net/bluetooth/l2cap.h	2008-09-01 16:20:17.000000000 +0200
@@ -62,6 +62,8 @@
 #define L2CAP_LM_RELIABLE	0x0010
 #define L2CAP_LM_SECURE		0x0020
 
+#define L2CAP_FORCE_ACTIVE_MODE	0x04
+
 /* L2CAP command codes */
 #define L2CAP_COMMAND_REJ 0x01
 #define L2CAP_CONN_REQ    0x02
Seulement dans linux-2.6.26+mh3+fch/kernel: bounds.s
Seulement dans linux-2.6.26+mh3+fch/kernel: timeconst.h
Seulement dans linux-2.6.26+mh3+fch/lib: crc32table.h
Seulement dans linux-2.6.26+mh3+fch/lib: gen_crc32table
Seulement dans linux-2.6.26+mh3+fch/: Module.symvers
diff -ru -x '*.so' -x '*.lds' -x '*.a' -x '*.elf' -x '.*' -x '*.order' -x '*.ko' -x '*.mod.c' -x '*.o' -x '*.cmd' linux-2.6.26/net/bluetooth/hci_conn.c linux-2.6.26+mh3+fch/net/bluetooth/hci_conn.c
--- linux-2.6.26/net/bluetooth/hci_conn.c	2008-09-01 17:06:22.000000000 +0200
+++ linux-2.6.26+mh3+fch/net/bluetooth/hci_conn.c	2008-09-01 16:16:33.000000000 +0200
@@ -214,6 +214,7 @@
 	conn->state = BT_OPEN;
 
 	conn->power_save = 1;
+	conn->force_active_mode = 0;
 
 	switch (type) {
 	case ACL_LINK:
@@ -464,7 +465,10 @@
 	if (test_bit(HCI_RAW, &hdev->flags))
 		return;
 
-	if (conn->mode != HCI_CM_SNIFF || !conn->power_save)
+	if (conn->mode != HCI_CM_SNIFF)
+		goto timer;
+
+	if (!conn->power_save && !conn->force_active_mode)
 		goto timer;
 
 	if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
diff -ru -x '*.so' -x '*.lds' -x '*.a' -x '*.elf' -x '.*' -x '*.order' -x '*.ko' -x '*.mod.c' -x '*.o' -x '*.cmd' linux-2.6.26/net/bluetooth/l2cap.c linux-2.6.26+mh3+fch/net/bluetooth/l2cap.c
--- linux-2.6.26/net/bluetooth/l2cap.c	2008-09-01 17:06:22.000000000 +0200
+++ linux-2.6.26+mh3+fch/net/bluetooth/l2cap.c	2008-09-01 17:18:23.000000000 +0200
@@ -1133,6 +1133,20 @@
 		l2cap_pi(sk)->link_mode = opt;
 		break;
 
+	case L2CAP_FORCE_ACTIVE_MODE:
+		if (sk->sk_state != BT_CONNECTED) {
+			err = -ENOTCONN;
+			break;
+		}
+
+		if (get_user(opt, (u32 __user *) optval)) {
+			err = -EFAULT;
+			break;
+		}
+
+		l2cap_pi(sk)->conn->hcon->force_active_mode = opt;
+		break;
+
 	default:
 		err = -ENOPROTOOPT;
 		break;
@@ -1189,6 +1203,17 @@
 
 		break;
 
+	case L2CAP_FORCE_ACTIVE_MODE:
+		if (sk->sk_state != BT_CONNECTED) {
+			err = -ENOTCONN;
+			break;
+		}
+
+		if (put_user(l2cap_pi(sk)->conn->hcon->force_active_mode,
+				 (u32 __user *) optval))
+			err = -EFAULT;
+		break;
+
 	default:
 		err = -ENOPROTOOPT;
 		break;
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Bluez-devel mailing list
Bluez-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/bluez-devel

[Index of Archives]     [Linux Bluetooth Devel]     [Linux USB Devel]     [Network Devel]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux