aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2014-03-25 04:51:52 -0400
committerMarcel Holtmann <marcel@holtmann.org>2014-03-26 12:31:38 -0400
commitb9a6328f2a7f15490de7e45eabb025f8b74a81af (patch)
tree888d8c7c40aaabee58f82c5bd8a09ede666c7585
parent3c857757ef6e5a4e472bd3e5c934709c2eb482af (diff)
Bluetooth: Merge ADV_IND/ADV_SCAN_IND and SCAN_RSP together
To avoid too many events being sent to user space and to help parsing of all available remote device data it makes sense for us to wait for the scan response and send a single merged Device Found event to user space. This patch adds a few new variables to hci_dev to track the last received ADV_IND/ADV_SCAN_IND, i.e. those which will cause a SCAN_REQ to be send in the case of active scanning. When the SCAN_RSP is received the pending data is passed together with the SCAN_RSP to the mgmt_device_found function which takes care of merging them into a single Device Found event. We also need a bit of extra logic to handle situations where we don't receive a SCAN_RSP after caching some data. In such a scenario we simply have to send out the pending data as it is and then operate on the new report as if there was no pending data. We also need to send out any pending data when scanning stops as well as ensure that the storage is empty at the start of a new active scanning session. These both cases are covered by the update to the hci_cc_le_set_scan_enable function in this patch. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/bluetooth/hci_core.h4
-rw-r--r--net/bluetooth/hci_event.c103
2 files changed, 105 insertions, 2 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index a1b8eab8a47d..59b112397d39 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -68,6 +68,10 @@ struct discovery_state {
68 struct list_head unknown; /* Name state not known */ 68 struct list_head unknown; /* Name state not known */
69 struct list_head resolve; /* Name needs to be resolved */ 69 struct list_head resolve; /* Name needs to be resolved */
70 __u32 timestamp; 70 __u32 timestamp;
71 bdaddr_t last_adv_addr;
72 u8 last_adv_addr_type;
73 u8 last_adv_data[HCI_MAX_AD_LENGTH];
74 u8 last_adv_data_len;
71}; 75};
72 76
73struct hci_conn_hash { 77struct hci_conn_hash {
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 81e5236a0119..5816a13c5342 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1033,6 +1033,32 @@ static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1033 hci_dev_unlock(hdev); 1033 hci_dev_unlock(hdev);
1034} 1034}
1035 1035
1036static bool has_pending_adv_report(struct hci_dev *hdev)
1037{
1038 struct discovery_state *d = &hdev->discovery;
1039
1040 return bacmp(&d->last_adv_addr, BDADDR_ANY);
1041}
1042
1043static void clear_pending_adv_report(struct hci_dev *hdev)
1044{
1045 struct discovery_state *d = &hdev->discovery;
1046
1047 bacpy(&d->last_adv_addr, BDADDR_ANY);
1048 d->last_adv_data_len = 0;
1049}
1050
1051static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr,
1052 u8 bdaddr_type, u8 *data, u8 len)
1053{
1054 struct discovery_state *d = &hdev->discovery;
1055
1056 bacpy(&d->last_adv_addr, bdaddr);
1057 d->last_adv_addr_type = bdaddr_type;
1058 memcpy(d->last_adv_data, data, len);
1059 d->last_adv_data_len = len;
1060}
1061
1036static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 1062static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1037 struct sk_buff *skb) 1063 struct sk_buff *skb)
1038{ 1064{
@@ -1051,9 +1077,24 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1051 switch (cp->enable) { 1077 switch (cp->enable) {
1052 case LE_SCAN_ENABLE: 1078 case LE_SCAN_ENABLE:
1053 set_bit(HCI_LE_SCAN, &hdev->dev_flags); 1079 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1080 if (hdev->le_scan_type == LE_SCAN_ACTIVE)
1081 clear_pending_adv_report(hdev);
1054 break; 1082 break;
1055 1083
1056 case LE_SCAN_DISABLE: 1084 case LE_SCAN_DISABLE:
1085 /* We do this here instead of when setting DISCOVERY_STOPPED
1086 * since the latter would potentially require waiting for
1087 * inquiry to stop too.
1088 */
1089 if (has_pending_adv_report(hdev)) {
1090 struct discovery_state *d = &hdev->discovery;
1091
1092 mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
1093 d->last_adv_addr_type, NULL, 0, 0,
1094 1, d->last_adv_data,
1095 d->last_adv_data_len, NULL, 0);
1096 }
1097
1057 /* Cancel this timer so that we don't try to disable scanning 1098 /* Cancel this timer so that we don't try to disable scanning
1058 * when it's already disabled. 1099 * when it's already disabled.
1059 */ 1100 */
@@ -3979,6 +4020,8 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
3979static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, 4020static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
3980 u8 bdaddr_type, s8 rssi, u8 *data, u8 len) 4021 u8 bdaddr_type, s8 rssi, u8 *data, u8 len)
3981{ 4022{
4023 struct discovery_state *d = &hdev->discovery;
4024
3982 /* Passive scanning shouldn't trigger any device found events */ 4025 /* Passive scanning shouldn't trigger any device found events */
3983 if (hdev->le_scan_type == LE_SCAN_PASSIVE) { 4026 if (hdev->le_scan_type == LE_SCAN_PASSIVE) {
3984 if (type == LE_ADV_IND || type == LE_ADV_DIRECT_IND) 4027 if (type == LE_ADV_IND || type == LE_ADV_DIRECT_IND)
@@ -3986,8 +4029,64 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
3986 return; 4029 return;
3987 } 4030 }
3988 4031
3989 mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, rssi, 0, 1, 4032 /* If there's nothing pending either store the data from this
3990 data, len, NULL, 0); 4033 * event or send an immediate device found event if the data
4034 * should not be stored for later.
4035 */
4036 if (!has_pending_adv_report(hdev)) {
4037 /* If the report will trigger a SCAN_REQ store it for
4038 * later merging.
4039 */
4040 if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
4041 store_pending_adv_report(hdev, bdaddr, bdaddr_type,
4042 data, len);
4043 return;
4044 }
4045
4046 mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
4047 rssi, 0, 1, data, len, NULL, 0);
4048 return;
4049 }
4050
4051 /* If the pending data doesn't match this report or this isn't a
4052 * scan response (e.g. we got a duplicate ADV_IND) then force
4053 * sending of the pending data.
4054 */
4055 if (type != LE_ADV_SCAN_RSP || bacmp(bdaddr, &d->last_adv_addr) ||
4056 bdaddr_type != d->last_adv_addr_type) {
4057 /* Send out whatever is in the cache */
4058 mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
4059 d->last_adv_addr_type, NULL, 0, 0, 1,
4060 d->last_adv_data, d->last_adv_data_len,
4061 NULL, 0);
4062
4063 /* If the new report will trigger a SCAN_REQ store it for
4064 * later merging.
4065 */
4066 if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
4067 store_pending_adv_report(hdev, bdaddr, bdaddr_type,
4068 data, len);
4069 return;
4070 }
4071
4072 /* The advertising reports cannot be merged, so clear
4073 * the pending report and send out a device found event.
4074 */
4075 clear_pending_adv_report(hdev);
4076 mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
4077 d->last_adv_addr_type, NULL, rssi, 0, 1,
4078 data, len, NULL, 0);
4079 return;
4080 }
4081
4082 /* If we get here we've got a pending ADV_IND or ADV_SCAN_IND and
4083 * the new event is a SCAN_RSP. We can therefore proceed with
4084 * sending a merged device found event.
4085 */
4086 mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
4087 d->last_adv_addr_type, NULL, rssi, 0, 1, data, len,
4088 d->last_adv_data, d->last_adv_data_len);
4089 clear_pending_adv_report(hdev);
3991} 4090}
3992 4091
3993static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) 4092static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)