aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2008-07-14 14:13:46 -0400
committerMarcel Holtmann <marcel@holtmann.org>2008-07-14 14:13:46 -0400
commita8746417e864da1ed36dd2432a399fbeb843c2a0 (patch)
treee0e392e8b76d53748f357e888483bced2de24e2b
parent9dc0a3afc08d6c20c284994dcd84531787d00ec2 (diff)
[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>
-rw-r--r--include/net/bluetooth/hci.h9
-rw-r--r--include/net/bluetooth/hci_core.h1
-rw-r--r--net/bluetooth/hci_conn.c32
-rw-r--r--net/bluetooth/hci_event.c32
4 files changed, 59 insertions, 15 deletions
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index a8a9eb6af966..f1dc174abc2a 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -137,6 +137,8 @@ enum {
137#define ESCO_EV4 0x0010 137#define ESCO_EV4 0x0010
138#define ESCO_EV5 0x0020 138#define ESCO_EV5 0x0020
139 139
140#define SCO_ESCO_MASK (ESCO_HV1 | ESCO_HV2 | ESCO_HV3)
141
140/* ACL flags */ 142/* ACL flags */
141#define ACL_CONT 0x01 143#define ACL_CONT 0x01
142#define ACL_START 0x02 144#define ACL_START 0x02
@@ -696,6 +698,13 @@ struct hci_ev_clock_offset {
696 __le16 clock_offset; 698 __le16 clock_offset;
697} __attribute__ ((packed)); 699} __attribute__ ((packed));
698 700
701#define HCI_EV_PKT_TYPE_CHANGE 0x1d
702struct hci_ev_pkt_type_change {
703 __u8 status;
704 __le16 handle;
705 __le16 pkt_type;
706} __attribute__ ((packed));
707
699#define HCI_EV_PSCAN_REP_MODE 0x20 708#define HCI_EV_PSCAN_REP_MODE 0x20
700struct hci_ev_pscan_rep_mode { 709struct hci_ev_pscan_rep_mode {
701 bdaddr_t bdaddr; 710 bdaddr_t bdaddr;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index c8255adee8f5..6424d63e3395 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -162,6 +162,7 @@ struct hci_conn {
162 __u8 dev_class[3]; 162 __u8 dev_class[3];
163 __u8 features[8]; 163 __u8 features[8];
164 __u16 interval; 164 __u16 interval;
165 __u16 pkt_type;
165 __u16 link_policy; 166 __u16 link_policy;
166 __u32 link_mode; 167 __u32 link_mode;
167 __u8 power_save; 168 __u8 power_save;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index f8880261da0e..69c64ce054fb 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -59,7 +59,8 @@ void hci_acl_connect(struct hci_conn *conn)
59 BT_DBG("%p", conn); 59 BT_DBG("%p", conn);
60 60
61 conn->state = BT_CONNECT; 61 conn->state = BT_CONNECT;
62 conn->out = 1; 62 conn->out = 1;
63
63 conn->link_mode = HCI_LM_MASTER; 64 conn->link_mode = HCI_LM_MASTER;
64 65
65 conn->attempt++; 66 conn->attempt++;
@@ -76,7 +77,7 @@ void hci_acl_connect(struct hci_conn *conn)
76 memcpy(conn->dev_class, ie->data.dev_class, 3); 77 memcpy(conn->dev_class, ie->data.dev_class, 3);
77 } 78 }
78 79
79 cp.pkt_type = cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK); 80 cp.pkt_type = cpu_to_le16(conn->pkt_type);
80 if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER)) 81 if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER))
81 cp.role_switch = 0x01; 82 cp.role_switch = 0x01;
82 else 83 else
@@ -122,7 +123,7 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle)
122 conn->out = 1; 123 conn->out = 1;
123 124
124 cp.handle = cpu_to_le16(handle); 125 cp.handle = cpu_to_le16(handle);
125 cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK); 126 cp.pkt_type = cpu_to_le16(conn->pkt_type);
126 127
127 hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp); 128 hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp);
128} 129}
@@ -138,7 +139,7 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
138 conn->out = 1; 139 conn->out = 1;
139 140
140 cp.handle = cpu_to_le16(handle); 141 cp.handle = cpu_to_le16(handle);
141 cp.pkt_type = cpu_to_le16(hdev->esco_type); 142 cp.pkt_type = cpu_to_le16(conn->pkt_type);
142 143
143 cp.tx_bandwidth = cpu_to_le32(0x00001f40); 144 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
144 cp.rx_bandwidth = cpu_to_le32(0x00001f40); 145 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
@@ -199,13 +200,28 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
199 return NULL; 200 return NULL;
200 201
201 bacpy(&conn->dst, dst); 202 bacpy(&conn->dst, dst);
202 conn->hdev = hdev; 203 conn->hdev = hdev;
203 conn->type = type; 204 conn->type = type;
204 conn->mode = HCI_CM_ACTIVE; 205 conn->mode = HCI_CM_ACTIVE;
205 conn->state = BT_OPEN; 206 conn->state = BT_OPEN;
206 207
207 conn->power_save = 1; 208 conn->power_save = 1;
208 209
210 switch (type) {
211 case ACL_LINK:
212 conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
213 break;
214 case SCO_LINK:
215 if (lmp_esco_capable(hdev))
216 conn->pkt_type = hdev->esco_type & SCO_ESCO_MASK;
217 else
218 conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK;
219 break;
220 case ESCO_LINK:
221 conn->pkt_type = hdev->esco_type;
222 break;
223 }
224
209 skb_queue_head_init(&conn->data_q); 225 skb_queue_head_init(&conn->data_q);
210 226
211 setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn); 227 setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn);
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
699 } 699 }
700 700
701 /* Set packet type for incoming connection */ 701 /* Set packet type for incoming connection */
702 if (!conn->out) { 702 if (!conn->out && hdev->hci_ver < 3) {
703 struct hci_cp_change_conn_ptype cp; 703 struct hci_cp_change_conn_ptype cp;
704 cp.handle = ev->handle; 704 cp.handle = ev->handle;
705 cp.pkt_type = (conn->type == ACL_LINK) ? 705 cp.pkt_type = cpu_to_le16(conn->pkt_type);
706 cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK): 706 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
707 cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK); 707 sizeof(cp), &cp);
708
709 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), &cp);
710 } else { 708 } else {
711 /* Update disconnect timer */ 709 /* Update disconnect timer */
712 hci_conn_hold(conn); 710 hci_conn_hold(conn);
@@ -786,7 +784,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
786 struct hci_cp_accept_sync_conn_req cp; 784 struct hci_cp_accept_sync_conn_req cp;
787 785
788 bacpy(&cp.bdaddr, &ev->bdaddr); 786 bacpy(&cp.bdaddr, &ev->bdaddr);
789 cp.pkt_type = cpu_to_le16(hdev->esco_type); 787 cp.pkt_type = cpu_to_le16(conn->pkt_type);
790 788
791 cp.tx_bandwidth = cpu_to_le32(0x00001f40); 789 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
792 cp.rx_bandwidth = cpu_to_le32(0x00001f40); 790 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
1237 hci_dev_unlock(hdev); 1235 hci_dev_unlock(hdev);
1238} 1236}
1239 1237
1238static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1239{
1240 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
1241 struct hci_conn *conn;
1242
1243 BT_DBG("%s status %d", hdev->name, ev->status);
1244
1245 hci_dev_lock(hdev);
1246
1247 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1248 if (conn && !ev->status)
1249 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
1250
1251 hci_dev_unlock(hdev);
1252}
1253
1240static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 1254static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
1241{ 1255{
1242 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 1256 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)
1480 hci_clock_offset_evt(hdev, skb); 1494 hci_clock_offset_evt(hdev, skb);
1481 break; 1495 break;
1482 1496
1497 case HCI_EV_PKT_TYPE_CHANGE:
1498 hci_pkt_type_change_evt(hdev, skb);
1499 break;
1500
1483 case HCI_EV_PSCAN_REP_MODE: 1501 case HCI_EV_PSCAN_REP_MODE:
1484 hci_pscan_rep_mode_evt(hdev, skb); 1502 hci_pscan_rep_mode_evt(hdev, skb);
1485 break; 1503 break;