[pulseaudio-discuss] bluetooth: problem with old headset
Georg Chini
georg at chini.tk
Mon Mar 2 14:02:52 PST 2015
On 02.03.2015 07:41, Georg Chini wrote:
> On 23.02.2015 09:06, David Henningsson wrote:
>>
>>
>> On 2015-02-21 23:14, Georg Chini wrote:
>>> Hello,
>>>
>>>
>>>
>>> With the Plantronics 590, the connect() call in bluez5_sco_acquire_cb
>>> returns
>>> "Protocol not supported". The headset itself is functional, I tested
>>> with my mobile.
>>>
>> I've heard of this, but never seen it myself. I suspect it's a kernel
>> regression, but I'm not sure. Does it work with older kernels? Like,
>> one, two, three years old kernels or such?
>>
> I had the chance to test this over the weekend. Works with kernel 3.10.
> This was the oldest kernel I still had on my machine, so I'll do some
> more
> investigations to see where exactly it breaks.
Yes, it is a kernel regression introduced in 3.12. There are two reasons
why it does no longer
work:
1) The driver expects the headset to issue a sync connection finished
event (0x2c), even
if the connection attempt fails, so that it can test various packet
types until it succeeds.
My old headset does not do so, it just sends a command status event
(0x0f) with the
status code 0x1a. So the driver tries its first option and then fails.
2) The headset apparently needs a retrans_effort of 0xff (whatever that
parameter means)
instead of 0x01.
The following patch (for kernel 3.17.2) solves the issue for me. Even if
this is
not the right approach it at least shows where the problem is.
--- a/net/bluetooth/hci_event.c 2014-10-30 17:43:25.000000000 +0100
+++ b/net/bluetooth/hci_event.c 2015-03-02 22:41:11.303887654 +0100
@@ -1738,6 +1738,8 @@
sco->state = BT_CLOSED;
- hci_proto_connect_cfm(sco, status);
- hci_conn_del(sco);
+ if (!hci_setup_sync(sco, handle)) {
+ hci_proto_connect_cfm(sco, status);
+ hci_conn_del(sco);
+ }
}
}
--- a/net/bluetooth/hci_conn.c 2014-10-30 17:43:25.000000000 +0100
+++ b/net/bluetooth/hci_conn.c 2015-03-02 21:51:32.569179920 +0100
@@ -37,17 +37,18 @@
u16 pkt_type;
u16 max_latency;
+ u8 retrans_effort;
};
static const struct sco_param sco_param_cvsd[] = {
- { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000a }, /* S3 */
- { EDR_ESCO_MASK & ~ESCO_2EV3, 0x0007 }, /* S2 */
- { EDR_ESCO_MASK | ESCO_EV3, 0x0007 }, /* S1 */
- { EDR_ESCO_MASK | ESCO_HV3, 0xffff }, /* D1 */
- { EDR_ESCO_MASK | ESCO_HV1, 0xffff }, /* D0 */
+ { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000a, 0x01 }, /* S3 */
+ { EDR_ESCO_MASK & ~ESCO_2EV3, 0x0007, 0x01 }, /* S2 */
+ { EDR_ESCO_MASK | ESCO_EV3, 0x0007, 0x01 }, /* S1 */
+ { EDR_ESCO_MASK | ESCO_HV3, 0xffff, 0x01 }, /* D1 */
+ { EDR_ESCO_MASK | ESCO_HV1, 0xffff, 0xff }, /* D0 */
};
static const struct sco_param sco_param_wideband[] = {
- { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000d }, /* T2 */
- { EDR_ESCO_MASK | ESCO_EV3, 0x0008 }, /* T1 */
+ { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000d, 0x02 }, /* T2 */
+ { EDR_ESCO_MASK | ESCO_EV3, 0x0008, 0x02 }, /* T1 */
};
@@ -191,5 +192,4 @@
if (conn->attempt > ARRAY_SIZE(sco_param_wideband))
return false;
- cp.retrans_effort = 0x02;
param = &sco_param_wideband[conn->attempt - 1];
break;
@@ -197,5 +197,4 @@
if (conn->attempt > ARRAY_SIZE(sco_param_cvsd))
return false;
- cp.retrans_effort = 0x01;
param = &sco_param_cvsd[conn->attempt - 1];
break;
@@ -206,4 +205,5 @@
cp.pkt_type = __cpu_to_le16(param->pkt_type);
cp.max_latency = __cpu_to_le16(param->max_latency);
+ cp.retrans_effort = param->retrans_effort;
if (hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp)
< 0)
More information about the pulseaudio-discuss
mailing list