Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Bluetooth: Check for SCO type before setting retransmission effort

SCO connection cannot be setup to devices that do not support retransmission.
Patch based on http://permalink.gmane.org/gmane.linux.bluez.kernel/7779 and
adapted for this kernel version.

Code changed to check SCO/eSCO type before setting retransmission effort
and max. latency. The purpose of the patch is to support older devices not
capable of eSCO.

Tested on Blackberry 655+ headset which does not support retransmission.
Credits go to Alexander Sommerhuber.

Signed-off-by: Bernhard Thaler <bernhard.thaler@r-it.at>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>

authored by

Bernhard Thaler and committed by
Marcel Holtmann
48e68ff5 5eb596f5

+17 -5
+17 -5
net/bluetooth/hci_conn.c
··· 38 38 u16 max_latency; 39 39 }; 40 40 41 - static const struct sco_param sco_param_cvsd[] = { 41 + static const struct sco_param esco_param_cvsd[] = { 42 42 { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000a }, /* S3 */ 43 43 { EDR_ESCO_MASK & ~ESCO_2EV3, 0x0007 }, /* S2 */ 44 44 { EDR_ESCO_MASK | ESCO_EV3, 0x0007 }, /* S1 */ 45 + { EDR_ESCO_MASK | ESCO_HV3, 0xffff }, /* D1 */ 46 + { EDR_ESCO_MASK | ESCO_HV1, 0xffff }, /* D0 */ 47 + }; 48 + 49 + static const struct sco_param sco_param_cvsd[] = { 45 50 { EDR_ESCO_MASK | ESCO_HV3, 0xffff }, /* D1 */ 46 51 { EDR_ESCO_MASK | ESCO_HV1, 0xffff }, /* D0 */ 47 52 }; ··· 212 207 param = &sco_param_wideband[conn->attempt - 1]; 213 208 break; 214 209 case SCO_AIRMODE_CVSD: 215 - if (conn->attempt > ARRAY_SIZE(sco_param_cvsd)) 216 - return false; 217 - cp.retrans_effort = 0x01; 218 - param = &sco_param_cvsd[conn->attempt - 1]; 210 + if (lmp_esco_capable(conn->link)) { 211 + if (conn->attempt > ARRAY_SIZE(esco_param_cvsd)) 212 + return false; 213 + cp.retrans_effort = 0x01; 214 + param = &esco_param_cvsd[conn->attempt - 1]; 215 + } else { 216 + if (conn->attempt > ARRAY_SIZE(sco_param_cvsd)) 217 + return false; 218 + cp.retrans_effort = 0xff; 219 + param = &sco_param_cvsd[conn->attempt - 1]; 220 + } 219 221 break; 220 222 default: 221 223 return false;