Loading MAINTAINERS +1 −0 Original line number Original line Diff line number Diff line Loading @@ -154,6 +154,7 @@ L: linux-zigbee-devel@lists.sourceforge.net (moderated for non-subscribers) L: linux-bluetooth@vger.kernel.org L: linux-bluetooth@vger.kernel.org S: Maintained S: Maintained F: net/6lowpan/ F: net/6lowpan/ F: include/net/6lowpan.h 6PACK NETWORK DRIVER FOR AX.25 6PACK NETWORK DRIVER FOR AX.25 M: Andreas Koensgen <ajk@comnets.uni-bremen.de> M: Andreas Koensgen <ajk@comnets.uni-bremen.de> Loading include/net/bluetooth/hci.h +4 −0 Original line number Original line Diff line number Diff line Loading @@ -1074,6 +1074,8 @@ struct hci_rp_read_data_block_size { __le16 num_blocks; __le16 num_blocks; } __packed; } __packed; #define HCI_OP_READ_LOCAL_CODECS 0x100b #define HCI_OP_READ_PAGE_SCAN_ACTIVITY 0x0c1b #define HCI_OP_READ_PAGE_SCAN_ACTIVITY 0x0c1b struct hci_rp_read_page_scan_activity { struct hci_rp_read_page_scan_activity { __u8 status; __u8 status; Loading Loading @@ -1170,6 +1172,8 @@ struct hci_rp_write_remote_amp_assoc { __u8 phy_handle; __u8 phy_handle; } __packed; } __packed; #define HCI_OP_GET_MWS_TRANSPORT_CONFIG 0x140c #define HCI_OP_ENABLE_DUT_MODE 0x1803 #define HCI_OP_ENABLE_DUT_MODE 0x1803 #define HCI_OP_WRITE_SSP_DEBUG_MODE 0x1804 #define HCI_OP_WRITE_SSP_DEBUG_MODE 0x1804 Loading include/net/bluetooth/hci_core.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -203,6 +203,8 @@ struct hci_dev { __u16 page_scan_window; __u16 page_scan_window; __u8 page_scan_type; __u8 page_scan_type; __u8 le_adv_channel_map; __u8 le_adv_channel_map; __u16 le_adv_min_interval; __u16 le_adv_max_interval; __u8 le_scan_type; __u8 le_scan_type; __u16 le_scan_interval; __u16 le_scan_interval; __u16 le_scan_window; __u16 le_scan_window; Loading Loading @@ -458,6 +460,7 @@ struct hci_conn_params { enum { enum { HCI_AUTO_CONN_DISABLED, HCI_AUTO_CONN_DISABLED, HCI_AUTO_CONN_REPORT, HCI_AUTO_CONN_REPORT, HCI_AUTO_CONN_DIRECT, HCI_AUTO_CONN_ALWAYS, HCI_AUTO_CONN_ALWAYS, HCI_AUTO_CONN_LINK_LOSS, HCI_AUTO_CONN_LINK_LOSS, } auto_connect; } auto_connect; Loading net/bluetooth/hci_core.c +180 −1 Original line number Original line Diff line number Diff line Loading @@ -970,6 +970,62 @@ static int adv_channel_map_get(void *data, u64 *val) DEFINE_SIMPLE_ATTRIBUTE(adv_channel_map_fops, adv_channel_map_get, DEFINE_SIMPLE_ATTRIBUTE(adv_channel_map_fops, adv_channel_map_get, adv_channel_map_set, "%llu\n"); adv_channel_map_set, "%llu\n"); static int adv_min_interval_set(void *data, u64 val) { struct hci_dev *hdev = data; if (val < 0x0020 || val > 0x4000 || val > hdev->le_adv_max_interval) return -EINVAL; hci_dev_lock(hdev); hdev->le_adv_min_interval = val; hci_dev_unlock(hdev); return 0; } static int adv_min_interval_get(void *data, u64 *val) { struct hci_dev *hdev = data; hci_dev_lock(hdev); *val = hdev->le_adv_min_interval; hci_dev_unlock(hdev); return 0; } DEFINE_SIMPLE_ATTRIBUTE(adv_min_interval_fops, adv_min_interval_get, adv_min_interval_set, "%llu\n"); static int adv_max_interval_set(void *data, u64 val) { struct hci_dev *hdev = data; if (val < 0x0020 || val > 0x4000 || val < hdev->le_adv_min_interval) return -EINVAL; hci_dev_lock(hdev); hdev->le_adv_max_interval = val; hci_dev_unlock(hdev); return 0; } static int adv_max_interval_get(void *data, u64 *val) { struct hci_dev *hdev = data; hci_dev_lock(hdev); *val = hdev->le_adv_max_interval; hci_dev_unlock(hdev); return 0; } DEFINE_SIMPLE_ATTRIBUTE(adv_max_interval_fops, adv_max_interval_get, adv_max_interval_set, "%llu\n"); static int device_list_show(struct seq_file *f, void *ptr) static int device_list_show(struct seq_file *f, void *ptr) { { struct hci_dev *hdev = f->private; struct hci_dev *hdev = f->private; Loading Loading @@ -1567,7 +1623,7 @@ static void hci_set_le_support(struct hci_request *req) if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { cp.le = 0x01; cp.le = 0x01; cp.simul = lmp_le_br_capable(hdev); cp.simul = 0x00; } } if (cp.le != lmp_host_le_capable(hdev)) if (cp.le != lmp_host_le_capable(hdev)) Loading Loading @@ -1686,6 +1742,14 @@ static void hci_init4_req(struct hci_request *req, unsigned long opt) if (hdev->commands[22] & 0x04) if (hdev->commands[22] & 0x04) hci_set_event_mask_page_2(req); hci_set_event_mask_page_2(req); /* Read local codec list if the HCI command is supported */ if (hdev->commands[29] & 0x20) hci_req_add(req, HCI_OP_READ_LOCAL_CODECS, 0, NULL); /* Get MWS transport configuration if the HCI command is supported */ if (hdev->commands[30] & 0x08) hci_req_add(req, HCI_OP_GET_MWS_TRANSPORT_CONFIG, 0, NULL); /* Check for Synchronization Train support */ /* Check for Synchronization Train support */ if (lmp_sync_train_capable(hdev)) if (lmp_sync_train_capable(hdev)) hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL); hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL); Loading Loading @@ -1825,6 +1889,10 @@ static int __hci_init(struct hci_dev *hdev) hdev, &supervision_timeout_fops); hdev, &supervision_timeout_fops); debugfs_create_file("adv_channel_map", 0644, hdev->debugfs, debugfs_create_file("adv_channel_map", 0644, hdev->debugfs, hdev, &adv_channel_map_fops); hdev, &adv_channel_map_fops); debugfs_create_file("adv_min_interval", 0644, hdev->debugfs, hdev, &adv_min_interval_fops); debugfs_create_file("adv_max_interval", 0644, hdev->debugfs, hdev, &adv_max_interval_fops); debugfs_create_file("device_list", 0444, hdev->debugfs, hdev, debugfs_create_file("device_list", 0444, hdev->debugfs, hdev, &device_list_fops); &device_list_fops); debugfs_create_u16("discov_interleaved_timeout", 0644, debugfs_create_u16("discov_interleaved_timeout", 0644, Loading Loading @@ -3639,6 +3707,7 @@ int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type, list_add(¶ms->action, &hdev->pend_le_reports); list_add(¶ms->action, &hdev->pend_le_reports); hci_update_background_scan(hdev); hci_update_background_scan(hdev); break; break; case HCI_AUTO_CONN_DIRECT: case HCI_AUTO_CONN_ALWAYS: case HCI_AUTO_CONN_ALWAYS: if (!is_connected(hdev, addr, addr_type)) { if (!is_connected(hdev, addr, addr_type)) { list_add(¶ms->action, &hdev->pend_le_conns); list_add(¶ms->action, &hdev->pend_le_conns); Loading Loading @@ -3914,6 +3983,8 @@ struct hci_dev *hci_alloc_dev(void) hdev->sniff_min_interval = 80; hdev->sniff_min_interval = 80; hdev->le_adv_channel_map = 0x07; hdev->le_adv_channel_map = 0x07; hdev->le_adv_min_interval = 0x0800; hdev->le_adv_max_interval = 0x0800; hdev->le_scan_interval = 0x0060; hdev->le_scan_interval = 0x0060; hdev->le_scan_window = 0x0030; hdev->le_scan_window = 0x0030; hdev->le_conn_min_interval = 0x0028; hdev->le_conn_min_interval = 0x0028; Loading Loading @@ -5397,12 +5468,113 @@ void hci_req_add_le_scan_disable(struct hci_request *req) hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); } } static void add_to_white_list(struct hci_request *req, struct hci_conn_params *params) { struct hci_cp_le_add_to_white_list cp; cp.bdaddr_type = params->addr_type; bacpy(&cp.bdaddr, ¶ms->addr); hci_req_add(req, HCI_OP_LE_ADD_TO_WHITE_LIST, sizeof(cp), &cp); } static u8 update_white_list(struct hci_request *req) { struct hci_dev *hdev = req->hdev; struct hci_conn_params *params; struct bdaddr_list *b; uint8_t white_list_entries = 0; /* Go through the current white list programmed into the * controller one by one and check if that address is still * in the list of pending connections or list of devices to * report. If not present in either list, then queue the * command to remove it from the controller. */ list_for_each_entry(b, &hdev->le_white_list, list) { struct hci_cp_le_del_from_white_list cp; if (hci_pend_le_action_lookup(&hdev->pend_le_conns, &b->bdaddr, b->bdaddr_type) || hci_pend_le_action_lookup(&hdev->pend_le_reports, &b->bdaddr, b->bdaddr_type)) { white_list_entries++; continue; } cp.bdaddr_type = b->bdaddr_type; bacpy(&cp.bdaddr, &b->bdaddr); hci_req_add(req, HCI_OP_LE_DEL_FROM_WHITE_LIST, sizeof(cp), &cp); } /* Since all no longer valid white list entries have been * removed, walk through the list of pending connections * and ensure that any new device gets programmed into * the controller. * * If the list of the devices is larger than the list of * available white list entries in the controller, then * just abort and return filer policy value to not use the * white list. */ list_for_each_entry(params, &hdev->pend_le_conns, action) { if (hci_bdaddr_list_lookup(&hdev->le_white_list, ¶ms->addr, params->addr_type)) continue; if (white_list_entries >= hdev->le_white_list_size) { /* Select filter policy to accept all advertising */ return 0x00; } if (hci_find_irk_by_addr(hdev, ¶ms->addr, params->addr_type)) { /* White list can not be used with RPAs */ return 0x00; } white_list_entries++; add_to_white_list(req, params); } /* After adding all new pending connections, walk through * the list of pending reports and also add these to the * white list if there is still space. */ list_for_each_entry(params, &hdev->pend_le_reports, action) { if (hci_bdaddr_list_lookup(&hdev->le_white_list, ¶ms->addr, params->addr_type)) continue; if (white_list_entries >= hdev->le_white_list_size) { /* Select filter policy to accept all advertising */ return 0x00; } if (hci_find_irk_by_addr(hdev, ¶ms->addr, params->addr_type)) { /* White list can not be used with RPAs */ return 0x00; } white_list_entries++; add_to_white_list(req, params); } /* Select filter policy to use white list */ return 0x01; } void hci_req_add_le_passive_scan(struct hci_request *req) void hci_req_add_le_passive_scan(struct hci_request *req) { { struct hci_cp_le_set_scan_param param_cp; struct hci_cp_le_set_scan_param param_cp; struct hci_cp_le_set_scan_enable enable_cp; struct hci_cp_le_set_scan_enable enable_cp; struct hci_dev *hdev = req->hdev; struct hci_dev *hdev = req->hdev; u8 own_addr_type; u8 own_addr_type; u8 filter_policy; /* Set require_privacy to false since no SCAN_REQ are send /* Set require_privacy to false since no SCAN_REQ are send * during passive scanning. Not using an unresolvable address * during passive scanning. Not using an unresolvable address Loading @@ -5413,11 +5585,18 @@ void hci_req_add_le_passive_scan(struct hci_request *req) if (hci_update_random_address(req, false, &own_addr_type)) if (hci_update_random_address(req, false, &own_addr_type)) return; return; /* Adding or removing entries from the white list must * happen before enabling scanning. The controller does * not allow white list modification while scanning. */ filter_policy = update_white_list(req); memset(¶m_cp, 0, sizeof(param_cp)); memset(¶m_cp, 0, sizeof(param_cp)); param_cp.type = LE_SCAN_PASSIVE; param_cp.type = LE_SCAN_PASSIVE; param_cp.interval = cpu_to_le16(hdev->le_scan_interval); param_cp.interval = cpu_to_le16(hdev->le_scan_interval); param_cp.window = cpu_to_le16(hdev->le_scan_window); param_cp.window = cpu_to_le16(hdev->le_scan_window); param_cp.own_address_type = own_addr_type; param_cp.own_address_type = own_addr_type; param_cp.filter_policy = filter_policy; hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), ¶m_cp); ¶m_cp); Loading net/bluetooth/hci_event.c +27 −8 Original line number Original line Diff line number Diff line Loading @@ -317,7 +317,7 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) if (param & SCAN_PAGE) if (param & SCAN_PAGE) set_bit(HCI_PSCAN, &hdev->flags); set_bit(HCI_PSCAN, &hdev->flags); else else clear_bit(HCI_ISCAN, &hdev->flags); clear_bit(HCI_PSCAN, &hdev->flags); done: done: hci_dev_unlock(hdev); hci_dev_unlock(hdev); Loading Loading @@ -2259,6 +2259,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) break; break; /* Fall through */ /* Fall through */ case HCI_AUTO_CONN_DIRECT: case HCI_AUTO_CONN_ALWAYS: case HCI_AUTO_CONN_ALWAYS: list_del_init(¶ms->action); list_del_init(¶ms->action); list_add(¶ms->action, &hdev->pend_le_conns); list_add(¶ms->action, &hdev->pend_le_conns); Loading Loading @@ -4251,6 +4252,7 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type, u8 adv_type) u8 addr_type, u8 adv_type) { { struct hci_conn *conn; struct hci_conn *conn; struct hci_conn_params *params; /* If the event is not connectable don't proceed further */ /* If the event is not connectable don't proceed further */ if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND) if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND) Loading @@ -4266,18 +4268,35 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr, if (hdev->conn_hash.le_num_slave > 0) if (hdev->conn_hash.le_num_slave > 0) return; return; /* If we're connectable, always connect any ADV_DIRECT_IND event */ if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) && adv_type == LE_ADV_DIRECT_IND) goto connect; /* If we're not connectable only connect devices that we have in /* If we're not connectable only connect devices that we have in * our pend_le_conns list. * our pend_le_conns list. */ */ if (!hci_pend_le_action_lookup(&hdev->pend_le_conns, addr, addr_type)) params = hci_pend_le_action_lookup(&hdev->pend_le_conns, addr, addr_type); if (!params) return; switch (params->auto_connect) { case HCI_AUTO_CONN_DIRECT: /* Only devices advertising with ADV_DIRECT_IND are * triggering a connection attempt. This is allowing * incoming connections from slave devices. */ if (adv_type != LE_ADV_DIRECT_IND) return; return; break; case HCI_AUTO_CONN_ALWAYS: /* Devices advertising with ADV_IND or ADV_DIRECT_IND * are triggering a connection attempt. This means * that incoming connectioms from slave device are * accepted and also outgoing connections to slave * devices are established when found. */ break; default: return; } connect: conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER); HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER); if (!IS_ERR(conn)) if (!IS_ERR(conn)) Loading Loading
MAINTAINERS +1 −0 Original line number Original line Diff line number Diff line Loading @@ -154,6 +154,7 @@ L: linux-zigbee-devel@lists.sourceforge.net (moderated for non-subscribers) L: linux-bluetooth@vger.kernel.org L: linux-bluetooth@vger.kernel.org S: Maintained S: Maintained F: net/6lowpan/ F: net/6lowpan/ F: include/net/6lowpan.h 6PACK NETWORK DRIVER FOR AX.25 6PACK NETWORK DRIVER FOR AX.25 M: Andreas Koensgen <ajk@comnets.uni-bremen.de> M: Andreas Koensgen <ajk@comnets.uni-bremen.de> Loading
include/net/bluetooth/hci.h +4 −0 Original line number Original line Diff line number Diff line Loading @@ -1074,6 +1074,8 @@ struct hci_rp_read_data_block_size { __le16 num_blocks; __le16 num_blocks; } __packed; } __packed; #define HCI_OP_READ_LOCAL_CODECS 0x100b #define HCI_OP_READ_PAGE_SCAN_ACTIVITY 0x0c1b #define HCI_OP_READ_PAGE_SCAN_ACTIVITY 0x0c1b struct hci_rp_read_page_scan_activity { struct hci_rp_read_page_scan_activity { __u8 status; __u8 status; Loading Loading @@ -1170,6 +1172,8 @@ struct hci_rp_write_remote_amp_assoc { __u8 phy_handle; __u8 phy_handle; } __packed; } __packed; #define HCI_OP_GET_MWS_TRANSPORT_CONFIG 0x140c #define HCI_OP_ENABLE_DUT_MODE 0x1803 #define HCI_OP_ENABLE_DUT_MODE 0x1803 #define HCI_OP_WRITE_SSP_DEBUG_MODE 0x1804 #define HCI_OP_WRITE_SSP_DEBUG_MODE 0x1804 Loading
include/net/bluetooth/hci_core.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -203,6 +203,8 @@ struct hci_dev { __u16 page_scan_window; __u16 page_scan_window; __u8 page_scan_type; __u8 page_scan_type; __u8 le_adv_channel_map; __u8 le_adv_channel_map; __u16 le_adv_min_interval; __u16 le_adv_max_interval; __u8 le_scan_type; __u8 le_scan_type; __u16 le_scan_interval; __u16 le_scan_interval; __u16 le_scan_window; __u16 le_scan_window; Loading Loading @@ -458,6 +460,7 @@ struct hci_conn_params { enum { enum { HCI_AUTO_CONN_DISABLED, HCI_AUTO_CONN_DISABLED, HCI_AUTO_CONN_REPORT, HCI_AUTO_CONN_REPORT, HCI_AUTO_CONN_DIRECT, HCI_AUTO_CONN_ALWAYS, HCI_AUTO_CONN_ALWAYS, HCI_AUTO_CONN_LINK_LOSS, HCI_AUTO_CONN_LINK_LOSS, } auto_connect; } auto_connect; Loading
net/bluetooth/hci_core.c +180 −1 Original line number Original line Diff line number Diff line Loading @@ -970,6 +970,62 @@ static int adv_channel_map_get(void *data, u64 *val) DEFINE_SIMPLE_ATTRIBUTE(adv_channel_map_fops, adv_channel_map_get, DEFINE_SIMPLE_ATTRIBUTE(adv_channel_map_fops, adv_channel_map_get, adv_channel_map_set, "%llu\n"); adv_channel_map_set, "%llu\n"); static int adv_min_interval_set(void *data, u64 val) { struct hci_dev *hdev = data; if (val < 0x0020 || val > 0x4000 || val > hdev->le_adv_max_interval) return -EINVAL; hci_dev_lock(hdev); hdev->le_adv_min_interval = val; hci_dev_unlock(hdev); return 0; } static int adv_min_interval_get(void *data, u64 *val) { struct hci_dev *hdev = data; hci_dev_lock(hdev); *val = hdev->le_adv_min_interval; hci_dev_unlock(hdev); return 0; } DEFINE_SIMPLE_ATTRIBUTE(adv_min_interval_fops, adv_min_interval_get, adv_min_interval_set, "%llu\n"); static int adv_max_interval_set(void *data, u64 val) { struct hci_dev *hdev = data; if (val < 0x0020 || val > 0x4000 || val < hdev->le_adv_min_interval) return -EINVAL; hci_dev_lock(hdev); hdev->le_adv_max_interval = val; hci_dev_unlock(hdev); return 0; } static int adv_max_interval_get(void *data, u64 *val) { struct hci_dev *hdev = data; hci_dev_lock(hdev); *val = hdev->le_adv_max_interval; hci_dev_unlock(hdev); return 0; } DEFINE_SIMPLE_ATTRIBUTE(adv_max_interval_fops, adv_max_interval_get, adv_max_interval_set, "%llu\n"); static int device_list_show(struct seq_file *f, void *ptr) static int device_list_show(struct seq_file *f, void *ptr) { { struct hci_dev *hdev = f->private; struct hci_dev *hdev = f->private; Loading Loading @@ -1567,7 +1623,7 @@ static void hci_set_le_support(struct hci_request *req) if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { cp.le = 0x01; cp.le = 0x01; cp.simul = lmp_le_br_capable(hdev); cp.simul = 0x00; } } if (cp.le != lmp_host_le_capable(hdev)) if (cp.le != lmp_host_le_capable(hdev)) Loading Loading @@ -1686,6 +1742,14 @@ static void hci_init4_req(struct hci_request *req, unsigned long opt) if (hdev->commands[22] & 0x04) if (hdev->commands[22] & 0x04) hci_set_event_mask_page_2(req); hci_set_event_mask_page_2(req); /* Read local codec list if the HCI command is supported */ if (hdev->commands[29] & 0x20) hci_req_add(req, HCI_OP_READ_LOCAL_CODECS, 0, NULL); /* Get MWS transport configuration if the HCI command is supported */ if (hdev->commands[30] & 0x08) hci_req_add(req, HCI_OP_GET_MWS_TRANSPORT_CONFIG, 0, NULL); /* Check for Synchronization Train support */ /* Check for Synchronization Train support */ if (lmp_sync_train_capable(hdev)) if (lmp_sync_train_capable(hdev)) hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL); hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL); Loading Loading @@ -1825,6 +1889,10 @@ static int __hci_init(struct hci_dev *hdev) hdev, &supervision_timeout_fops); hdev, &supervision_timeout_fops); debugfs_create_file("adv_channel_map", 0644, hdev->debugfs, debugfs_create_file("adv_channel_map", 0644, hdev->debugfs, hdev, &adv_channel_map_fops); hdev, &adv_channel_map_fops); debugfs_create_file("adv_min_interval", 0644, hdev->debugfs, hdev, &adv_min_interval_fops); debugfs_create_file("adv_max_interval", 0644, hdev->debugfs, hdev, &adv_max_interval_fops); debugfs_create_file("device_list", 0444, hdev->debugfs, hdev, debugfs_create_file("device_list", 0444, hdev->debugfs, hdev, &device_list_fops); &device_list_fops); debugfs_create_u16("discov_interleaved_timeout", 0644, debugfs_create_u16("discov_interleaved_timeout", 0644, Loading Loading @@ -3639,6 +3707,7 @@ int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type, list_add(¶ms->action, &hdev->pend_le_reports); list_add(¶ms->action, &hdev->pend_le_reports); hci_update_background_scan(hdev); hci_update_background_scan(hdev); break; break; case HCI_AUTO_CONN_DIRECT: case HCI_AUTO_CONN_ALWAYS: case HCI_AUTO_CONN_ALWAYS: if (!is_connected(hdev, addr, addr_type)) { if (!is_connected(hdev, addr, addr_type)) { list_add(¶ms->action, &hdev->pend_le_conns); list_add(¶ms->action, &hdev->pend_le_conns); Loading Loading @@ -3914,6 +3983,8 @@ struct hci_dev *hci_alloc_dev(void) hdev->sniff_min_interval = 80; hdev->sniff_min_interval = 80; hdev->le_adv_channel_map = 0x07; hdev->le_adv_channel_map = 0x07; hdev->le_adv_min_interval = 0x0800; hdev->le_adv_max_interval = 0x0800; hdev->le_scan_interval = 0x0060; hdev->le_scan_interval = 0x0060; hdev->le_scan_window = 0x0030; hdev->le_scan_window = 0x0030; hdev->le_conn_min_interval = 0x0028; hdev->le_conn_min_interval = 0x0028; Loading Loading @@ -5397,12 +5468,113 @@ void hci_req_add_le_scan_disable(struct hci_request *req) hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); } } static void add_to_white_list(struct hci_request *req, struct hci_conn_params *params) { struct hci_cp_le_add_to_white_list cp; cp.bdaddr_type = params->addr_type; bacpy(&cp.bdaddr, ¶ms->addr); hci_req_add(req, HCI_OP_LE_ADD_TO_WHITE_LIST, sizeof(cp), &cp); } static u8 update_white_list(struct hci_request *req) { struct hci_dev *hdev = req->hdev; struct hci_conn_params *params; struct bdaddr_list *b; uint8_t white_list_entries = 0; /* Go through the current white list programmed into the * controller one by one and check if that address is still * in the list of pending connections or list of devices to * report. If not present in either list, then queue the * command to remove it from the controller. */ list_for_each_entry(b, &hdev->le_white_list, list) { struct hci_cp_le_del_from_white_list cp; if (hci_pend_le_action_lookup(&hdev->pend_le_conns, &b->bdaddr, b->bdaddr_type) || hci_pend_le_action_lookup(&hdev->pend_le_reports, &b->bdaddr, b->bdaddr_type)) { white_list_entries++; continue; } cp.bdaddr_type = b->bdaddr_type; bacpy(&cp.bdaddr, &b->bdaddr); hci_req_add(req, HCI_OP_LE_DEL_FROM_WHITE_LIST, sizeof(cp), &cp); } /* Since all no longer valid white list entries have been * removed, walk through the list of pending connections * and ensure that any new device gets programmed into * the controller. * * If the list of the devices is larger than the list of * available white list entries in the controller, then * just abort and return filer policy value to not use the * white list. */ list_for_each_entry(params, &hdev->pend_le_conns, action) { if (hci_bdaddr_list_lookup(&hdev->le_white_list, ¶ms->addr, params->addr_type)) continue; if (white_list_entries >= hdev->le_white_list_size) { /* Select filter policy to accept all advertising */ return 0x00; } if (hci_find_irk_by_addr(hdev, ¶ms->addr, params->addr_type)) { /* White list can not be used with RPAs */ return 0x00; } white_list_entries++; add_to_white_list(req, params); } /* After adding all new pending connections, walk through * the list of pending reports and also add these to the * white list if there is still space. */ list_for_each_entry(params, &hdev->pend_le_reports, action) { if (hci_bdaddr_list_lookup(&hdev->le_white_list, ¶ms->addr, params->addr_type)) continue; if (white_list_entries >= hdev->le_white_list_size) { /* Select filter policy to accept all advertising */ return 0x00; } if (hci_find_irk_by_addr(hdev, ¶ms->addr, params->addr_type)) { /* White list can not be used with RPAs */ return 0x00; } white_list_entries++; add_to_white_list(req, params); } /* Select filter policy to use white list */ return 0x01; } void hci_req_add_le_passive_scan(struct hci_request *req) void hci_req_add_le_passive_scan(struct hci_request *req) { { struct hci_cp_le_set_scan_param param_cp; struct hci_cp_le_set_scan_param param_cp; struct hci_cp_le_set_scan_enable enable_cp; struct hci_cp_le_set_scan_enable enable_cp; struct hci_dev *hdev = req->hdev; struct hci_dev *hdev = req->hdev; u8 own_addr_type; u8 own_addr_type; u8 filter_policy; /* Set require_privacy to false since no SCAN_REQ are send /* Set require_privacy to false since no SCAN_REQ are send * during passive scanning. Not using an unresolvable address * during passive scanning. Not using an unresolvable address Loading @@ -5413,11 +5585,18 @@ void hci_req_add_le_passive_scan(struct hci_request *req) if (hci_update_random_address(req, false, &own_addr_type)) if (hci_update_random_address(req, false, &own_addr_type)) return; return; /* Adding or removing entries from the white list must * happen before enabling scanning. The controller does * not allow white list modification while scanning. */ filter_policy = update_white_list(req); memset(¶m_cp, 0, sizeof(param_cp)); memset(¶m_cp, 0, sizeof(param_cp)); param_cp.type = LE_SCAN_PASSIVE; param_cp.type = LE_SCAN_PASSIVE; param_cp.interval = cpu_to_le16(hdev->le_scan_interval); param_cp.interval = cpu_to_le16(hdev->le_scan_interval); param_cp.window = cpu_to_le16(hdev->le_scan_window); param_cp.window = cpu_to_le16(hdev->le_scan_window); param_cp.own_address_type = own_addr_type; param_cp.own_address_type = own_addr_type; param_cp.filter_policy = filter_policy; hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), ¶m_cp); ¶m_cp); Loading
net/bluetooth/hci_event.c +27 −8 Original line number Original line Diff line number Diff line Loading @@ -317,7 +317,7 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) if (param & SCAN_PAGE) if (param & SCAN_PAGE) set_bit(HCI_PSCAN, &hdev->flags); set_bit(HCI_PSCAN, &hdev->flags); else else clear_bit(HCI_ISCAN, &hdev->flags); clear_bit(HCI_PSCAN, &hdev->flags); done: done: hci_dev_unlock(hdev); hci_dev_unlock(hdev); Loading Loading @@ -2259,6 +2259,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) break; break; /* Fall through */ /* Fall through */ case HCI_AUTO_CONN_DIRECT: case HCI_AUTO_CONN_ALWAYS: case HCI_AUTO_CONN_ALWAYS: list_del_init(¶ms->action); list_del_init(¶ms->action); list_add(¶ms->action, &hdev->pend_le_conns); list_add(¶ms->action, &hdev->pend_le_conns); Loading Loading @@ -4251,6 +4252,7 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type, u8 adv_type) u8 addr_type, u8 adv_type) { { struct hci_conn *conn; struct hci_conn *conn; struct hci_conn_params *params; /* If the event is not connectable don't proceed further */ /* If the event is not connectable don't proceed further */ if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND) if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND) Loading @@ -4266,18 +4268,35 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr, if (hdev->conn_hash.le_num_slave > 0) if (hdev->conn_hash.le_num_slave > 0) return; return; /* If we're connectable, always connect any ADV_DIRECT_IND event */ if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) && adv_type == LE_ADV_DIRECT_IND) goto connect; /* If we're not connectable only connect devices that we have in /* If we're not connectable only connect devices that we have in * our pend_le_conns list. * our pend_le_conns list. */ */ if (!hci_pend_le_action_lookup(&hdev->pend_le_conns, addr, addr_type)) params = hci_pend_le_action_lookup(&hdev->pend_le_conns, addr, addr_type); if (!params) return; switch (params->auto_connect) { case HCI_AUTO_CONN_DIRECT: /* Only devices advertising with ADV_DIRECT_IND are * triggering a connection attempt. This is allowing * incoming connections from slave devices. */ if (adv_type != LE_ADV_DIRECT_IND) return; return; break; case HCI_AUTO_CONN_ALWAYS: /* Devices advertising with ADV_IND or ADV_DIRECT_IND * are triggering a connection attempt. This means * that incoming connectioms from slave device are * accepted and also outgoing connections to slave * devices are established when found. */ break; default: return; } connect: conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER); HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER); if (!IS_ERR(conn)) if (!IS_ERR(conn)) Loading