aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2013-04-17 08:00:51 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2013-04-17 23:26:20 -0400
commitcad718ed2f6fd204b2c5cac6b611fc3fcde7b183 (patch)
tree3772acb4f9dc18f9a4c5dc4687aeba039eb2a1a0
parentfa5513be2b709c8ce6ff0b11d0715760a9a70ffd (diff)
Bluetooth: Track feature pages in a single table
The local and remote features are organized by page number. Page 0 are the LMP features, page 1 the host features, and any pages beyond 1 features that future core specification versions may define. So far we've only had the first two pages and two separate variables has been convenient enough, however with the introduction of Core Specification Addendum 4 there are features defined on page 2. Instead of requiring the addition of a new variable each time a new page number is defined, this patch refactors the code to use a single table for the features. The patch needs to update both the hci_dev and hci_conn structures since there are macros that depend on the features being represented in the same way in both of them. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
-rw-r--r--include/net/bluetooth/hci_core.h49
-rw-r--r--net/bluetooth/hci_event.c58
-rw-r--r--net/bluetooth/hci_sysfs.c16
3 files changed, 63 insertions, 60 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 74f77b7ef136..26822967e29c 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -134,6 +134,8 @@ struct amp_assoc {
134 __u8 data[HCI_MAX_AMP_ASSOC_SIZE]; 134 __u8 data[HCI_MAX_AMP_ASSOC_SIZE];
135}; 135};
136 136
137#define HCI_MAX_PAGES 2
138
137#define NUM_REASSEMBLY 4 139#define NUM_REASSEMBLY 4
138struct hci_dev { 140struct hci_dev {
139 struct list_head list; 141 struct list_head list;
@@ -151,8 +153,7 @@ struct hci_dev {
151 __u8 dev_class[3]; 153 __u8 dev_class[3];
152 __u8 major_class; 154 __u8 major_class;
153 __u8 minor_class; 155 __u8 minor_class;
154 __u8 features[8]; 156 __u8 features[HCI_MAX_PAGES][8];
155 __u8 host_features[8];
156 __u8 le_features[8]; 157 __u8 le_features[8];
157 __u8 le_white_list_size; 158 __u8 le_white_list_size;
158 __u8 le_states[8]; 159 __u8 le_states[8];
@@ -313,7 +314,7 @@ struct hci_conn {
313 bool out; 314 bool out;
314 __u8 attempt; 315 __u8 attempt;
315 __u8 dev_class[3]; 316 __u8 dev_class[3];
316 __u8 features[8]; 317 __u8 features[HCI_MAX_PAGES][8];
317 __u16 interval; 318 __u16 interval;
318 __u16 pkt_type; 319 __u16 pkt_type;
319 __u16 link_policy; 320 __u16 link_policy;
@@ -786,29 +787,29 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
786#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev)) 787#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev))
787 788
788/* ----- LMP capabilities ----- */ 789/* ----- LMP capabilities ----- */
789#define lmp_encrypt_capable(dev) ((dev)->features[0] & LMP_ENCRYPT) 790#define lmp_encrypt_capable(dev) ((dev)->features[0][0] & LMP_ENCRYPT)
790#define lmp_rswitch_capable(dev) ((dev)->features[0] & LMP_RSWITCH) 791#define lmp_rswitch_capable(dev) ((dev)->features[0][0] & LMP_RSWITCH)
791#define lmp_hold_capable(dev) ((dev)->features[0] & LMP_HOLD) 792#define lmp_hold_capable(dev) ((dev)->features[0][0] & LMP_HOLD)
792#define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF) 793#define lmp_sniff_capable(dev) ((dev)->features[0][0] & LMP_SNIFF)
793#define lmp_park_capable(dev) ((dev)->features[1] & LMP_PARK) 794#define lmp_park_capable(dev) ((dev)->features[0][1] & LMP_PARK)
794#define lmp_inq_rssi_capable(dev) ((dev)->features[3] & LMP_RSSI_INQ) 795#define lmp_inq_rssi_capable(dev) ((dev)->features[0][3] & LMP_RSSI_INQ)
795#define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO) 796#define lmp_esco_capable(dev) ((dev)->features[0][3] & LMP_ESCO)
796#define lmp_bredr_capable(dev) (!((dev)->features[4] & LMP_NO_BREDR)) 797#define lmp_bredr_capable(dev) (!((dev)->features[0][4] & LMP_NO_BREDR))
797#define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE) 798#define lmp_le_capable(dev) ((dev)->features[0][4] & LMP_LE)
798#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR) 799#define lmp_sniffsubr_capable(dev) ((dev)->features[0][5] & LMP_SNIFF_SUBR)
799#define lmp_pause_enc_capable(dev) ((dev)->features[5] & LMP_PAUSE_ENC) 800#define lmp_pause_enc_capable(dev) ((dev)->features[0][5] & LMP_PAUSE_ENC)
800#define lmp_ext_inq_capable(dev) ((dev)->features[6] & LMP_EXT_INQ) 801#define lmp_ext_inq_capable(dev) ((dev)->features[0][6] & LMP_EXT_INQ)
801#define lmp_le_br_capable(dev) !!((dev)->features[6] & LMP_SIMUL_LE_BR) 802#define lmp_le_br_capable(dev) (!!((dev)->features[0][6] & LMP_SIMUL_LE_BR))
802#define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR) 803#define lmp_ssp_capable(dev) ((dev)->features[0][6] & LMP_SIMPLE_PAIR)
803#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH) 804#define lmp_no_flush_capable(dev) ((dev)->features[0][6] & LMP_NO_FLUSH)
804#define lmp_lsto_capable(dev) ((dev)->features[7] & LMP_LSTO) 805#define lmp_lsto_capable(dev) ((dev)->features[0][7] & LMP_LSTO)
805#define lmp_inq_tx_pwr_capable(dev) ((dev)->features[7] & LMP_INQ_TX_PWR) 806#define lmp_inq_tx_pwr_capable(dev) ((dev)->features[0][7] & LMP_INQ_TX_PWR)
806#define lmp_ext_feat_capable(dev) ((dev)->features[7] & LMP_EXTFEATURES) 807#define lmp_ext_feat_capable(dev) ((dev)->features[0][7] & LMP_EXTFEATURES)
807 808
808/* ----- Extended LMP capabilities ----- */ 809/* ----- Extended LMP capabilities ----- */
809#define lmp_host_ssp_capable(dev) ((dev)->host_features[0] & LMP_HOST_SSP) 810#define lmp_host_ssp_capable(dev) ((dev)->features[1][0] & LMP_HOST_SSP)
810#define lmp_host_le_capable(dev) !!((dev)->host_features[0] & LMP_HOST_LE) 811#define lmp_host_le_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE))
811#define lmp_host_le_br_capable(dev) !!((dev)->host_features[0] & LMP_HOST_LE_BREDR) 812#define lmp_host_le_br_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE_BREDR))
812 813
813/* returns true if at least one AMP active */ 814/* returns true if at least one AMP active */
814static inline bool hci_amp_capable(void) 815static inline bool hci_amp_capable(void)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index e4d4d231fd8a..8adc3915ece4 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -433,9 +433,9 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
433 433
434 if (!status) { 434 if (!status) {
435 if (sent->mode) 435 if (sent->mode)
436 hdev->host_features[0] |= LMP_HOST_SSP; 436 hdev->features[1][0] |= LMP_HOST_SSP;
437 else 437 else
438 hdev->host_features[0] &= ~LMP_HOST_SSP; 438 hdev->features[1][0] &= ~LMP_HOST_SSP;
439 } 439 }
440 440
441 if (test_bit(HCI_MGMT, &hdev->dev_flags)) 441 if (test_bit(HCI_MGMT, &hdev->dev_flags))
@@ -493,18 +493,18 @@ static void hci_cc_read_local_features(struct hci_dev *hdev,
493 /* Adjust default settings according to features 493 /* Adjust default settings according to features
494 * supported by device. */ 494 * supported by device. */
495 495
496 if (hdev->features[0] & LMP_3SLOT) 496 if (hdev->features[0][0] & LMP_3SLOT)
497 hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 497 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
498 498
499 if (hdev->features[0] & LMP_5SLOT) 499 if (hdev->features[0][0] & LMP_5SLOT)
500 hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 500 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
501 501
502 if (hdev->features[1] & LMP_HV2) { 502 if (hdev->features[0][1] & LMP_HV2) {
503 hdev->pkt_type |= (HCI_HV2); 503 hdev->pkt_type |= (HCI_HV2);
504 hdev->esco_type |= (ESCO_HV2); 504 hdev->esco_type |= (ESCO_HV2);
505 } 505 }
506 506
507 if (hdev->features[1] & LMP_HV3) { 507 if (hdev->features[0][1] & LMP_HV3) {
508 hdev->pkt_type |= (HCI_HV3); 508 hdev->pkt_type |= (HCI_HV3);
509 hdev->esco_type |= (ESCO_HV3); 509 hdev->esco_type |= (ESCO_HV3);
510 } 510 }
@@ -512,26 +512,26 @@ static void hci_cc_read_local_features(struct hci_dev *hdev,
512 if (lmp_esco_capable(hdev)) 512 if (lmp_esco_capable(hdev))
513 hdev->esco_type |= (ESCO_EV3); 513 hdev->esco_type |= (ESCO_EV3);
514 514
515 if (hdev->features[4] & LMP_EV4) 515 if (hdev->features[0][4] & LMP_EV4)
516 hdev->esco_type |= (ESCO_EV4); 516 hdev->esco_type |= (ESCO_EV4);
517 517
518 if (hdev->features[4] & LMP_EV5) 518 if (hdev->features[0][4] & LMP_EV5)
519 hdev->esco_type |= (ESCO_EV5); 519 hdev->esco_type |= (ESCO_EV5);
520 520
521 if (hdev->features[5] & LMP_EDR_ESCO_2M) 521 if (hdev->features[0][5] & LMP_EDR_ESCO_2M)
522 hdev->esco_type |= (ESCO_2EV3); 522 hdev->esco_type |= (ESCO_2EV3);
523 523
524 if (hdev->features[5] & LMP_EDR_ESCO_3M) 524 if (hdev->features[0][5] & LMP_EDR_ESCO_3M)
525 hdev->esco_type |= (ESCO_3EV3); 525 hdev->esco_type |= (ESCO_3EV3);
526 526
527 if (hdev->features[5] & LMP_EDR_3S_ESCO) 527 if (hdev->features[0][5] & LMP_EDR_3S_ESCO)
528 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 528 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
529 529
530 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 530 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
531 hdev->features[0], hdev->features[1], 531 hdev->features[0][0], hdev->features[0][1],
532 hdev->features[2], hdev->features[3], 532 hdev->features[0][2], hdev->features[0][3],
533 hdev->features[4], hdev->features[5], 533 hdev->features[0][4], hdev->features[0][5],
534 hdev->features[6], hdev->features[7]); 534 hdev->features[0][6], hdev->features[0][7]);
535} 535}
536 536
537static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 537static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
@@ -544,14 +544,8 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
544 if (rp->status) 544 if (rp->status)
545 return; 545 return;
546 546
547 switch (rp->page) { 547 if (rp->page < HCI_MAX_PAGES)
548 case 0: 548 memcpy(hdev->features[rp->page], rp->features, 8);
549 memcpy(hdev->features, rp->features, 8);
550 break;
551 case 1:
552 memcpy(hdev->host_features, rp->features, 8);
553 break;
554 }
555} 549}
556 550
557static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 551static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
@@ -1046,14 +1040,14 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1046 1040
1047 if (!status) { 1041 if (!status) {
1048 if (sent->le) 1042 if (sent->le)
1049 hdev->host_features[0] |= LMP_HOST_LE; 1043 hdev->features[1][0] |= LMP_HOST_LE;
1050 else 1044 else
1051 hdev->host_features[0] &= ~LMP_HOST_LE; 1045 hdev->features[1][0] &= ~LMP_HOST_LE;
1052 1046
1053 if (sent->simul) 1047 if (sent->simul)
1054 hdev->host_features[0] |= LMP_HOST_LE_BREDR; 1048 hdev->features[1][0] |= LMP_HOST_LE_BREDR;
1055 else 1049 else
1056 hdev->host_features[0] &= ~LMP_HOST_LE_BREDR; 1050 hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
1057 } 1051 }
1058 1052
1059 if (test_bit(HCI_MGMT, &hdev->dev_flags) && 1053 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
@@ -2076,7 +2070,7 @@ static void hci_remote_features_evt(struct hci_dev *hdev,
2076 goto unlock; 2070 goto unlock;
2077 2071
2078 if (!ev->status) 2072 if (!ev->status)
2079 memcpy(conn->features, ev->features, 8); 2073 memcpy(conn->features[0], ev->features, 8);
2080 2074
2081 if (conn->state != BT_CONFIG) 2075 if (conn->state != BT_CONFIG)
2082 goto unlock; 2076 goto unlock;
@@ -2888,6 +2882,9 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev,
2888 if (!conn) 2882 if (!conn)
2889 goto unlock; 2883 goto unlock;
2890 2884
2885 if (ev->page < HCI_MAX_PAGES)
2886 memcpy(conn->features[ev->page], ev->features, 8);
2887
2891 if (!ev->status && ev->page == 0x01) { 2888 if (!ev->status && ev->page == 0x01) {
2892 struct inquiry_entry *ie; 2889 struct inquiry_entry *ie;
2893 2890
@@ -3346,11 +3343,16 @@ static void hci_remote_host_features_evt(struct hci_dev *hdev,
3346{ 3343{
3347 struct hci_ev_remote_host_features *ev = (void *) skb->data; 3344 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3348 struct inquiry_entry *ie; 3345 struct inquiry_entry *ie;
3346 struct hci_conn *conn;
3349 3347
3350 BT_DBG("%s", hdev->name); 3348 BT_DBG("%s", hdev->name);
3351 3349
3352 hci_dev_lock(hdev); 3350 hci_dev_lock(hdev);
3353 3351
3352 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3353 if (conn)
3354 memcpy(conn->features[1], ev->features, 8);
3355
3354 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3356 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3355 if (ie) 3357 if (ie)
3356 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 3358 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 6fe15c822847..7ad6ecf36f20 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -48,10 +48,10 @@ static ssize_t show_link_features(struct device *dev,
48 struct hci_conn *conn = to_hci_conn(dev); 48 struct hci_conn *conn = to_hci_conn(dev);
49 49
50 return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", 50 return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
51 conn->features[0], conn->features[1], 51 conn->features[0][0], conn->features[0][1],
52 conn->features[2], conn->features[3], 52 conn->features[0][2], conn->features[0][3],
53 conn->features[4], conn->features[5], 53 conn->features[0][4], conn->features[0][5],
54 conn->features[6], conn->features[7]); 54 conn->features[0][6], conn->features[0][7]);
55} 55}
56 56
57#define LINK_ATTR(_name, _mode, _show, _store) \ 57#define LINK_ATTR(_name, _mode, _show, _store) \
@@ -233,10 +233,10 @@ static ssize_t show_features(struct device *dev,
233 struct hci_dev *hdev = to_hci_dev(dev); 233 struct hci_dev *hdev = to_hci_dev(dev);
234 234
235 return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", 235 return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
236 hdev->features[0], hdev->features[1], 236 hdev->features[0][0], hdev->features[0][1],
237 hdev->features[2], hdev->features[3], 237 hdev->features[0][2], hdev->features[0][3],
238 hdev->features[4], hdev->features[5], 238 hdev->features[0][4], hdev->features[0][5],
239 hdev->features[6], hdev->features[7]); 239 hdev->features[0][6], hdev->features[0][7]);
240} 240}
241 241
242static ssize_t show_manufacturer(struct device *dev, 242static ssize_t show_manufacturer(struct device *dev,