Commit 10c62ddc authored by Frédéric Dalleau's avatar Frédéric Dalleau Committed by Gustavo Padovan

Bluetooth: Parameters for outgoing SCO connections

In order to establish a transparent SCO connection, the correct settings
must be specified in the Setup Synchronous Connection request. For that,
a setting field is added to ACL connection data to set up the desired
parameters. The patch also removes usage of hdev->voice_setting in CVSD
connection and makes use of T2 parameters for transparent data.
Signed-off-by: default avatarFrédéric Dalleau <frederic.dalleau@linux.intel.com>
Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
Acked-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarGustavo Padovan <gustavo.padovan@collabora.co.uk>
parent 2f69a82a
...@@ -320,6 +320,7 @@ struct hci_conn { ...@@ -320,6 +320,7 @@ struct hci_conn {
__u32 passkey_notify; __u32 passkey_notify;
__u8 passkey_entered; __u8 passkey_entered;
__u16 disc_timeout; __u16 disc_timeout;
__u16 setting;
unsigned long flags; unsigned long flags;
__u8 remote_cap; __u8 remote_cap;
...@@ -584,8 +585,8 @@ struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle); ...@@ -584,8 +585,8 @@ struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle);
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
__u8 dst_type, __u8 sec_level, __u8 auth_type); __u8 dst_type, __u8 sec_level, __u8 auth_type);
struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
bdaddr_t *dst); __u16 setting);
int hci_conn_check_link_mode(struct hci_conn *conn); int hci_conn_check_link_mode(struct hci_conn *conn);
int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level); int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level);
int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type); int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
......
...@@ -185,13 +185,24 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle) ...@@ -185,13 +185,24 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
conn->attempt++; conn->attempt++;
cp.handle = cpu_to_le16(handle); cp.handle = cpu_to_le16(handle);
cp.pkt_type = cpu_to_le16(conn->pkt_type);
cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
cp.voice_setting = cpu_to_le16(conn->setting);
switch (conn->setting & SCO_AIRMODE_MASK) {
case SCO_AIRMODE_TRANSP:
cp.pkt_type = __constant_cpu_to_le16(EDR_ESCO_MASK &
~ESCO_2EV3);
cp.max_latency = __constant_cpu_to_le16(0x000d);
cp.retrans_effort = 0x02;
break;
case SCO_AIRMODE_CVSD:
cp.pkt_type = cpu_to_le16(conn->pkt_type);
cp.max_latency = __constant_cpu_to_le16(0xffff); cp.max_latency = __constant_cpu_to_le16(0xffff);
cp.voice_setting = cpu_to_le16(hdev->voice_setting);
cp.retrans_effort = 0xff; cp.retrans_effort = 0xff;
break;
}
hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp); hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
} }
...@@ -560,7 +571,8 @@ static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, ...@@ -560,7 +571,8 @@ static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
return acl; return acl;
} }
struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst) struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
__u16 setting)
{ {
struct hci_conn *acl; struct hci_conn *acl;
struct hci_conn *sco; struct hci_conn *sco;
...@@ -583,6 +595,8 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst) ...@@ -583,6 +595,8 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst)
hci_conn_hold(sco); hci_conn_hold(sco);
sco->setting = setting;
if (acl->state == BT_CONNECTED && if (acl->state == BT_CONNECTED &&
(sco->state == BT_OPEN || sco->state == BT_CLOSED)) { (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
set_bit(HCI_CONN_POWER_SAVE, &acl->flags); set_bit(HCI_CONN_POWER_SAVE, &acl->flags);
......
...@@ -176,7 +176,7 @@ static int sco_connect(struct sock *sk) ...@@ -176,7 +176,7 @@ static int sco_connect(struct sock *sk)
else else
type = SCO_LINK; type = SCO_LINK;
hcon = hci_connect_sco(hdev, type, dst); hcon = hci_connect_sco(hdev, type, dst, sco_pi(sk)->setting);
if (IS_ERR(hcon)) { if (IS_ERR(hcon)) {
err = PTR_ERR(hcon); err = PTR_ERR(hcon);
goto done; goto done;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment