2009-09-14 11:52:31

by Lan Zhu

[permalink] [raw]
Subject: can we disable/enable eSCO by using setsockopt of sco socket?

Hi Marcel,

When we connect a SCO socket, BlueZ decides whether to connect SCO or
eSCO type according to the remote feature. If the remote device
declares supporting eSCO in the remote feature, BlueZ will select eSCO
type to connect with it.

But in fact there are some old carkits or headsets which are only
support SCO but wrongly declare to support eSCO, such as Motorola
HF850 and HS820 which use a very old CSR chip, so we have problem to
create sco connection with them.

We thought a method to resolve this issue, which is force to create
SCO type connection if we find the HFP version of one remote device is
less than 1.2. So we need a method to control the SCO type from user
space. We want to use setsockopt() functon to do that. The code change
in net/bluetooth/sco.c is like below,


@@ -653,12 +653,25 @@ static int sco_sock_setsockopt(struct socket *sock, int le
{
struct sock *sk = sock->sk;
int err = 0;
+ u32 opt;

BT_DBG("sk %p", sk);

lock_sock(sk);

+ if (level != SOL_SCO) {
+ err = -ENOPROTOOPT;
+ return err;
+ }
+
switch (optname) {
+ case BT_DISABLE_ESCO:
+ if (get_user(opt, (u32 __user *) optval)) {
+ err = -EFAULT;
+ break;
+ }
+ disable_esco = opt;
+ break;
default:
err = -ENOPROTOOPT;
break;


Then, in the user space, we can call setsockopt(fd, SOL_SCO,
BT_DISABLE_ESCO, &disabled, sizeof(disabled)) to force to connect SCO.

Do you agree with this change?

Thanks,
Zhu Lan


2009-09-22 23:09:22

by Nick Pelly

[permalink] [raw]
Subject: Re: can we disable/enable eSCO by using setsockopt of sco socket?

> it gives us to determine that eSCO might not be working good enough. So
> I want output from hcitool info and detailed hcidump.

We can also reproduce this issue with HF850.

hciinfo

Requesting information ...
BD Address: 00:50:CD:20:C6:84
Device Name: Motorola HF850
LMP Version: 1.2 (0x2) LMP Subversion: 0x638
Manufacturer: Cambridge Silicon Radio (10)
Features: 0xff 0xff 0x8f 0xf8 0x18 0x18 0x00 0x80
<3-slot packets> <5-slot packets> <encryption> <slot offset>
<timing accuracy> <role switch> <hold mode> <sniff mode>
<park state> <RSSI> <channel quality> <SCO link> <HV2 packets>
<HV3 packets> <u-law log> <A-law log> <CVSD> <paging scheme>
<power control> <transparent SCO> <broadcast encrypt>
<enhanced iscan> <interlaced iscan> <interlaced pscan>
<inquiry with RSSI> <extended SCO> <AFH cap. slave>
<AFH class. slave> <AFH cap. master> <AFH class. master>
<extended features>

Attached is hcidump showing the failed eSCO attempt.

You'll notice in this hcidump we retry with SCO after failed eSCO.
This is because I have applied the following patch:


commit d5d0c6bf73b3b44f1d66bf4f9d7f3365cce70ff0
Author: Nick Pelly <[email protected]>
Date: Tue Sep 22 15:19:46 2009 -0700

Bluetooth: Fallback to SCO on error code 0x10 (Connection Accept Timeout).

This is to support the Motorola HF850 carkit which reports the
error code 0x10
for an eSCO attempt, even though it advertises eSCO support. Here is the
hcidump:

2009-09-22 15:40:24.492391 < HCI Command: Setup Synchronous Connection
(0x01|0x0028) plen 17
handle 1 voice setting 0x0060
2009-09-22 15:40:24.493002 > HCI Event: Command Status (0x0f) plen 4
Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1
2009-09-22 15:40:30.594869 > HCI Event: Synchronous Connect Complete (0x2c)
plen 17
status 0x10 handle 257 bdaddr 00:50:CD:20:C6:84 type eSCO
Error: Connection Accept Timeout Exceeded

With this patch we will retry with a SCO connection, which succeeds.

Unfortunately the Moto HF850 also takes 5 seconds to return the
error for the
eSCO attempt, so it will still take 5 seconds to fallback to SCO with this
patch.

Signed-off-by: Nick Pelly <[email protected]>

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index e99fe38..7c6f62a 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1700,6 +1700,7 @@ static inline void
hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_bu

case 0x1c: /* SCO interval rejected */
case 0x1f: /* Unspecified error */
+ case 0x10: /* Connection accept timeout - for Motorola HF850 */
if (conn->out && conn->attempt < 2) {
conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
(hdev->esco_type & EDR_ESCO_MASK);

2009-09-19 05:50:49

by Marcel Holtmann

[permalink] [raw]
Subject: Re: can we disable/enable eSCO by using setsockopt of sco socket?

Hi Peter,

> >> We did some investigation on Mecel Bluetooth stack and Qualcomm's,
> >> they both provide the upper layer with the option to specify SCO type
> >> or eSCO type when creating synchronous connection. There are plenty of
> >> different Bluetooth devices in the world, compatiblility with them is
> >> usually a big issue for one Bluetooth product. So the rubestness will
> >> be a very important target for a product. Sometimes the Bluetooth
> >> developer need enough flexibility to handle many specific cases,
> >> because that can not be totally dealt with
> >> in stack layer. Actually Bluez already has an excellent architecture,
> >> but still a little weak in the rubestness. Then, why not give the
> >> developer more flexibility to deal with some problems?
> >>
> >
> > BlueZ is not weak in robustness. Do me a favor and get your English
> > right here and do not spread FUD. You are saying that it is important to
> > work around some total broken eSCO capable chip to be robust. I do
> > question that statement. It is nice to have good interoperability with
> > broken devices, but there is a limit of broken devices we can support.
> >
> > And the userspace option to select between SCO and eSCO is just stupid
> > since you just start hacking some blacklist non-sense into the code that
> > becomes a big magic blob that nobody can track or understand.
> >
> > The way forward here is to analyze the headset and see what information
> > it gives us to determine that eSCO might not be working good enough. So
> > I want output from hcitool info and detailed hcidump.
> >
> There are device incompatibilities with eSCO. I recently posted a
> report here ("Odd eSCO behavior with BCM2045-based receiver") that
> explains that (in that case) an eSCO connection *should not even be
> tried* (much less retried). In the case I provided, the controller's
> link manager dumps all other connections and becomes unresponsive after
> a --successful-- eSCO link is established.

that is a bug in your local controller. That is different from a broken
remote controller.

> Maybe one could argue that supporting a "broken device" is too much to
> ask but, IMO, the BCM2045 is too common to avoid. The reality is that
> any code that directly supports hardware needs to account for situations
> that reflect what actually happens, rather than what the spec describes
> (again, IMO).
>
> I feel this situation especially applies to Bluetooth. Because of the
> evolving complexities of Bluetooth (1300 page core spec with countless
> sub-specs on its 3rd major evolution), there are bound to be plenty of
> special cases that will continue to emerge. Presumably your implicit
> understanding of this is what prompted adding the "disable_esco" module
> parameter to the sco driver. At some point, special casing becomes
> necessary -- so the real decision is what form that support will take.

The reason behind disable_esco is 1) to accommodate controllers that
tell that they support eSCO, but they are bluntly lying to you. So that
way can either replace them or use this option.

The second reason and more important one is that we need this for
testing and from qualification corner cases. We also have disable_cfc
for RFCOMM example and some crazy BNEP options. They are needed for
reasons that have nothing with this problem at hand. Which is that the
remote device is messed up.

Regards

Marcel



2009-09-18 16:13:51

by Peter Hurley

[permalink] [raw]
Subject: Re: can we disable/enable eSCO by using setsockopt of sco socket?

Marcel Holtmann wrote:
> Hi,
>
>
>>>>> When we connect a SCO socket, BlueZ decides whether to connect SCO or
>>>>> eSCO type according to the remote feature. If the remote device
>>>>> declares supporting eSCO in the remote feature, BlueZ will select eSCO
>>>>> type to connect with it.
>>>>>
>>>>> But in fact there are some old carkits or headsets which are only
>>>>> support SCO but wrongly declare to support eSCO, such as Motorola
>>>>> HF850 and HS820 which use a very old CSR chip, so we have problem to
>>>>> create sco connection with them.
>>>>>
>>>>> We thought a method to resolve this issue, which is force to create
>>>>> SCO type connection if we find the HFP version of one remote device is
>>>>> less than 1.2. So we need a method to control the SCO type from user
>>>>> space. We want to use setsockopt() functon to do that. The code change
>>>>> in net/bluetooth/sco.c is like below,
>>>>>
>>>>>
>>>>> @@ -653,12 +653,25 @@ static int sco_sock_setsockopt(struct socket *sock, int le
>>>>> {
>>>>> struct sock *sk = sock->sk;
>>>>> int err = 0;
>>>>> + u32 opt;
>>>>>
>>>>> BT_DBG("sk %p", sk);
>>>>>
>>>>> lock_sock(sk);
>>>>>
>>>>> + if (level != SOL_SCO) {
>>>>> + err = -ENOPROTOOPT;
>>>>> + return err;
>>>>> + }
>>>>> +
>>>>> switch (optname) {
>>>>> + case BT_DISABLE_ESCO:
>>>>> + if (get_user(opt, (u32 __user *) optval)) {
>>>>> + err = -EFAULT;
>>>>> + break;
>>>>> + }
>>>>> + disable_esco = opt;
>>>>> + break;
>>>>> default:
>>>>> err = -ENOPROTOOPT;
>>>>> break;
>>>>>
>>>>>
>>>>> Then, in the user space, we can call setsockopt(fd, SOL_SCO,
>>>>> BT_DISABLE_ESCO, &disabled, sizeof(disabled)) to force to connect SCO.
>>>>>
>>>>> Do you agree with this change?
>>>>>
>>>> I don't. You first have to prove to me that this change is needed at
>>>> all. Show me the hcidump -X -V connections attempts for these carkits.
>>>>
>>>> Also your analysis is wrong. BlueZ doesn't care if the remote headset
>>>> supports eSCO or not. We just care about if our local controller has the
>>>> synchronous setup commands. It is the job of the link manager inside the
>>>> controller firmware to either establish SCO or eSCO. And we do retry
>>>> with SCO if eSCO fails. This sounds more like the case that you have an
>>>> outdated kernel.
>>>>
>>>> Regards
>>>>
>>>> Marcel
>>>>
>>>>
>>>>
>>>>
>>> Please excuse me for my inaccurate description. Actually it is LMP
>>> layer to check the remote feature then decide which SCO type shall be
>>> setup. So, if one remote device wrongly declare to support eSCO, it
>>> will cause problem. I do know you have a retry mechanism to retry SCO
>>> if eSCO failed, it is in below code in net/bluetooth/hci_event.c,
>>> right?
>>>
>>> case 0x1c: /* SCO interval rejected */
>>> case 0x1f: /* Unspecified error */
>>> if (conn->out && conn->attempt < 2) {
>>> conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
>>> (hdev->esco_type & EDR_ESCO_MASK);
>>> hci_setup_sync(conn, conn->link->handle);
>>> goto unlock;
>>> }
>>> /* fall through */
>>>
>>> But the problem is, not all the returned error code can bring retry
>>> SCO. So, we still got problem when connecting some devices because it
>>> returns some error code else.
>>>
>>> This is the hcidump log when we test SCO with HF850 carkit.
>>>
>>> 2009-09-03 17:26:29.093601 < HCI Command: Setup Synchronous Connection (0x01|0x0
>>> 028) plen 17
>>> handle 1 voice setting 0x0060
>>> 2009-09-03 17:26:29.094608 > HCI Event: Command Status (0x0f) plen 4
>>> Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1
>>> 2009-09-03 17:26:34.190952 > HCI Event: Synchronous Connect Complete (0x2c) plen
>>> 17
>>> status 0x10 handle 257 bdaddr 00:50:CD:20:BA:E6 type eSCO
>>> Error: Connection Accept Timeout Exceeded
>>> 2009-09-03 17:26:34.191196 < HCI Command: Setup Synchronous Connection (0x01|0x0
>>> 028) plen 17
>>> handle 1 voice setting 0x0060
>>>
>>> From the log you can see, the eSCO connection failed in 5 seconds with
>>> the error "0x10 Timeout Exceeded", and it do not retry SCO again.
>>>
>>> In order to resolve such issue, we have thought about two methods to
>>> resolve this.
>>>
>>> The first one is, add a new case for "0x10" error code and then retry
>>> SCO. We do have tested this, SCO can be setup, but the 5 seconds delay
>>> can not be eliminated.
>>>
>>> The second one is, we hope to force to use the sco type of SCO for
>>> some special devices which have compatible issue with eSCO. We can
>>> force to connect SCO by calling hci_add_sco() or hci_setup_sync() with
>>> limited pkt_type for those kind of devices. This is why we want to add
>>> a DISABLE_ESCO option into setsockopt() function.
>>>
>> We did some investigation on Mecel Bluetooth stack and Qualcomm's,
>> they both provide the upper layer with the option to specify SCO type
>> or eSCO type when creating synchronous connection. There are plenty of
>> different Bluetooth devices in the world, compatiblility with them is
>> usually a big issue for one Bluetooth product. So the rubestness will
>> be a very important target for a product. Sometimes the Bluetooth
>> developer need enough flexibility to handle many specific cases,
>> because that can not be totally dealt with
>> in stack layer. Actually Bluez already has an excellent architecture,
>> but still a little weak in the rubestness. Then, why not give the
>> developer more flexibility to deal with some problems?
>>
>
> BlueZ is not weak in robustness. Do me a favor and get your English
> right here and do not spread FUD. You are saying that it is important to
> work around some total broken eSCO capable chip to be robust. I do
> question that statement. It is nice to have good interoperability with
> broken devices, but there is a limit of broken devices we can support.
>
> And the userspace option to select between SCO and eSCO is just stupid
> since you just start hacking some blacklist non-sense into the code that
> becomes a big magic blob that nobody can track or understand.
>
> The way forward here is to analyze the headset and see what information
> it gives us to determine that eSCO might not be working good enough. So
> I want output from hcitool info and detailed hcidump.
>
> Regards
>
> Marcel
Hi Marcel,

There are device incompatibilities with eSCO. I recently posted a
report here ("Odd eSCO behavior with BCM2045-based receiver") that
explains that (in that case) an eSCO connection *should not even be
tried* (much less retried). In the case I provided, the controller's
link manager dumps all other connections and becomes unresponsive after
a --successful-- eSCO link is established.

Maybe one could argue that supporting a "broken device" is too much to
ask but, IMO, the BCM2045 is too common to avoid. The reality is that
any code that directly supports hardware needs to account for situations
that reflect what actually happens, rather than what the spec describes
(again, IMO).

I feel this situation especially applies to Bluetooth. Because of the
evolving complexities of Bluetooth (1300 page core spec with countless
sub-specs on its 3rd major evolution), there are bound to be plenty of
special cases that will continue to emerge. Presumably your implicit
understanding of this is what prompted adding the "disable_esco" module
parameter to the sco driver. At some point, special casing becomes
necessary -- so the real decision is what form that support will take.

Respectfully,
Peter Hurley

2009-09-18 15:31:23

by Marcel Holtmann

[permalink] [raw]
Subject: Re: can we disable/enable eSCO by using setsockopt of sco socket?

Hi,

> >>> When we connect a SCO socket, BlueZ decides whether to connect SCO or
> >>> eSCO type according to the remote feature. If the remote device
> >>> declares supporting eSCO in the remote feature, BlueZ will select eSCO
> >>> type to connect with it.
> >>>
> >>> But in fact there are some old carkits or headsets which are only
> >>> support SCO but wrongly declare to support eSCO, such as Motorola
> >>> HF850 and HS820 which use a very old CSR chip, so we have problem to
> >>> create sco connection with them.
> >>>
> >>> We thought a method to resolve this issue, which is force to create
> >>> SCO type connection if we find the HFP version of one remote device is
> >>> less than 1.2. So we need a method to control the SCO type from user
> >>> space. We want to use setsockopt() functon to do that. The code change
> >>> in net/bluetooth/sco.c is like below,
> >>>
> >>>
> >>> @@ -653,12 +653,25 @@ static int sco_sock_setsockopt(struct socket *sock, int le
> >>> {
> >>> struct sock *sk = sock->sk;
> >>> int err = 0;
> >>> + u32 opt;
> >>>
> >>> BT_DBG("sk %p", sk);
> >>>
> >>> lock_sock(sk);
> >>>
> >>> + if (level != SOL_SCO) {
> >>> + err = -ENOPROTOOPT;
> >>> + return err;
> >>> + }
> >>> +
> >>> switch (optname) {
> >>> + case BT_DISABLE_ESCO:
> >>> + if (get_user(opt, (u32 __user *) optval)) {
> >>> + err = -EFAULT;
> >>> + break;
> >>> + }
> >>> + disable_esco = opt;
> >>> + break;
> >>> default:
> >>> err = -ENOPROTOOPT;
> >>> break;
> >>>
> >>>
> >>> Then, in the user space, we can call setsockopt(fd, SOL_SCO,
> >>> BT_DISABLE_ESCO, &disabled, sizeof(disabled)) to force to connect SCO.
> >>>
> >>> Do you agree with this change?
> >>
> >> I don't. You first have to prove to me that this change is needed at
> >> all. Show me the hcidump -X -V connections attempts for these carkits.
> >>
> >> Also your analysis is wrong. BlueZ doesn't care if the remote headset
> >> supports eSCO or not. We just care about if our local controller has the
> >> synchronous setup commands. It is the job of the link manager inside the
> >> controller firmware to either establish SCO or eSCO. And we do retry
> >> with SCO if eSCO fails. This sounds more like the case that you have an
> >> outdated kernel.
> >>
> >> Regards
> >>
> >> Marcel
> >>
> >>
> >>
> >
> > Please excuse me for my inaccurate description. Actually it is LMP
> > layer to check the remote feature then decide which SCO type shall be
> > setup. So, if one remote device wrongly declare to support eSCO, it
> > will cause problem. I do know you have a retry mechanism to retry SCO
> > if eSCO failed, it is in below code in net/bluetooth/hci_event.c,
> > right?
> >
> > case 0x1c: /* SCO interval rejected */
> > case 0x1f: /* Unspecified error */
> > if (conn->out && conn->attempt < 2) {
> > conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
> > (hdev->esco_type & EDR_ESCO_MASK);
> > hci_setup_sync(conn, conn->link->handle);
> > goto unlock;
> > }
> > /* fall through */
> >
> > But the problem is, not all the returned error code can bring retry
> > SCO. So, we still got problem when connecting some devices because it
> > returns some error code else.
> >
> > This is the hcidump log when we test SCO with HF850 carkit.
> >
> > 2009-09-03 17:26:29.093601 < HCI Command: Setup Synchronous Connection (0x01|0x0
> > 028) plen 17
> > handle 1 voice setting 0x0060
> > 2009-09-03 17:26:29.094608 > HCI Event: Command Status (0x0f) plen 4
> > Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1
> > 2009-09-03 17:26:34.190952 > HCI Event: Synchronous Connect Complete (0x2c) plen
> > 17
> > status 0x10 handle 257 bdaddr 00:50:CD:20:BA:E6 type eSCO
> > Error: Connection Accept Timeout Exceeded
> > 2009-09-03 17:26:34.191196 < HCI Command: Setup Synchronous Connection (0x01|0x0
> > 028) plen 17
> > handle 1 voice setting 0x0060
> >
> > From the log you can see, the eSCO connection failed in 5 seconds with
> > the error "0x10 Timeout Exceeded", and it do not retry SCO again.
> >
> > In order to resolve such issue, we have thought about two methods to
> > resolve this.
> >
> > The first one is, add a new case for "0x10" error code and then retry
> > SCO. We do have tested this, SCO can be setup, but the 5 seconds delay
> > can not be eliminated.
> >
> > The second one is, we hope to force to use the sco type of SCO for
> > some special devices which have compatible issue with eSCO. We can
> > force to connect SCO by calling hci_add_sco() or hci_setup_sync() with
> > limited pkt_type for those kind of devices. This is why we want to add
> > a DISABLE_ESCO option into setsockopt() function.
>
> We did some investigation on Mecel Bluetooth stack and Qualcomm's,
> they both provide the upper layer with the option to specify SCO type
> or eSCO type when creating synchronous connection. There are plenty of
> different Bluetooth devices in the world, compatiblility with them is
> usually a big issue for one Bluetooth product. So the rubestness will
> be a very important target for a product. Sometimes the Bluetooth
> developer need enough flexibility to handle many specific cases,
> because that can not be totally dealt with
> in stack layer. Actually Bluez already has an excellent architecture,
> but still a little weak in the rubestness. Then, why not give the
> developer more flexibility to deal with some problems?

BlueZ is not weak in robustness. Do me a favor and get your English
right here and do not spread FUD. You are saying that it is important to
work around some total broken eSCO capable chip to be robust. I do
question that statement. It is nice to have good interoperability with
broken devices, but there is a limit of broken devices we can support.

And the userspace option to select between SCO and eSCO is just stupid
since you just start hacking some blacklist non-sense into the code that
becomes a big magic blob that nobody can track or understand.

The way forward here is to analyze the headset and see what information
it gives us to determine that eSCO might not be working good enough. So
I want output from hcitool info and detailed hcidump.

Regards

Marcel



2009-09-18 10:47:10

by Lan Zhu

[permalink] [raw]
Subject: Re: can we disable/enable eSCO by using setsockopt of sco socket?

Hi Marcel,

2009/9/14 Lan Zhu <[email protected]>:
> Hi Marcel,
>
> 2009/9/14 Marcel Holtmann <[email protected]>:
>> Hi,
>>
>>> When we connect a SCO socket, BlueZ decides whether to connect SCO or
>>> eSCO type according to the remote feature. If the remote device
>>> declares supporting eSCO in the remote feature, BlueZ will select eSCO
>>> type to connect with it.
>>>
>>> But in fact =A0there are some old carkits or headsets which are only
>>> support SCO but wrongly declare to support eSCO, such as Motorola
>>> HF850 and HS820 which use a very old CSR chip, so we have problem to
>>> create sco connection with them.
>>>
>>> We thought a method to resolve this issue, which is force to create
>>> SCO type connection if we find the HFP version of one remote device is
>>> less than 1.2. So we need a method to control the SCO type from user
>>> space. We want to use setsockopt() functon to do that. The code change
>>> in net/bluetooth/sco.c is like below,
>>>
>>>
>>> @@ -653,12 +653,25 @@ static int sco_sock_setsockopt(struct socket *soc=
k, int le
>>> =A0{
>>> =A0 =A0 =A0 =A0struct sock *sk =3D sock->sk;
>>> =A0 =A0 =A0 =A0int err =3D 0;
>>> + =A0 =A0 =A0 u32 opt;
>>>
>>> =A0 =A0 =A0 =A0BT_DBG("sk %p", sk);
>>>
>>> =A0 =A0 =A0 =A0lock_sock(sk);
>>>
>>> + =A0 =A0 =A0 if (level !=3D SOL_SCO) {
>>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 err =3D -ENOPROTOOPT;
>>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return err;
>>> + =A0 =A0 =A0 }
>>> +
>>> =A0 =A0 =A0 =A0switch (optname) {
>>> + =A0 =A0 =A0 case BT_DISABLE_ESCO:
>>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (get_user(opt, (u32 __user *) optval))=
{
>>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 err =3D -EFAULT;
>>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
>>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 disable_esco =3D opt;
>>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
>>> =A0 =A0 =A0 =A0default:
>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0err =3D -ENOPROTOOPT;
>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
>>>
>>>
>>> Then, in the user space, we can call setsockopt(fd, SOL_SCO,
>>> BT_DISABLE_ESCO, &disabled, sizeof(disabled)) to force to connect SCO.
>>>
>>> Do you agree with this change?
>>
>> I don't. You first have to prove to me that this change is needed at
>> all. Show me the hcidump -X -V connections attempts for these carkits.
>>
>> Also your analysis is wrong. BlueZ doesn't care if the remote headset
>> supports eSCO or not. We just care about if our local controller has the
>> synchronous setup commands. It is the job of the link manager inside the
>> controller firmware to either establish SCO or eSCO. And we do retry
>> with SCO if eSCO fails. This sounds more like the case that you have an
>> outdated kernel.
>>
>> Regards
>>
>> Marcel
>>
>>
>>
>
> Please excuse me for my inaccurate description. Actually it is LMP
> layer to check the remote feature then decide which SCO type shall be
> setup. So, if one remote device wrongly declare to support eSCO, it
> will cause problem. I do know you have a retry mechanism to retry SCO
> if eSCO failed, it is in below code in net/bluetooth/hci_event.c,
> right?
>
> =A0 =A0 =A0 =A0case 0x1c: =A0 =A0 =A0/* SCO interval rejected */
> =A0 =A0 =A0 =A0case 0x1f: =A0 =A0 =A0/* Unspecified error */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (conn->out && conn->attempt < 2) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0conn->pkt_type =3D (hdev->=
esco_type & SCO_ESCO_MASK) |
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0(hdev->esco_type & EDR_ESCO_MASK);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0hci_setup_sync(conn, conn-=
>link->handle);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto unlock;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* fall through */
>
> But the problem is, not all the returned error code can bring retry
> SCO. So, we still got problem when connecting some devices because it
> returns some error code else.
>
> This is the hcidump log when we test SCO with HF850 carkit.
>
> 2009-09-03 17:26:29.093601 < HCI Command: Setup Synchronous Connection (0=
x01|0x0
> 028) plen 17
> =A0 =A0handle 1 voice setting 0x0060
> 2009-09-03 17:26:29.094608 > HCI Event: Command Status (0x0f) plen 4
> =A0 =A0Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1
> 2009-09-03 17:26:34.190952 > HCI Event: Synchronous Connect Complete (0x2=
c) plen
> =A017
> =A0 =A0status 0x10 handle 257 bdaddr 00:50:CD:20:BA:E6 type eSCO
> =A0 =A0Error: Connection Accept Timeout Exceeded
> 2009-09-03 17:26:34.191196 < HCI Command: Setup Synchronous Connection (0=
x01|0x0
> 028) plen 17
> =A0 =A0handle 1 voice setting 0x0060
>
> From the log you can see, the eSCO connection failed in 5 seconds with
> the error "0x10 Timeout Exceeded", and it do not retry SCO again.
>
> In order to resolve such issue, we have thought about two methods to
> resolve this.
>
> The first one is, add a new case for "0x10" error code and then retry
> SCO. We do have tested this, SCO can be setup, but the 5 seconds delay
> can not be eliminated.
>
> The second one is, we hope to force to use the sco type of SCO for
> some special devices which have compatible issue with eSCO. We can
> force to connect SCO by calling hci_add_sco() or hci_setup_sync() with
> limited pkt_type for those kind of devices. This is why we want to add
> a DISABLE_ESCO option into setsockopt() function.
>
>
> Thank you,
> Zhu Lan
>

We did some investigation on Mecel Bluetooth stack and Qualcomm's,
they both provide the upper layer with the option to specify SCO type
or eSCO type when creating synchronous connection. There are plenty of
different Bluetooth devices in the world, compatiblility with them is
usually a big issue for one Bluetooth product. So the rubestness will
be a very important target for a product. Sometimes the Bluetooth
developer need enough flexibility to handle many specific cases,
because that can not be totally dealt with
in stack layer. Actually Bluez already has an excellent architecture,
but still a little weak in the rubestness. Then, why not give the
developer more flexibility to deal with some problems?


Thanks,
Zhu Lan

2009-09-14 15:29:07

by Lan Zhu

[permalink] [raw]
Subject: Re: can we disable/enable eSCO by using setsockopt of sco socket?

Hi Marcel,

2009/9/14 Marcel Holtmann <[email protected]>:
> Hi,
>
>> When we connect a SCO socket, BlueZ decides whether to connect SCO or
>> eSCO type according to the remote feature. If the remote device
>> declares supporting eSCO in the remote feature, BlueZ will select eSCO
>> type to connect with it.
>>
>> But in fact =A0there are some old carkits or headsets which are only
>> support SCO but wrongly declare to support eSCO, such as Motorola
>> HF850 and HS820 which use a very old CSR chip, so we have problem to
>> create sco connection with them.
>>
>> We thought a method to resolve this issue, which is force to create
>> SCO type connection if we find the HFP version of one remote device is
>> less than 1.2. So we need a method to control the SCO type from user
>> space. We want to use setsockopt() functon to do that. The code change
>> in net/bluetooth/sco.c is like below,
>>
>>
>> @@ -653,12 +653,25 @@ static int sco_sock_setsockopt(struct socket *sock=
, int le
>> =A0{
>> =A0 =A0 =A0 =A0struct sock *sk =3D sock->sk;
>> =A0 =A0 =A0 =A0int err =3D 0;
>> + =A0 =A0 =A0 u32 opt;
>>
>> =A0 =A0 =A0 =A0BT_DBG("sk %p", sk);
>>
>> =A0 =A0 =A0 =A0lock_sock(sk);
>>
>> + =A0 =A0 =A0 if (level !=3D SOL_SCO) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 err =3D -ENOPROTOOPT;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return err;
>> + =A0 =A0 =A0 }
>> +
>> =A0 =A0 =A0 =A0switch (optname) {
>> + =A0 =A0 =A0 case BT_DISABLE_ESCO:
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (get_user(opt, (u32 __user *) optval)) =
{
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 err =3D -EFAULT;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 disable_esco =3D opt;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
>> =A0 =A0 =A0 =A0default:
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0err =3D -ENOPROTOOPT;
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
>>
>>
>> Then, in the user space, we can call setsockopt(fd, SOL_SCO,
>> BT_DISABLE_ESCO, &disabled, sizeof(disabled)) to force to connect SCO.
>>
>> Do you agree with this change?
>
> I don't. You first have to prove to me that this change is needed at
> all. Show me the hcidump -X -V connections attempts for these carkits.
>
> Also your analysis is wrong. BlueZ doesn't care if the remote headset
> supports eSCO or not. We just care about if our local controller has the
> synchronous setup commands. It is the job of the link manager inside the
> controller firmware to either establish SCO or eSCO. And we do retry
> with SCO if eSCO fails. This sounds more like the case that you have an
> outdated kernel.
>
> Regards
>
> Marcel
>
>
>

Please excuse me for my inaccurate description. Actually it is LMP
layer to check the remote feature then decide which SCO type shall be
setup. So, if one remote device wrongly declare to support eSCO, it
will cause problem. I do know you have a retry mechanism to retry SCO
if eSCO failed, it is in below code in net/bluetooth/hci_event.c,
right?

case 0x1c: /* SCO interval rejected */
case 0x1f: /* Unspecified error */
if (conn->out && conn->attempt < 2) {
conn->pkt_type =3D (hdev->esco_type & SCO_ESCO_MASK) |
(hdev->esco_type & EDR_ESCO_MASK);
hci_setup_sync(conn, conn->link->handle);
goto unlock;
}
/* fall through */

But the problem is, not all the returned error code can bring retry
SCO. So, we still got problem when connecting some devices because it
returns some error code else.

This is the hcidump log when we test SCO with HF850 carkit.

2009-09-03 17:26:29.093601 < HCI Command: Setup Synchronous Connection (0x0=
1|0x0
028) plen 17
handle 1 voice setting 0x0060
2009-09-03 17:26:29.094608 > HCI Event: Command Status (0x0f) plen 4
Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1
2009-09-03 17:26:34.190952 > HCI Event: Synchronous Connect Complete (0x2c)=
plen
17
status 0x10 handle 257 bdaddr 00:50:CD:20:BA:E6 type eSCO
Error: Connection Accept Timeout Exceeded
2009-09-03 17:26:34.191196 < HCI Command: Setup Synchronous Connection (0x0=
1|0x0
028) plen 17
handle 1 voice setting 0x0060

>From the log you can see, the eSCO connection failed in 5 seconds with
the error "0x10 Timeout Exceeded", and it do not retry SCO again.

In order to resolve such issue, we have thought about two methods to
resolve this.

The first one is, add a new case for "0x10" error code and then retry
SCO. We do have tested this, SCO can be setup, but the 5 seconds delay
can not be eliminated.

The second one is, we hope to force to use the sco type of SCO for
some special devices which have compatible issue with eSCO. We can
force to connect SCO by calling hci_add_sco() or hci_setup_sync() with
limited pkt_type for those kind of devices. This is why we want to add
a DISABLE_ESCO option into setsockopt() function.


Thank you,
Zhu Lan

2009-09-14 13:32:34

by Marcel Holtmann

[permalink] [raw]
Subject: Re: can we disable/enable eSCO by using setsockopt of sco socket?

Hi,

> When we connect a SCO socket, BlueZ decides whether to connect SCO or
> eSCO type according to the remote feature. If the remote device
> declares supporting eSCO in the remote feature, BlueZ will select eSCO
> type to connect with it.
>
> But in fact there are some old carkits or headsets which are only
> support SCO but wrongly declare to support eSCO, such as Motorola
> HF850 and HS820 which use a very old CSR chip, so we have problem to
> create sco connection with them.
>
> We thought a method to resolve this issue, which is force to create
> SCO type connection if we find the HFP version of one remote device is
> less than 1.2. So we need a method to control the SCO type from user
> space. We want to use setsockopt() functon to do that. The code change
> in net/bluetooth/sco.c is like below,
>
>
> @@ -653,12 +653,25 @@ static int sco_sock_setsockopt(struct socket *sock, int le
> {
> struct sock *sk = sock->sk;
> int err = 0;
> + u32 opt;
>
> BT_DBG("sk %p", sk);
>
> lock_sock(sk);
>
> + if (level != SOL_SCO) {
> + err = -ENOPROTOOPT;
> + return err;
> + }
> +
> switch (optname) {
> + case BT_DISABLE_ESCO:
> + if (get_user(opt, (u32 __user *) optval)) {
> + err = -EFAULT;
> + break;
> + }
> + disable_esco = opt;
> + break;
> default:
> err = -ENOPROTOOPT;
> break;
>
>
> Then, in the user space, we can call setsockopt(fd, SOL_SCO,
> BT_DISABLE_ESCO, &disabled, sizeof(disabled)) to force to connect SCO.
>
> Do you agree with this change?

I don't. You first have to prove to me that this change is needed at
all. Show me the hcidump -X -V connections attempts for these carkits.

Also your analysis is wrong. BlueZ doesn't care if the remote headset
supports eSCO or not. We just care about if our local controller has the
synchronous setup commands. It is the job of the link manager inside the
controller firmware to either establish SCO or eSCO. And we do retry
with SCO if eSCO fails. This sounds more like the case that you have an
outdated kernel.

Regards

Marcel



2010-01-15 06:31:43

by Liang Bao

[permalink] [raw]
Subject: Re: can we disable/enable eSCO by using setsockopt of sco socket?

Hi, Marcel,

I've merged the 2.6.33-rc3 into our code base and made extensive tests
in the past 2 days. The problem is still there if I tried long enough.
But it could be my own problem because the merge is manually
conducted. Our code is 2.6.29 and has a couple of changes so I have to
add the commit 9eba32b86d17ef87131fa0bce43c614904ab5781 with some
minor tailoring.

However, I doubt the duplicate sysfs entry doesn't lead to our kernel
panic. I revert the code back to official 2.6.30 where retry logic was
first introduced and simply add the error code 0x10(Connection Accept
Timeout Exceeded) for retry(see modified code snippet at the end) on
the code snippet for retrying SCO right now. By using hcitool to
monitor the connections, I found the code will eventually result in 3
connection handles while the eSCO one seems to be invalid.

# /data/local/hcitool con
Connections:
< eSCO 00:50:CD:20:BA:E6 handle 0 state 5 lm SLAVE (note the handle
and the state)
< SCO 00:50:CD:20:BA:E6 handle 513 state 1 lm SLAVE
> ACL 00:50:CD:20:BA:E6 handle 1 state 1 lm MASTER AUTH ENCRYPT

While the phenomenon appears due to error 0x10 and with our code, I am
wondering the same will happen if the hci_sync_conn_complete_evt() is
called with error 0x1c and 0x1f in the official code. As you can see,
the snippet just skips hci_conn_del(conn) and goto unlock:. With the
invalid eSCO handle, when I power off bluetooth, sometimes a kernel
panic will happen(the panic backtrace appended at the end of the
message,too). Now my question is that shall we call hci_conn_del(conn)
for the failed eSCO attempt before retry SCO?

Regarding extend the SCO socket parameters to allow specifying a
eSCO/SCO packet mask, do you want us to provide a patch as well?

Regards,
Liang Bao

<<the backtrace of the kernel panic>>

<4>[ 7691.791656] Backtrace:

<4>[ 7691.794799] [<c03663f8>] (hci_send_to_sock+0x0/0x17c) from
[<c0362078>] (hci_si_event+0xd0/0xe0)

<4>[ 7691.805480] [<c0361fa8>] (hci_si_event+0x0/0xe0) from
[<c03657e8>] (hci_sock_dev_event+0x38/0x148)

<4>[ 7691.816040] [<c03657b0>] (hci_sock_dev_event+0x0/0x148) from
[<c007caec>] (notifier_call_chain+0x34/0x78)

<4>[ 7691.827545] [<c007cab8>] (notifier_call_chain+0x0/0x78) from
[<c007d104>] (__atomic_notifier_call_chain+0x34/0x60)

<4>[ 7691.839843] [<c007d0d0>] (__atomic_notifier_call_chain+0x0/0x60)
from [<c007d150>] (atomic_notifier_call_chain+0x20/0x28)

<4>[ 7691.852783] r5:c96e1218 r4:c96e1000

<4>[ 7691.857666] [<c007d130>] (atomic_notifier_call_chain+0x0/0x28)
from [<c035e9a8>] (hci_notify+0x18/0x20)

<4>[ 7691.868713] [<c035e990>] (hci_notify+0x0/0x20) from [<c035ec24>]
(hci_dev_do_close+0xcc/0x1f0)

<4>[ 7691.879180] [<c035eb58>] (hci_dev_do_close+0x0/0x1f0) from
[<c035f4d4>] (hci_dev_close+0x20/0x60)

<4>[ 7691.889953] r7:400448ca r6:00000000 r5:c62c4c00 r4:c96e1000

<4>[ 7691.897369] [<c035f4b4>] (hci_dev_close+0x0/0x60) from
[<c03660cc>] (hci_sock_ioctl+0x100/0x284)

<4>[ 7691.908050] r5:c62c4c00 r4:400448ca

<4>[ 7691.912658] [<c0365fcc>] (hci_sock_ioctl+0x0/0x284) from
[<c02ac90c>] (sock_ioctl+0x1f0/0x240)

<4>[ 7691.922882] r7:400448ca r6:00000000 r5:00000000 r4:400448ca

<4>[ 7691.930541] [<c02ac71c>] (sock_ioctl+0x0/0x240) from
[<c00ccdbc>] (vfs_ioctl+0x34/0x94)

<4>[ 7691.940124] r7:400448ca r6:00000000 r5:c02ac71c r4:c97d04c0

<4>[ 7691.947784] [<c00ccd88>] (vfs_ioctl+0x0/0x94) from [<c00cd41c>]
(do_vfs_ioctl+0x508/0x56c)

<4>[ 7691.957916] r7:0000006b r6:400448ca r5:c97d04c0 r4:00000000

<4>[ 7691.965332] [<c00ccf14>] (do_vfs_ioctl+0x0/0x56c) from
[<c00cd4c0>] (sys_ioctl+0x40/0x64)

<4>[ 7691.975372] r9:c9da2000 r8:c0037004 r7:0000006b r6:400448ca r5:00000=
000

<4>[ 7691.983947] r4:c97d04c0

<4>[ 7691.987548] [<c00cd480>] (sys_ioctl+0x0/0x64) from [<c0036e80>]
(ret_fast_syscall+0x0/0x2c)

<4>[ 7691.997497] r7:00000036 r6:0000006b r5:aea00d30 r4:aea010c8

<4>[ 7692.005157] Code: e5955000 e3550000 0a000006 e1a04005 (e4143008)

<0>[ 7692.014282] Kernel panic - not syncing: Fatal exception


<< the code I am currently using, one line insertion on official 2.6.30 >>

1670static inline void hci_sync_conn_complete_evt(struct hci_dev
*hdev, struct sk_buff *skb)
1671{
1672 =A0 =A0 =A0 =A0struct hci_ev_sync_conn_complete *ev =3D (void *) skb->=
data;
1673 =A0 =A0 =A0 =A0struct hci_conn *conn;
1674
1675 =A0 =A0 =A0 =A0BT_DBG("%s status %d", hdev->name, ev->status);
1676
1677 =A0 =A0 =A0 =A0hci_dev_lock(hdev);
1678
1679 =A0 =A0 =A0 =A0conn =3D hci_conn_hash_lookup_ba(hdev, ev->link_type, &=
ev->bdaddr);
1680 =A0 =A0 =A0 =A0if (!conn) {
1681 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (ev->link_type =3D=3D ESCO_LINK)
1682 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto unlock;
1683
1684 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0conn =3D hci_conn_hash_lookup_ba(hdev, =
ESCO_LINK,
&ev->bdaddr);
1685 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (!conn)
1686 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto unlock;
1687
1688 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0conn->type =3D SCO_LINK;
1689 =A0 =A0 =A0 =A0}
1690
1691 =A0 =A0 =A0 =A0switch (ev->status) {
1692 =A0 =A0 =A0 =A0case 0x00:
1693 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0conn->handle =3D __le16_to_cpu(ev->hand=
le);
1694 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0conn->state =A0=3D BT_CONNECTED;
1695
1696 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0hci_conn_add_sysfs(conn);
1697 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
1698
++++=A0 =A0 =A0 =A0 case 0x10: =A0 =A0 =A0/* Connection accept timeout exce=
eded */
1699 =A0 =A0 =A0 =A0case 0x1c: =A0 =A0 =A0/* SCO interval rejected */
1700 =A0 =A0 =A0 =A0case 0x1f: =A0 =A0 =A0/* Unspecified error */
1701 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (conn->out && conn->attempt < 2) {
1702 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0conn->pkt_type =3D (hde=
v->esco_type & SCO_ESCO_MASK) |
1703 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0(hdev->esco_type & EDR_ESCO_MASK);
1704 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0hci_setup_sync(conn, co=
nn->link->handle);
1705 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto unlock;
1706 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
1707 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* fall through */
1708
1709 =A0 =A0 =A0 =A0default:
1710 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0conn->state =3D BT_CLOSED;
1711 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
1712 =A0 =A0 =A0 =A0}
1713
1714 =A0 =A0 =A0 =A0hci_proto_connect_cfm(conn, ev->status);
1715 =A0 =A0 =A0 =A0if (ev->status)
1716 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0hci_conn_del(conn);
1717
1718unlock:
1719 =A0 =A0 =A0 =A0hci_dev_unlock(hdev);
1720}


2010/1/13 Marcel Holtmann <[email protected]>:
> Hi Liang,
>
>> >> We resumed the work of troubleshooting some problematic carkits
>> >> recently. While we agree with that eSCO/SCO is handled by the stuff
>> >> below HCI and bluez is absoultely right handling this, we still need
>> >> to face the fact that there're bunch of carkits and headsets with
>> >> hidden issues which only get exposed in certain combination like the
>> >> HF850 and our phones. Bluez can still be even better.
>> >>
>> >> In our case, the HF850 claims eSCO but when you're trying to connect
>> >> with it, it will timeout. So to have the stack works with those
>> >> on-market products, it's better if the developers sitting above the
>> >> HCI layer have some tweaking method on bluez behavior in ununsal
>> >> cases.
>> >>
>> >> Regarding the particular eSCO timeout failure, we add the following
>> >> delta into the net/bluetooth/hci_event.c
>> >>
>> >> =A0 =A0 =A0 =A0 hci_proto_connect_cfm(conn, ev->status);
>> >> +
>> >> + =A0 =A0if (conn->out && (ev->status =3D=3D 0x1a || ev->status =3D=
=3D 0x1c ||
>> >> + =A0 =A0 =A0 =A0 =A0 =A0ev->status =3D=3D 0x1f || ev->status =3D=3D =
0x10) &&
>> >> + =A0 =A0 =A0 =A0 =A0 =A0conn->attempt < 2) {
>> >> + =A0 =A0 =A0 =A0conn->pkt_type =3D (hdev->esco_type & SCO_ESCO_MASK)=
|
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(hdev->esco_type & EDR_ESCO_=
MASK);
>> >> + =A0 =A0 =A0 =A0hci_setup_sync(conn, conn->link->handle);
>> >> + =A0 =A0 =A0 =A0goto unlock;
>> >> + =A0 =A0}
>> >> +
>> >> =A0 =A0 =A0 if (ev->status)
>> >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 hci_conn_del(conn);
>> >>
>> >> With this code change, we can successfully retry a SCO link after eSC=
O
>> >> attempt timeout. Still, a setsockopt interface will be better for
>> >> tweaking. Or is there any better idea on how to allow bluez work with
>> >> those on-market problematic devices?
>> >
>> > no you can NOT. It is race condition hazard. You can not call
>> > hci_proto_connect_cfm() and then just hci_setup_sync(). That confuses
>> > upper layers and just works by pure luck.
>> >
>> > The upstream code actually handles already the 0x1c and 0x1f error cod=
es
>> > and retries the setup without eSCO packets types. So you snippet is
>> > against an old kernel (older than 2.6.30 at least).
>> >
>> Yeah, you're right, we're using version 2.6.29. I put the retry code bet=
ween
>>
>> =A0 =A0 hci_proto_connect_cfm(conn, ev->status)
>>
>> and
>>
>> =A0 =A0 if (ev->status)
>> =A0 =A0 =A0 =A0 =A0hci_conn_del(conn);
>>
>> because the kernel log is showing a warning complaining duplicate
>> device files is being added( log put at the end to make reading easy).
>> It seems the device file is created twice. I noticed a call to
>> hci_conn_hold_device(conn) is added to kernel 2.6.30 and onwards. I'll
>> try the new way tomorrow.
>
> that should be fixed. Please re-test with bluetooth-testing tree based
> on 2.6.33-rc3.
>
>> >> The hcidump log is copied again here for your convenience:
>> >> > 2009-09-03 17:26:29.093601 < HCI Command: Setup Synchronous Connect=
ion (0x01|0x0
>> >> > 028) plen 17
>> >> > =A0 =A0handle 1 voice setting 0x0060
>> >> > 2009-09-03 17:26:29.094608 > HCI Event: Command Status (0x0f) plen =
4
>> >> > =A0 =A0Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd =
1
>> >> > 2009-09-03 17:26:34.190952 > HCI Event: Synchronous Connect Complet=
e (0x2c) plen
>> >> > =A017
>> >> > =A0 =A0status 0x10 handle 257 bdaddr 00:50:CD:20:BA:E6 type eSCO
>> >> > =A0 =A0Error: Connection Accept Timeout Exceeded
>> >
>> > The accept timeout has a pretty clear definition and while we could
>> > retry, I am having some concerns here. This also does not explain why
>> > 0x1a is in your code snippet.
>> We conduct a retry for the code 0x1a because there's also some devices
>> claim eSCO capability but respond with "Unsupported Remote Feature /
>> Unsupported LMP Feature (0X1A)".
>
> So adding 0x1a to the exception list and falling back to SCO is fine
> with me. Send a proper patch against the bluetooth-testing tree with a
> detailed commit message and the extract of hcidump -X -V for this one.
> You will find an example on how such a commit message should look like
> when looking through the history.
>
>> We can understand your concern for 0x10 as it's a timeout by
>> definition, therefore, if a retry will be done, probably the same set
>> of parameters shall be used. However, the reality is that devices came
>> to market around eSCO was introduced could be troubles - eSCO was
>> added but not fully tested or failed to pass test and finally device
>> manufacturer had to turn off them but inconsistency was kept - like
>> what the Motorola HF850 does. Anyway, it's your call to determine the
>> behavior for the 0x10(Connection Accept Timeout Exceeded) and
>> personally I'll respect that.
>
> If we really wanna work around this problem, then it might be better to
> extend the SCO socket parameters to allow specifying a eSCO/SCO packet
> mask. So it is up to the userspace to select any quirks.
>
> Regards
>
> Marcel
>
>
>

2010-01-12 18:45:44

by Marcel Holtmann

[permalink] [raw]
Subject: Re: can we disable/enable eSCO by using setsockopt of sco socket?

Hi Liang,

> >> We resumed the work of troubleshooting some problematic carkits
> >> recently. While we agree with that eSCO/SCO is handled by the stuff
> >> below HCI and bluez is absoultely right handling this, we still need
> >> to face the fact that there're bunch of carkits and headsets with
> >> hidden issues which only get exposed in certain combination like the
> >> HF850 and our phones. Bluez can still be even better.
> >>
> >> In our case, the HF850 claims eSCO but when you're trying to connect
> >> with it, it will timeout. So to have the stack works with those
> >> on-market products, it's better if the developers sitting above the
> >> HCI layer have some tweaking method on bluez behavior in ununsal
> >> cases.
> >>
> >> Regarding the particular eSCO timeout failure, we add the following
> >> delta into the net/bluetooth/hci_event.c
> >>
> >> hci_proto_connect_cfm(conn, ev->status);
> >> +
> >> + if (conn->out && (ev->status == 0x1a || ev->status == 0x1c ||
> >> + ev->status == 0x1f || ev->status == 0x10) &&
> >> + conn->attempt < 2) {
> >> + conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
> >> + (hdev->esco_type & EDR_ESCO_MASK);
> >> + hci_setup_sync(conn, conn->link->handle);
> >> + goto unlock;
> >> + }
> >> +
> >> if (ev->status)
> >> hci_conn_del(conn);
> >>
> >> With this code change, we can successfully retry a SCO link after eSCO
> >> attempt timeout. Still, a setsockopt interface will be better for
> >> tweaking. Or is there any better idea on how to allow bluez work with
> >> those on-market problematic devices?
> >
> > no you can NOT. It is race condition hazard. You can not call
> > hci_proto_connect_cfm() and then just hci_setup_sync(). That confuses
> > upper layers and just works by pure luck.
> >
> > The upstream code actually handles already the 0x1c and 0x1f error codes
> > and retries the setup without eSCO packets types. So you snippet is
> > against an old kernel (older than 2.6.30 at least).
> >
> Yeah, you're right, we're using version 2.6.29. I put the retry code between
>
> hci_proto_connect_cfm(conn, ev->status)
>
> and
>
> if (ev->status)
> hci_conn_del(conn);
>
> because the kernel log is showing a warning complaining duplicate
> device files is being added( log put at the end to make reading easy).
> It seems the device file is created twice. I noticed a call to
> hci_conn_hold_device(conn) is added to kernel 2.6.30 and onwards. I'll
> try the new way tomorrow.

that should be fixed. Please re-test with bluetooth-testing tree based
on 2.6.33-rc3.

> >> The hcidump log is copied again here for your convenience:
> >> > 2009-09-03 17:26:29.093601 < HCI Command: Setup Synchronous Connection (0x01|0x0
> >> > 028) plen 17
> >> > handle 1 voice setting 0x0060
> >> > 2009-09-03 17:26:29.094608 > HCI Event: Command Status (0x0f) plen 4
> >> > Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1
> >> > 2009-09-03 17:26:34.190952 > HCI Event: Synchronous Connect Complete (0x2c) plen
> >> > 17
> >> > status 0x10 handle 257 bdaddr 00:50:CD:20:BA:E6 type eSCO
> >> > Error: Connection Accept Timeout Exceeded
> >
> > The accept timeout has a pretty clear definition and while we could
> > retry, I am having some concerns here. This also does not explain why
> > 0x1a is in your code snippet.
> We conduct a retry for the code 0x1a because there's also some devices
> claim eSCO capability but respond with "Unsupported Remote Feature /
> Unsupported LMP Feature (0X1A)".

So adding 0x1a to the exception list and falling back to SCO is fine
with me. Send a proper patch against the bluetooth-testing tree with a
detailed commit message and the extract of hcidump -X -V for this one.
You will find an example on how such a commit message should look like
when looking through the history.

> We can understand your concern for 0x10 as it's a timeout by
> definition, therefore, if a retry will be done, probably the same set
> of parameters shall be used. However, the reality is that devices came
> to market around eSCO was introduced could be troubles - eSCO was
> added but not fully tested or failed to pass test and finally device
> manufacturer had to turn off them but inconsistency was kept - like
> what the Motorola HF850 does. Anyway, it's your call to determine the
> behavior for the 0x10(Connection Accept Timeout Exceeded) and
> personally I'll respect that.

If we really wanna work around this problem, then it might be better to
extend the SCO socket parameters to allow specifying a eSCO/SCO packet
mask. So it is up to the userspace to select any quirks.

Regards

Marcel



2010-01-12 13:39:16

by Liang Bao

[permalink] [raw]
Subject: Re: can we disable/enable eSCO by using setsockopt of sco socket?

I revisited every message regarding this thread and found I'm a little
out-of-date. Thanks a lot for pointing out this.Some inline replies
below.

2010/1/12 Marcel Holtmann <[email protected]>:
> Hi Liang,
>
>> We resumed the work of troubleshooting some problematic carkits
>> recently. While we agree with that eSCO/SCO is handled by the stuff
>> below HCI and bluez is absoultely right handling this, we still need
>> to face the fact that there're bunch of carkits and headsets with
>> hidden issues which only get exposed in certain combination like the
>> HF850 and our phones. Bluez can still be even better.
>>
>> In our case, the HF850 claims eSCO but when you're trying to connect
>> with it, it will timeout. So to have the stack works with those
>> on-market products, it's better if the developers sitting above the
>> HCI layer have some tweaking method on bluez behavior in ununsal
>> cases.
>>
>> Regarding the particular eSCO timeout failure, we add the following
>> delta into the net/bluetooth/hci_event.c
>>
>> =A0 =A0 =A0 =A0 hci_proto_connect_cfm(conn, ev->status);
>> +
>> + =A0 =A0if (conn->out && (ev->status =3D=3D 0x1a || ev->status =3D=3D 0=
x1c ||
>> + =A0 =A0 =A0 =A0 =A0 =A0ev->status =3D=3D 0x1f || ev->status =3D=3D 0x1=
0) &&
>> + =A0 =A0 =A0 =A0 =A0 =A0conn->attempt < 2) {
>> + =A0 =A0 =A0 =A0conn->pkt_type =3D (hdev->esco_type & SCO_ESCO_MASK) |
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(hdev->esco_type & EDR_ESCO_MAS=
K);
>> + =A0 =A0 =A0 =A0hci_setup_sync(conn, conn->link->handle);
>> + =A0 =A0 =A0 =A0goto unlock;
>> + =A0 =A0}
>> +
>> =A0 =A0 =A0 if (ev->status)
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 hci_conn_del(conn);
>>
>> With this code change, we can successfully retry a SCO link after eSCO
>> attempt timeout. Still, a setsockopt interface will be better for
>> tweaking. Or is there any better idea on how to allow bluez work with
>> those on-market problematic devices?
>
> no you can NOT. It is race condition hazard. You can not call
> hci_proto_connect_cfm() and then just hci_setup_sync(). That confuses
> upper layers and just works by pure luck.
>
> The upstream code actually handles already the 0x1c and 0x1f error codes
> and retries the setup without eSCO packets types. So you snippet is
> against an old kernel (older than 2.6.30 at least).
>
Yeah, you're right, we're using version 2.6.29. I put the retry code betwee=
n

hci_proto_connect_cfm(conn, ev->status)

and

if (ev->status)
hci_conn_del(conn);

because the kernel log is showing a warning complaining duplicate
device files is being added( log put at the end to make reading easy).
It seems the device file is created twice. I noticed a call to
hci_conn_hold_device(conn) is added to kernel 2.6.30 and onwards. I'll
try the new way tomorrow.

>> The hcidump log is copied again here for your convenience:
>> > 2009-09-03 17:26:29.093601 < HCI Command: Setup Synchronous Connection=
(0x01|0x0
>> > 028) plen 17
>> > =A0 =A0handle 1 voice setting 0x0060
>> > 2009-09-03 17:26:29.094608 > HCI Event: Command Status (0x0f) plen 4
>> > =A0 =A0Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1
>> > 2009-09-03 17:26:34.190952 > HCI Event: Synchronous Connect Complete (=
0x2c) plen
>> > =A017
>> > =A0 =A0status 0x10 handle 257 bdaddr 00:50:CD:20:BA:E6 type eSCO
>> > =A0 =A0Error: Connection Accept Timeout Exceeded
>
> The accept timeout has a pretty clear definition and while we could
> retry, I am having some concerns here. This also does not explain why
> 0x1a is in your code snippet.
We conduct a retry for the code 0x1a because there's also some devices
claim eSCO capability but respond with "Unsupported Remote Feature /
Unsupported LMP Feature (0X1A)".
We can understand your concern for 0x10 as it's a timeout by
definition, therefore, if a retry will be done, probably the same set
of parameters shall be used. However, the reality is that devices came
to market around eSCO was introduced could be troubles - eSCO was
added but not fully tested or failed to pass test and finally device
manufacturer had to turn off them but inconsistency was kept - like
what the Motorola HF850 does. Anyway, it's your call to determine the
behavior for the 0x10(Connection Accept Timeout Exceeded) and
personally I'll respect that.
>
> Regards
>
> Marcel
>
>
>

<4>[ 3753.172760] ------------[ cut here ]------------
<4>[ 3753.178649] WARNING: at fs/sysfs/dir.c:462 sysfs_add_one+0x34/0x44()
<4>[ 3753.226074] sysfs: duplicate filename 'hci0:257' can not be created
<4>[ 3753.239959] Modules linked in:
<4>[ 3753.243469] [<c037ce14>] (dump_stack+0x0/0x14) from [<c0062098>]
(warn_slowpath+0x70/0x8c)
<4>[ 3753.268310] [<c0062028>] (warn_slowpath+0x0/0x8c) from
[<c010d594>] (sysfs_add_one+0x34/0x44)
<4>[ 3753.298309] r3:c9bf0280 r2:c041ec0a
<4>[ 3753.303161] r7:00000001 r6:ced6dd58<3>kobject (c7c9f6dc): tried
to init an initialized object, something is seriously wrong.
<4>[ 3753.319458] [<c037ce14>] (dump_stack+0x0/0x14) from [<c0153940>]
(kobject_init+0x40/0x94)
<4>[ 3753.328826] [<c0153900>] (kobject_init+0x0/0x94) from
[<c01baa98>] (device_initialize+0x28/0x8c)
<4>[ 3753.338653] r5:c057c430 r4:c7c9f698
<4>[ 3753.342987] [<c01baa70>] (device_initialize+0x0/0x8c) from
[<c0366bc4>] (hci_conn_add_sysfs+0x54/0x90)
<4>[ 3753.353363] r5:c057c430 r4:c7c9f600
<4>[ 3753.357666] [<c0366b70>] (hci_conn_add_sysfs+0x0/0x90) from
[<c03651cc>] (hci_event_packet+0x3254/0x367c)
<4>[ 3753.368438] r7:c963f00a r6:c7c9f600 r5:cec58140 r4:c9dd3c00
<4>[ 3753.375091] [<c0361f78>] (hci_event_packet+0x0/0x367c) from
[<c035fc3c>] (hci_rx_task+0xb8/0x2c4)
<4>[ 3753.385162] [<c035fb84>] (hci_rx_task+0x0/0x2c4) from
[<c00671b8>] (tasklet_action+0x74/0xb0)
<4>[ 3753.394836] [<c0067144>] (tasklet_action+0x0/0xb0) from
[<c00677a4>] (__do_softirq+0x60/0xf8)
<4>[ 3753.404388] r7:c04f8e40 r6:cec52000 r5:00000009 r4:00000014
<4>[ 3753.411193] [<c0067744>] (__do_softirq+0x0/0xf8) from
[<c0067888>] (irq_exit+0x4c/0xac)
<4>[ 3753.420349] [<c006783c>] (irq_exit+0x0/0xac) from [<c0036058>]
(__exception_text_start+0x58/0x6c)
<4>[ 3753.430297] [<c0036000>] (__exception_text_start+0x0/0x6c) from
[<c0036a04>] (__irq_svc+0x44/0xa4)
<4>[ 3753.440399] Exception stack(0xcec53c68 to 0xcec53cb0)
<4>[ 3753.445983] 3c60: c048ddcc 00000013 c048ddb0
00000000 00000000 0000000c
<4>[ 3753.456115] 3c80: cec53d60 c014f8fc 00000004 00000013 cec53ce0
cec53d40 cec53c84 cec53cb4
<4>[ 3753.466369] 3ca0: c0062764 c0062dc0 60000013 ffffffff
<4>[ 3753.476623] r5:d8200000 r4:ffffffff
<4>[ 3753.480804] [<c0062ad8>] (vprintk+0x0/0x340) from [<c037cf80>]
(printk+0x28/0x30)
<4>[ 3753.489379] [<c037cf58>] (printk+0x0/0x30) from [<c014f8e4>]
(no_frame+0x48/0xa8)
<4>[ 3753.497833] r3:ced6dd58 r2:00000006 r1:00000020 r0:c014f8fc
<4>[ 3753.504608] [<c037ce14>] (dump_stack+0x0/0x14) from [<c0062098>]
(warn_slowpath+0x70/0x8c)
<4>[ 3753.514007] [<c0062028>] (warn_slowpath+0x0/0x8c) from
[<c010d594>] (sysfs_add_one+0x34/0x44)
<4>[ 3753.523559] r3:c9bf0280 r2:c041ec0a
<4>[ 3753.527862] r7:00000001 r6:ced6dd58 r5:cd9f8608 r4:ffffffef
<4>[ 3753.534515] [<c010d560>] (sysfs_add_one+0x0/0x44) from
[<c010e518>] (sysfs_do_create_link+0x104/0x19c)
<4>[ 3753.545013] r5:cd9f8698 r4:cd9f8608
<4>[ 3753.549194] [<c010e414>] (sysfs_do_create_link+0x0/0x19c) from
[<c010e5dc>] (sysfs_create_link+0x14/0x18)
<4>[ 3753.559967] r8:c7c9f700 r7:00000000 r6:00000000 r5:c7c9f6dc r4:c7c9f=
698
<4>[ 3753.567871] [<c010e5c8>] (sysfs_create_link+0x0/0x18) from
[<c01baf74>] (device_add+0x160/0x478)
<4>[ 3753.577819] [<c01bae14>] (device_add+0x0/0x478) from
[<c0366c24>] (add_conn+0x24/0x48)
<4>[ 3753.586730] [<c0366c00>] (add_conn+0x0/0x48) from [<c00737a8>]
(run_workqueue+0xe0/0x19c)
<4>[ 3753.596038] r5:cec52000 r4:ced53700
<4>[ 3753.600219] [<c00736c8>] (run_workqueue+0x0/0x19c) from
[<c0073fb8>] (worker_thread+0x104/0x118)
<4>[ 3753.610168] [<c0073eb4>] (worker_thread+0x0/0x118) from
[<c0077c5c>] (kthread+0x5c/0x98)
<4>[ 3753.619415] r7:00000000 r6:ced53700 r5:c0073eb4 r4:cec52000
<4>[ 3753.626068] [<c0077c00>] (kthread+0x0/0x98) from [<c0065600>]
(do_exit+0x0/0x784)
<4>[ 3753.634643] r7:00000000 r6:00000000 r5:00000000 r4:00000000
<4>[ 3753.791687] r5:cd9f8608 r4:ffffffef
<4>[ 3753.796752] [<c010d560>] (sysfs_add_one+0x0/0x44) from
[<c010e518>] (sysfs_do_create_link+0x104/0x19c)
<4>[ 3753.807281] r5:cd9f8698 r4:cd9f8608
<4>[ 3753.811523] [<c010e414>] (sysfs_do_create_link+0x0/0x19c) from
[<c010e5dc>] (sysfs_create_link+0x14/0x18)
<4>[ 3753.822265] r8:c7c9f700 r7:00000000 r6:00000000 r5:c7c9f6dc r4:c7c9f=
698
<4>[ 3753.830200] [<c010e5c8>] (sysfs_create_link+0x0/0x18) from
[<c01baf74>] (device_add+0x160/0x478)
<4>[ 3753.840179] [<c01bae14>] (device_add+0x0/0x478) from
[<c0366c24>] (add_conn+0x24/0x48)
<4>[ 3753.849304] [<c0366c00>] (add_conn+0x0/0x48) from [<c00737a8>]
(run_workqueue+0xe0/0x19c)
<4>[ 3753.858703] r5:cec52000 r4:ced53700
<4>[ 3753.863525] [<c00736c8>] (run_workqueue+0x0/0x19c) from
[<c0073fb8>] (worker_thread+0x104/0x118)
<4>[ 3753.873504] [<c0073eb4>] (worker_thread+0x0/0x118) from
[<c0077c5c>] (kthread+0x5c/0x98)
<4>[ 3753.882659] r7:00000000 r6:ced53700 r5:c0073eb4 r4:cec52000
<4>[ 3753.889465] [<c0077c00>] (kthread+0x0/0x98) from [<c0065600>]
(do_exit+0x0/0x784)
<4>[ 3753.898162] r7:00000000 r6:00000000 r5:00000000 r4:00000000

2010-01-12 11:22:17

by Marcel Holtmann

[permalink] [raw]
Subject: Re: can we disable/enable eSCO by using setsockopt of sco socket?

Hi Liang,

> We resumed the work of troubleshooting some problematic carkits
> recently. While we agree with that eSCO/SCO is handled by the stuff
> below HCI and bluez is absoultely right handling this, we still need
> to face the fact that there're bunch of carkits and headsets with
> hidden issues which only get exposed in certain combination like the
> HF850 and our phones. Bluez can still be even better.
>
> In our case, the HF850 claims eSCO but when you're trying to connect
> with it, it will timeout. So to have the stack works with those
> on-market products, it's better if the developers sitting above the
> HCI layer have some tweaking method on bluez behavior in ununsal
> cases.
>
> Regarding the particular eSCO timeout failure, we add the following
> delta into the net/bluetooth/hci_event.c
>
> hci_proto_connect_cfm(conn, ev->status);
> +
> + if (conn->out && (ev->status == 0x1a || ev->status == 0x1c ||
> + ev->status == 0x1f || ev->status == 0x10) &&
> + conn->attempt < 2) {
> + conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
> + (hdev->esco_type & EDR_ESCO_MASK);
> + hci_setup_sync(conn, conn->link->handle);
> + goto unlock;
> + }
> +
> if (ev->status)
> hci_conn_del(conn);
>
> With this code change, we can successfully retry a SCO link after eSCO
> attempt timeout. Still, a setsockopt interface will be better for
> tweaking. Or is there any better idea on how to allow bluez work with
> those on-market problematic devices?

no you can NOT. It is race condition hazard. You can not call
hci_proto_connect_cfm() and then just hci_setup_sync(). That confuses
upper layers and just works by pure luck.

The upstream code actually handles already the 0x1c and 0x1f error codes
and retries the setup without eSCO packets types. So you snippet is
against an old kernel (older than 2.6.30 at least).

> The hcidump log is copied again here for your convenience:
> > 2009-09-03 17:26:29.093601 < HCI Command: Setup Synchronous Connection (0x01|0x0
> > 028) plen 17
> > handle 1 voice setting 0x0060
> > 2009-09-03 17:26:29.094608 > HCI Event: Command Status (0x0f) plen 4
> > Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1
> > 2009-09-03 17:26:34.190952 > HCI Event: Synchronous Connect Complete (0x2c) plen
> > 17
> > status 0x10 handle 257 bdaddr 00:50:CD:20:BA:E6 type eSCO
> > Error: Connection Accept Timeout Exceeded

The accept timeout has a pretty clear definition and while we could
retry, I am having some concerns here. This also does not explain why
0x1a is in your code snippet.

Regards

Marcel



2010-01-12 09:57:11

by Liang Bao

[permalink] [raw]
Subject: Re: can we disable/enable eSCO by using setsockopt of sco socket?

Dear Marcel and other people who's interested on this topic,

We resumed the work of troubleshooting some problematic carkits
recently. While we agree with that eSCO/SCO is handled by the stuff
below HCI and bluez is absoultely right handling this, we still need
to face the fact that there're bunch of carkits and headsets with
hidden issues which only get exposed in certain combination like the
HF850 and our phones. Bluez can still be even better.

In our case, the HF850 claims eSCO but when you're trying to connect
with it, it will timeout. So to have the stack works with those
on-market products, it's better if the developers sitting above the
HCI layer have some tweaking method on bluez behavior in ununsal
cases.

Regarding the particular eSCO timeout failure, we add the following
delta into the net/bluetooth/hci_event.c

hci_proto_connect_cfm(conn, ev->status);
+
+ if (conn->out && (ev->status == 0x1a || ev->status == 0x1c ||
+ ev->status == 0x1f || ev->status == 0x10) &&
+ conn->attempt < 2) {
+ conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
+ (hdev->esco_type & EDR_ESCO_MASK);
+ hci_setup_sync(conn, conn->link->handle);
+ goto unlock;
+ }
+
if (ev->status)
hci_conn_del(conn);

With this code change, we can successfully retry a SCO link after eSCO
attempt timeout. Still, a setsockopt interface will be better for
tweaking. Or is there any better idea on how to allow bluez work with
those on-market problematic devices?

The hcidump log is copied again here for your convenience:
> 2009-09-03 17:26:29.093601 < HCI Command: Setup Synchronous Connection (0x01|0x0
> 028) plen 17
> handle 1 voice setting 0x0060
> 2009-09-03 17:26:29.094608 > HCI Event: Command Status (0x0f) plen 4
> Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1
> 2009-09-03 17:26:34.190952 > HCI Event: Synchronous Connect Complete (0x2c) plen
> 17
> status 0x10 handle 257 bdaddr 00:50:CD:20:BA:E6 type eSCO
> Error: Connection Accept Timeout Exceeded

Regards,
Liang Bao

Quoted text:
===================

Hi Marcel,

2009/9/14 Lan Zhu <zhu.lan.cn@...>:
> Hi Marcel,
>
> 2009/9/14 Marcel Holtmann <marcel@...>:
>> Hi,
>>
>>> When we connect a SCO socket, BlueZ decides whether to connect SCO or
>>> eSCO type according to the remote feature. If the remote device
>>> declares supporting eSCO in the remote feature, BlueZ will select eSCO
>>> type to connect with it.
>>>
>>> But in fact there are some old carkits or headsets which are only
>>> support SCO but wrongly declare to support eSCO, such as Motorola
>>> HF850 and HS820 which use a very old CSR chip, so we have problem to
>>> create sco connection with them.
>>>
>>> We thought a method to resolve this issue, which is force to create
>>> SCO type connection if we find the HFP version of one remote device is
>>> less than 1.2. So we need a method to control the SCO type from user
>>> space. We want to use setsockopt() functon to do that. The code change
>>> in net/bluetooth/sco.c is like below,
>>>
>>>
>>> @@ -653,12 +653,25 @@ static int sco_sock_setsockopt(struct socket *sock, int le
>>> {
>>> struct sock *sk = sock->sk;
>>> int err = 0;
>>> + u32 opt;
>>>
>>> BT_DBG("sk %p", sk);
>>>
>>> lock_sock(sk);
>>>
>>> + if (level != SOL_SCO) {
>>> + err = -ENOPROTOOPT;
>>> + return err;
>>> + }
>>> +
>>> switch (optname) {
>>> + case BT_DISABLE_ESCO:
>>> + if (get_user(opt, (u32 __user *) optval)) {
>>> + err = -EFAULT;
>>> + break;
>>> + }
>>> + disable_esco = opt;
>>> + break;
>>> default:
>>> err = -ENOPROTOOPT;
>>> break;
>>>
>>>
>>> Then, in the user space, we can call setsockopt(fd, SOL_SCO,
>>> BT_DISABLE_ESCO, &disabled, sizeof(disabled)) to force to connect SCO.
>>>
>>> Do you agree with this change?
>>
>> I don't. You first have to prove to me that this change is needed at
>> all. Show me the hcidump -X -V connections attempts for these carkits.
>>
>> Also your analysis is wrong. BlueZ doesn't care if the remote headset
>> supports eSCO or not. We just care about if our local controller has the
>> synchronous setup commands. It is the job of the link manager inside the
>> controller firmware to either establish SCO or eSCO. And we do retry
>> with SCO if eSCO fails. This sounds more like the case that you have an
>> outdated kernel.
>>
>> Regards
>>
>> Marcel
>>
>>
>>
>
> Please excuse me for my inaccurate description. Actually it is LMP
> layer to check the remote feature then decide which SCO type shall be
> setup. So, if one remote device wrongly declare to support eSCO, it
> will cause problem. I do know you have a retry mechanism to retry SCO
> if eSCO failed, it is in below code in net/bluetooth/hci_event.c,
> right?
>
> case 0x1c: /* SCO interval rejected */
> case 0x1f: /* Unspecified error */
> if (conn->out && conn->attempt < 2) {
> conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
> (hdev->esco_type & EDR_ESCO_MASK);
> hci_setup_sync(conn, conn->link->handle);
> goto unlock;
> }
> /* fall through */
>
> But the problem is, not all the returned error code can bring retry
> SCO. So, we still got problem when connecting some devices because it
> returns some error code else.
>
> This is the hcidump log when we test SCO with HF850 carkit.
>
> 2009-09-03 17:26:29.093601 < HCI Command: Setup Synchronous Connection (0x01|0x0
> 028) plen 17
> handle 1 voice setting 0x0060
> 2009-09-03 17:26:29.094608 > HCI Event: Command Status (0x0f) plen 4
> Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1
> 2009-09-03 17:26:34.190952 > HCI Event: Synchronous Connect Complete (0x2c) plen
> 17
> status 0x10 handle 257 bdaddr 00:50:CD:20:BA:E6 type eSCO
> Error: Connection Accept Timeout Exceeded
> 2009-09-03 17:26:34.191196 < HCI Command: Setup Synchronous Connection (0x01|0x0
> 028) plen 17
> handle 1 voice setting 0x0060
>
> From the log you can see, the eSCO connection failed in 5 seconds with
> the error "0x10 Timeout Exceeded", and it do not retry SCO again.
>
> In order to resolve such issue, we have thought about two methods to
> resolve this.
>
> The first one is, add a new case for "0x10" error code and then retry
> SCO. We do have tested this, SCO can be setup, but the 5 seconds delay
> can not be eliminated.
>
> The second one is, we hope to force to use the sco type of SCO for
> some special devices which have compatible issue with eSCO. We can
> force to connect SCO by calling hci_add_sco() or hci_setup_sync() with
> limited pkt_type for those kind of devices. This is why we want to add
> a DISABLE_ESCO option into setsockopt() function.
>
>
> Thank you,
> Zhu Lan
>

We did some investigation on Mecel Bluetooth stack and Qualcomm's,
they both provide the upper layer with the option to specify SCO type
or eSCO type when creating synchronous connection. There are plenty of
different Bluetooth devices in the world, compatiblility with them is
usually a big issue for one Bluetooth product. So the rubestness will
be a very important target for a product. Sometimes the Bluetooth
developer need enough flexibility to handle many specific cases,
because that can not be totally dealt with
in stack layer. Actually Bluez already has an excellent architecture,
but still a little weak in the rubestness. Then, why not give the
developer more flexibility to deal with some problems?

Thanks,
Zhu Lan