summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Grandel <fgrandel@gmail.com>2015-06-17 21:16:34 -0400
committerMarcel Holtmann <marcel@holtmann.org>2015-06-18 12:11:51 -0400
commitd2609b345ebf0547015a78588c4d7ad68c9ccf26 (patch)
tree2b0d35d71227e87a1b1906158bada9dbb63e8fe1
parentaebceccc18bf49f8fb208ac4548b7bd402b6662c (diff)
Bluetooth: hci_core/mgmt: Introduce multi-adv list
The current hci dev structure only supports a single advertising instance. To support multi-instance advertising it is necessary to introduce a linked list of advertising instances so that multiple advertising instances can be dynamically added and/or removed. In a first step, the existing adv_instance member of the hci_dev struct is supplemented by a linked list of advertising instances. This patch introduces the list and supporting list management infrastructure. The list is not being used yet. Signed-off-by: Florian Grandel <fgrandel@gmail.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/bluetooth/hci_core.h17
-rw-r--r--net/bluetooth/hci_core.c117
-rw-r--r--net/bluetooth/mgmt.c2
3 files changed, 135 insertions, 1 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 3fbb793e634d..4242dbfb4cf5 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -157,15 +157,20 @@ struct oob_data {
157 157
158struct adv_info { 158struct adv_info {
159 struct delayed_work timeout_exp; 159 struct delayed_work timeout_exp;
160 struct list_head list;
160 __u8 instance; 161 __u8 instance;
161 __u32 flags; 162 __u32 flags;
162 __u16 timeout; 163 __u16 timeout;
164 __u16 duration;
163 __u16 adv_data_len; 165 __u16 adv_data_len;
164 __u8 adv_data[HCI_MAX_AD_LENGTH]; 166 __u8 adv_data[HCI_MAX_AD_LENGTH];
165 __u16 scan_rsp_len; 167 __u16 scan_rsp_len;
166 __u8 scan_rsp_data[HCI_MAX_AD_LENGTH]; 168 __u8 scan_rsp_data[HCI_MAX_AD_LENGTH];
167}; 169};
168 170
171#define HCI_MAX_ADV_INSTANCES 1
172#define HCI_DEFAULT_ADV_DURATION 2
173
169#define HCI_MAX_SHORT_NAME_LENGTH 10 174#define HCI_MAX_SHORT_NAME_LENGTH 10
170 175
171/* Default LE RPA expiry time, 15 minutes */ 176/* Default LE RPA expiry time, 15 minutes */
@@ -374,6 +379,9 @@ struct hci_dev {
374 __u8 scan_rsp_data_len; 379 __u8 scan_rsp_data_len;
375 380
376 struct adv_info adv_instance; 381 struct adv_info adv_instance;
382 struct list_head adv_instances;
383 unsigned int adv_instance_cnt;
384 __u8 cur_adv_instance;
377 385
378 __u8 irk[16]; 386 __u8 irk[16];
379 __u32 rpa_timeout; 387 __u32 rpa_timeout;
@@ -1019,6 +1027,15 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
1019int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, 1027int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
1020 u8 bdaddr_type); 1028 u8 bdaddr_type);
1021 1029
1030void hci_adv_instances_clear(struct hci_dev *hdev);
1031struct adv_info *hci_find_adv_instance(struct hci_dev *hdev, u8 instance);
1032struct adv_info *hci_get_next_instance(struct hci_dev *hdev, u8 instance);
1033int hci_add_adv_instance(struct hci_dev *hdev, u8 instance, u32 flags,
1034 u16 adv_data_len, u8 *adv_data,
1035 u16 scan_rsp_len, u8 *scan_rsp_data,
1036 u16 timeout, u16 duration);
1037int hci_remove_adv_instance(struct hci_dev *hdev, u8 instance);
1038
1022void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); 1039void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
1023 1040
1024int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb); 1041int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 573711c2d09e..ebf37ebcfd12 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2610,6 +2610,119 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
2610 return 0; 2610 return 0;
2611} 2611}
2612 2612
2613/* This function requires the caller holds hdev->lock */
2614struct adv_info *hci_find_adv_instance(struct hci_dev *hdev, u8 instance)
2615{
2616 struct adv_info *adv_instance;
2617
2618 list_for_each_entry(adv_instance, &hdev->adv_instances, list) {
2619 if (adv_instance->instance == instance)
2620 return adv_instance;
2621 }
2622
2623 return NULL;
2624}
2625
2626/* This function requires the caller holds hdev->lock */
2627struct adv_info *hci_get_next_instance(struct hci_dev *hdev, u8 instance) {
2628 struct adv_info *cur_instance;
2629
2630 cur_instance = hci_find_adv_instance(hdev, instance);
2631 if (!cur_instance)
2632 return NULL;
2633
2634 if (cur_instance == list_last_entry(&hdev->adv_instances,
2635 struct adv_info, list))
2636 return list_first_entry(&hdev->adv_instances,
2637 struct adv_info, list);
2638 else
2639 return list_next_entry(cur_instance, list);
2640}
2641
2642/* This function requires the caller holds hdev->lock */
2643int hci_remove_adv_instance(struct hci_dev *hdev, u8 instance)
2644{
2645 struct adv_info *adv_instance;
2646
2647 adv_instance = hci_find_adv_instance(hdev, instance);
2648 if (!adv_instance)
2649 return -ENOENT;
2650
2651 BT_DBG("%s removing %dMR", hdev->name, instance);
2652
2653 list_del(&adv_instance->list);
2654 kfree(adv_instance);
2655
2656 hdev->adv_instance_cnt--;
2657
2658 return 0;
2659}
2660
2661/* This function requires the caller holds hdev->lock */
2662void hci_adv_instances_clear(struct hci_dev *hdev)
2663{
2664 struct adv_info *adv_instance, *n;
2665
2666 list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, list) {
2667 list_del(&adv_instance->list);
2668 kfree(adv_instance);
2669 }
2670
2671 hdev->adv_instance_cnt = 0;
2672}
2673
2674/* This function requires the caller holds hdev->lock */
2675int hci_add_adv_instance(struct hci_dev *hdev, u8 instance, u32 flags,
2676 u16 adv_data_len, u8 *adv_data,
2677 u16 scan_rsp_len, u8 *scan_rsp_data,
2678 u16 timeout, u16 duration)
2679{
2680 struct adv_info *adv_instance;
2681
2682 adv_instance = hci_find_adv_instance(hdev, instance);
2683 if (adv_instance) {
2684 memset(adv_instance->adv_data, 0,
2685 sizeof(adv_instance->adv_data));
2686 memset(adv_instance->scan_rsp_data, 0,
2687 sizeof(adv_instance->scan_rsp_data));
2688 } else {
2689 if (hdev->adv_instance_cnt >= HCI_MAX_ADV_INSTANCES ||
2690 instance < 1 || instance > HCI_MAX_ADV_INSTANCES)
2691 return -EOVERFLOW;
2692
2693 adv_instance = kmalloc(sizeof(*adv_instance), GFP_KERNEL);
2694 if (!adv_instance)
2695 return -ENOMEM;
2696
2697 memset(adv_instance, 0, sizeof(*adv_instance));
2698 adv_instance->instance = instance;
2699 list_add(&adv_instance->list, &hdev->adv_instances);
2700 hdev->adv_instance_cnt++;
2701 }
2702
2703 adv_instance->flags = flags;
2704 adv_instance->adv_data_len = adv_data_len;
2705 adv_instance->scan_rsp_len = scan_rsp_len;
2706
2707 if (adv_data_len)
2708 memcpy(adv_instance->adv_data, adv_data, adv_data_len);
2709
2710 if (scan_rsp_len)
2711 memcpy(adv_instance->scan_rsp_data,
2712 scan_rsp_data, scan_rsp_len);
2713
2714 adv_instance->timeout = timeout;
2715
2716 if (duration == 0)
2717 adv_instance->duration = HCI_DEFAULT_ADV_DURATION;
2718 else
2719 adv_instance->duration = duration;
2720
2721 BT_DBG("%s for %dMR", hdev->name, instance);
2722
2723 return 0;
2724}
2725
2613struct bdaddr_list *hci_bdaddr_list_lookup(struct list_head *bdaddr_list, 2726struct bdaddr_list *hci_bdaddr_list_lookup(struct list_head *bdaddr_list,
2614 bdaddr_t *bdaddr, u8 type) 2727 bdaddr_t *bdaddr, u8 type)
2615{ 2728{
@@ -3015,6 +3128,8 @@ struct hci_dev *hci_alloc_dev(void)
3015 hdev->manufacturer = 0xffff; /* Default to internal use */ 3128 hdev->manufacturer = 0xffff; /* Default to internal use */
3016 hdev->inq_tx_power = HCI_TX_POWER_INVALID; 3129 hdev->inq_tx_power = HCI_TX_POWER_INVALID;
3017 hdev->adv_tx_power = HCI_TX_POWER_INVALID; 3130 hdev->adv_tx_power = HCI_TX_POWER_INVALID;
3131 hdev->adv_instance_cnt = 0;
3132 hdev->cur_adv_instance = 0x00;
3018 3133
3019 hdev->sniff_max_interval = 800; 3134 hdev->sniff_max_interval = 800;
3020 hdev->sniff_min_interval = 80; 3135 hdev->sniff_min_interval = 80;
@@ -3056,6 +3171,7 @@ struct hci_dev *hci_alloc_dev(void)
3056 INIT_LIST_HEAD(&hdev->pend_le_conns); 3171 INIT_LIST_HEAD(&hdev->pend_le_conns);
3057 INIT_LIST_HEAD(&hdev->pend_le_reports); 3172 INIT_LIST_HEAD(&hdev->pend_le_reports);
3058 INIT_LIST_HEAD(&hdev->conn_hash.list); 3173 INIT_LIST_HEAD(&hdev->conn_hash.list);
3174 INIT_LIST_HEAD(&hdev->adv_instances);
3059 3175
3060 INIT_WORK(&hdev->rx_work, hci_rx_work); 3176 INIT_WORK(&hdev->rx_work, hci_rx_work);
3061 INIT_WORK(&hdev->cmd_work, hci_cmd_work); 3177 INIT_WORK(&hdev->cmd_work, hci_cmd_work);
@@ -3249,6 +3365,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
3249 hci_smp_ltks_clear(hdev); 3365 hci_smp_ltks_clear(hdev);
3250 hci_smp_irks_clear(hdev); 3366 hci_smp_irks_clear(hdev);
3251 hci_remote_oob_data_clear(hdev); 3367 hci_remote_oob_data_clear(hdev);
3368 hci_adv_instances_clear(hdev);
3252 hci_bdaddr_list_clear(&hdev->le_white_list); 3369 hci_bdaddr_list_clear(&hdev->le_white_list);
3253 hci_conn_params_clear_all(hdev); 3370 hci_conn_params_clear_all(hdev);
3254 hci_discovery_filter_clear(hdev); 3371 hci_discovery_filter_clear(hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index e41bbe28a36e..92c50a17fdf9 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -6813,7 +6813,7 @@ static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
6813 rp->supported_flags = cpu_to_le32(supported_flags); 6813 rp->supported_flags = cpu_to_le32(supported_flags);
6814 rp->max_adv_data_len = HCI_MAX_AD_LENGTH; 6814 rp->max_adv_data_len = HCI_MAX_AD_LENGTH;
6815 rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH; 6815 rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH;
6816 rp->max_instances = 1; 6816 rp->max_instances = HCI_MAX_ADV_INSTANCES;
6817 6817
6818 /* Currently only one instance is supported, so simply return the 6818 /* Currently only one instance is supported, so simply return the
6819 * current instance number. 6819 * current instance number.