Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Bluetooth: MGMT: Allow use of Set Device Flags without Add Device

In certain cases setting devices flags like HCI_CONN_FLAG_PAST it
shouldn't require to do Add Device first since it may not need to add
an auto-connect policy, so this instead just automatically creates
a hci_conn_params if one cannot be found using HCI_AUTO_CONN_DISABLED.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

+76 -72
+76 -72
net/bluetooth/mgmt.c
··· 5122 5122 mgmt_event(MGMT_EV_DEVICE_FLAGS_CHANGED, hdev, &ev, sizeof(ev), sk); 5123 5123 } 5124 5124 5125 + static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type) 5126 + { 5127 + struct hci_conn *conn; 5128 + 5129 + conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr); 5130 + if (!conn) 5131 + return false; 5132 + 5133 + if (conn->dst_type != type) 5134 + return false; 5135 + 5136 + if (conn->state != BT_CONNECTED) 5137 + return false; 5138 + 5139 + return true; 5140 + } 5141 + 5142 + /* This function requires the caller holds hdev->lock */ 5143 + static struct hci_conn_params *hci_conn_params_set(struct hci_dev *hdev, 5144 + bdaddr_t *addr, u8 addr_type, 5145 + u8 auto_connect) 5146 + { 5147 + struct hci_conn_params *params; 5148 + 5149 + params = hci_conn_params_add(hdev, addr, addr_type); 5150 + if (!params) 5151 + return NULL; 5152 + 5153 + if (params->auto_connect == auto_connect) 5154 + return params; 5155 + 5156 + hci_pend_le_list_del_init(params); 5157 + 5158 + switch (auto_connect) { 5159 + case HCI_AUTO_CONN_DISABLED: 5160 + case HCI_AUTO_CONN_LINK_LOSS: 5161 + /* If auto connect is being disabled when we're trying to 5162 + * connect to device, keep connecting. 5163 + */ 5164 + if (params->explicit_connect) 5165 + hci_pend_le_list_add(params, &hdev->pend_le_conns); 5166 + break; 5167 + case HCI_AUTO_CONN_REPORT: 5168 + if (params->explicit_connect) 5169 + hci_pend_le_list_add(params, &hdev->pend_le_conns); 5170 + else 5171 + hci_pend_le_list_add(params, &hdev->pend_le_reports); 5172 + break; 5173 + case HCI_AUTO_CONN_DIRECT: 5174 + case HCI_AUTO_CONN_ALWAYS: 5175 + if (!is_connected(hdev, addr, addr_type)) 5176 + hci_pend_le_list_add(params, &hdev->pend_le_conns); 5177 + break; 5178 + } 5179 + 5180 + params->auto_connect = auto_connect; 5181 + 5182 + bt_dev_dbg(hdev, "addr %pMR (type %u) auto_connect %u", 5183 + addr, addr_type, auto_connect); 5184 + 5185 + return params; 5186 + } 5187 + 5125 5188 static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data, 5126 5189 u16 len) 5127 5190 { ··· 5228 5165 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr, 5229 5166 le_addr_type(cp->addr.type)); 5230 5167 if (!params) { 5231 - bt_dev_warn(hdev, "No such LE device %pMR (0x%x)", 5232 - &cp->addr.bdaddr, le_addr_type(cp->addr.type)); 5233 - goto unlock; 5168 + /* Create a new hci_conn_params if it doesn't exist */ 5169 + params = hci_conn_params_set(hdev, &cp->addr.bdaddr, 5170 + le_addr_type(cp->addr.type), 5171 + HCI_AUTO_CONN_DISABLED); 5172 + if (!params) { 5173 + bt_dev_warn(hdev, "No such LE device %pMR (0x%x)", 5174 + &cp->addr.bdaddr, 5175 + le_addr_type(cp->addr.type)); 5176 + goto unlock; 5177 + } 5234 5178 } 5235 5179 5236 5180 supported_flags = hdev->conn_flags; ··· 7624 7554 return err; 7625 7555 } 7626 7556 7627 - static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type) 7628 - { 7629 - struct hci_conn *conn; 7630 - 7631 - conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr); 7632 - if (!conn) 7633 - return false; 7634 - 7635 - if (conn->dst_type != type) 7636 - return false; 7637 - 7638 - if (conn->state != BT_CONNECTED) 7639 - return false; 7640 - 7641 - return true; 7642 - } 7643 - 7644 - /* This function requires the caller holds hdev->lock */ 7645 - static int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr, 7646 - u8 addr_type, u8 auto_connect) 7647 - { 7648 - struct hci_conn_params *params; 7649 - 7650 - params = hci_conn_params_add(hdev, addr, addr_type); 7651 - if (!params) 7652 - return -EIO; 7653 - 7654 - if (params->auto_connect == auto_connect) 7655 - return 0; 7656 - 7657 - hci_pend_le_list_del_init(params); 7658 - 7659 - switch (auto_connect) { 7660 - case HCI_AUTO_CONN_DISABLED: 7661 - case HCI_AUTO_CONN_LINK_LOSS: 7662 - /* If auto connect is being disabled when we're trying to 7663 - * connect to device, keep connecting. 7664 - */ 7665 - if (params->explicit_connect) 7666 - hci_pend_le_list_add(params, &hdev->pend_le_conns); 7667 - break; 7668 - case HCI_AUTO_CONN_REPORT: 7669 - if (params->explicit_connect) 7670 - hci_pend_le_list_add(params, &hdev->pend_le_conns); 7671 - else 7672 - hci_pend_le_list_add(params, &hdev->pend_le_reports); 7673 - break; 7674 - case HCI_AUTO_CONN_DIRECT: 7675 - case HCI_AUTO_CONN_ALWAYS: 7676 - if (!is_connected(hdev, addr, addr_type)) 7677 - hci_pend_le_list_add(params, &hdev->pend_le_conns); 7678 - break; 7679 - } 7680 - 7681 - params->auto_connect = auto_connect; 7682 - 7683 - bt_dev_dbg(hdev, "addr %pMR (type %u) auto_connect %u", 7684 - addr, addr_type, auto_connect); 7685 - 7686 - return 0; 7687 - } 7688 - 7689 7557 static void device_added(struct sock *sk, struct hci_dev *hdev, 7690 7558 bdaddr_t *bdaddr, u8 type, u8 action) 7691 7559 { ··· 7735 7727 /* If the connection parameters don't exist for this device, 7736 7728 * they will be created and configured with defaults. 7737 7729 */ 7738 - if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type, 7739 - auto_conn) < 0) { 7730 + params = hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type, 7731 + auto_conn); 7732 + if (!params) { 7740 7733 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, 7741 7734 MGMT_STATUS_FAILED, &cp->addr, 7742 7735 sizeof(cp->addr)); 7743 7736 goto unlock; 7744 - } else { 7745 - params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr, 7746 - addr_type); 7747 - if (params) 7748 - current_flags = params->flags; 7749 7737 } 7750 7738 7751 7739 cmd = mgmt_pending_new(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);