summaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_event.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2008-07-14 20:13:46 +0200
committerMarcel Holtmann <marcel@holtmann.org>2008-07-14 20:13:46 +0200
commita8746417e864da1ed36dd2432a399fbeb843c2a0 (patch)
treee0e392e8b76d53748f357e888483bced2de24e2b /net/bluetooth/hci_event.c
parent[Bluetooth] Support the case when headset falls back to SCO link (diff)
downloadlinux-a8746417e864da1ed36dd2432a399fbeb843c2a0.tar.xz
linux-a8746417e864da1ed36dd2432a399fbeb843c2a0.zip
[Bluetooth] Track connection packet type changes
The connection packet type can be changed after the connection has been established and thus needs to be properly tracked to ensure that the host stack has always correct and valid information about it. On incoming connections the Bluetooth core switches the supported packet types to the configured list for this controller. However the usefulness of this feature has been questioned a lot. The general consent is that every Bluetooth host stack should enable as many packet types as the hardware actually supports and leave the decision to the link manager software running on the Bluetooth chip. When running on Bluetooth 2.0 or later hardware, don't change the packet type for incoming connections anymore. This hardware likely supports Enhanced Data Rate and thus leave it completely up to the link manager to pick the best packet type. Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/hci_event.c')
-rw-r--r--net/bluetooth/hci_event.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 6bc5a0506c6c..d4d2dcc40fc7 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -699,14 +699,12 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
}
/* Set packet type for incoming connection */
- if (!conn->out) {
+ if (!conn->out && hdev->hci_ver < 3) {
struct hci_cp_change_conn_ptype cp;
cp.handle = ev->handle;
- cp.pkt_type = (conn->type == ACL_LINK) ?
- cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK):
- cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);
-
- hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), &cp);
+ cp.pkt_type = cpu_to_le16(conn->pkt_type);
+ hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
+ sizeof(cp), &cp);
} else {
/* Update disconnect timer */
hci_conn_hold(conn);
@@ -786,7 +784,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
struct hci_cp_accept_sync_conn_req cp;
bacpy(&cp.bdaddr, &ev->bdaddr);
- cp.pkt_type = cpu_to_le16(hdev->esco_type);
+ cp.pkt_type = cpu_to_le16(conn->pkt_type);
cp.tx_bandwidth = cpu_to_le32(0x00001f40);
cp.rx_bandwidth = cpu_to_le32(0x00001f40);
@@ -1237,6 +1235,22 @@ static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_dev_unlock(hdev);
}
+static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_ev_pkt_type_change *ev = (void *) skb->data;
+ struct hci_conn *conn;
+
+ BT_DBG("%s status %d", hdev->name, ev->status);
+
+ hci_dev_lock(hdev);
+
+ conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
+ if (conn && !ev->status)
+ conn->pkt_type = __le16_to_cpu(ev->pkt_type);
+
+ hci_dev_unlock(hdev);
+}
+
static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
@@ -1480,6 +1494,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_clock_offset_evt(hdev, skb);
break;
+ case HCI_EV_PKT_TYPE_CHANGE:
+ hci_pkt_type_change_evt(hdev, skb);
+ break;
+
case HCI_EV_PSCAN_REP_MODE:
hci_pscan_rep_mode_evt(hdev, skb);
break;