Loading net/bluetooth/mgmt.c +64 −91 Original line number Diff line number Diff line Loading @@ -941,52 +941,73 @@ static u8 get_adv_discov_flags(struct hci_dev *hdev) return 0; } static u8 create_default_adv_data(struct hci_dev *hdev, u8 *ptr) static u8 get_current_adv_instance(struct hci_dev *hdev) { u8 ad_len = 0, flags = 0; /* The "Set Advertising" setting supersedes the "Add Advertising" * setting. Here we set the advertising data based on which * setting was set. When neither apply, default to the global settings, * represented by instance "0". */ if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) && !hci_dev_test_flag(hdev, HCI_ADVERTISING)) return 0x01; flags |= get_adv_discov_flags(hdev); return 0x00; } if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) flags |= LE_AD_NO_BREDR; static bool get_connectable(struct hci_dev *hdev) { struct mgmt_pending_cmd *cmd; if (flags) { BT_DBG("adv flags 0x%02x", flags); /* If there's a pending mgmt command the flag will not yet have * it's final value, so check for this first. */ cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev); if (cmd) { struct mgmt_mode *cp = cmd->param; ptr[0] = 2; ptr[1] = EIR_FLAGS; ptr[2] = flags; return cp->val; } ad_len += 3; ptr += 3; return hci_dev_test_flag(hdev, HCI_CONNECTABLE); } if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) { ptr[0] = 2; ptr[1] = EIR_TX_POWER; ptr[2] = (u8) hdev->adv_tx_power; static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance) { u32 flags; ad_len += 3; ptr += 3; } if (instance > 0x01) return 0; return ad_len; if (instance == 0x01) return hdev->adv_instance.flags; /* Instance 0 always manages the "Tx Power" and "Flags" fields */ flags = MGMT_ADV_FLAG_TX_POWER | MGMT_ADV_FLAG_MANAGED_FLAGS; /* For instance 0, assemble the flags from global settings */ if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE) || get_connectable(hdev)) flags |= MGMT_ADV_FLAG_CONNECTABLE; return flags; } static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr) static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr) { u8 ad_len = 0, flags = 0; u32 instance_flags = get_adv_instance_flags(hdev, instance); /* The Add Advertising command allows userspace to set both the general * and limited discoverable flags. */ if (hdev->adv_instance.flags & MGMT_ADV_FLAG_DISCOV) if (instance_flags & MGMT_ADV_FLAG_DISCOV) flags |= LE_AD_GENERAL; if (hdev->adv_instance.flags & MGMT_ADV_FLAG_LIMITED_DISCOV) if (instance_flags & MGMT_ADV_FLAG_LIMITED_DISCOV) flags |= LE_AD_LIMITED; if (flags || (hdev->adv_instance.flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) { if (flags || (instance_flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) { /* If a discovery flag wasn't provided, simply use the global * settings. */ Loading @@ -996,6 +1017,10 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr) if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) flags |= LE_AD_NO_BREDR; /* If flags would still be empty, then there is no need to * include the "Flags" AD field". */ if (flags) { ptr[0] = 0x02; ptr[1] = EIR_FLAGS; ptr[2] = flags; Loading @@ -1003,9 +1028,11 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr) ad_len += 3; ptr += 3; } } /* Provide Tx Power only if we can provide a valid value for it */ if (hdev->adv_tx_power != HCI_TX_POWER_INVALID && (hdev->adv_instance.flags & MGMT_ADV_FLAG_TX_POWER)) { (instance_flags & MGMT_ADV_FLAG_TX_POWER)) { ptr[0] = 0x02; ptr[1] = EIR_TX_POWER; ptr[2] = (u8)hdev->adv_tx_power; Loading @@ -1014,9 +1041,11 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr) ptr += 3; } if (instance) { memcpy(ptr, hdev->adv_instance.adv_data, hdev->adv_instance.adv_data_len); ad_len += hdev->adv_instance.adv_data_len; } return ad_len; } Loading @@ -1032,10 +1061,7 @@ static void update_adv_data_for_instance(struct hci_request *req, u8 instance) memset(&cp, 0, sizeof(cp)); if (instance) len = create_instance_adv_data(hdev, cp.data); else len = create_default_adv_data(hdev, cp.data); len = create_instance_adv_data(hdev, instance, cp.data); /* There's nothing to do if the data hasn't changed */ if (hdev->adv_data_len == len && Loading @@ -1050,59 +1076,6 @@ static void update_adv_data_for_instance(struct hci_request *req, u8 instance) hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); } static u8 get_current_adv_instance(struct hci_dev *hdev) { /* The "Set Advertising" setting supersedes the "Add Advertising" * setting. Here we set the advertising data based on which * setting was set. When neither apply, default to the global settings, * represented by instance "0". */ if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) && !hci_dev_test_flag(hdev, HCI_ADVERTISING)) return 0x01; return 0x00; } static bool get_connectable(struct hci_dev *hdev) { struct mgmt_pending_cmd *cmd; /* If there's a pending mgmt command the flag will not yet have * it's final value, so check for this first. */ cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev); if (cmd) { struct mgmt_mode *cp = cmd->param; return cp->val; } return hci_dev_test_flag(hdev, HCI_CONNECTABLE); } static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance) { u32 flags; if (instance > 0x01) return 0; if (instance == 1) return hdev->adv_instance.flags; flags = 0; /* For instance 0, assemble the flags from global settings */ if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE) || get_connectable(hdev)) flags |= MGMT_ADV_FLAG_CONNECTABLE; /* TODO: Add the rest of the flags */ return flags; } static void update_adv_data(struct hci_request *req) { struct hci_dev *hdev = req->hdev; Loading Loading
net/bluetooth/mgmt.c +64 −91 Original line number Diff line number Diff line Loading @@ -941,52 +941,73 @@ static u8 get_adv_discov_flags(struct hci_dev *hdev) return 0; } static u8 create_default_adv_data(struct hci_dev *hdev, u8 *ptr) static u8 get_current_adv_instance(struct hci_dev *hdev) { u8 ad_len = 0, flags = 0; /* The "Set Advertising" setting supersedes the "Add Advertising" * setting. Here we set the advertising data based on which * setting was set. When neither apply, default to the global settings, * represented by instance "0". */ if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) && !hci_dev_test_flag(hdev, HCI_ADVERTISING)) return 0x01; flags |= get_adv_discov_flags(hdev); return 0x00; } if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) flags |= LE_AD_NO_BREDR; static bool get_connectable(struct hci_dev *hdev) { struct mgmt_pending_cmd *cmd; if (flags) { BT_DBG("adv flags 0x%02x", flags); /* If there's a pending mgmt command the flag will not yet have * it's final value, so check for this first. */ cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev); if (cmd) { struct mgmt_mode *cp = cmd->param; ptr[0] = 2; ptr[1] = EIR_FLAGS; ptr[2] = flags; return cp->val; } ad_len += 3; ptr += 3; return hci_dev_test_flag(hdev, HCI_CONNECTABLE); } if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) { ptr[0] = 2; ptr[1] = EIR_TX_POWER; ptr[2] = (u8) hdev->adv_tx_power; static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance) { u32 flags; ad_len += 3; ptr += 3; } if (instance > 0x01) return 0; return ad_len; if (instance == 0x01) return hdev->adv_instance.flags; /* Instance 0 always manages the "Tx Power" and "Flags" fields */ flags = MGMT_ADV_FLAG_TX_POWER | MGMT_ADV_FLAG_MANAGED_FLAGS; /* For instance 0, assemble the flags from global settings */ if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE) || get_connectable(hdev)) flags |= MGMT_ADV_FLAG_CONNECTABLE; return flags; } static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr) static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr) { u8 ad_len = 0, flags = 0; u32 instance_flags = get_adv_instance_flags(hdev, instance); /* The Add Advertising command allows userspace to set both the general * and limited discoverable flags. */ if (hdev->adv_instance.flags & MGMT_ADV_FLAG_DISCOV) if (instance_flags & MGMT_ADV_FLAG_DISCOV) flags |= LE_AD_GENERAL; if (hdev->adv_instance.flags & MGMT_ADV_FLAG_LIMITED_DISCOV) if (instance_flags & MGMT_ADV_FLAG_LIMITED_DISCOV) flags |= LE_AD_LIMITED; if (flags || (hdev->adv_instance.flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) { if (flags || (instance_flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) { /* If a discovery flag wasn't provided, simply use the global * settings. */ Loading @@ -996,6 +1017,10 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr) if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) flags |= LE_AD_NO_BREDR; /* If flags would still be empty, then there is no need to * include the "Flags" AD field". */ if (flags) { ptr[0] = 0x02; ptr[1] = EIR_FLAGS; ptr[2] = flags; Loading @@ -1003,9 +1028,11 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr) ad_len += 3; ptr += 3; } } /* Provide Tx Power only if we can provide a valid value for it */ if (hdev->adv_tx_power != HCI_TX_POWER_INVALID && (hdev->adv_instance.flags & MGMT_ADV_FLAG_TX_POWER)) { (instance_flags & MGMT_ADV_FLAG_TX_POWER)) { ptr[0] = 0x02; ptr[1] = EIR_TX_POWER; ptr[2] = (u8)hdev->adv_tx_power; Loading @@ -1014,9 +1041,11 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr) ptr += 3; } if (instance) { memcpy(ptr, hdev->adv_instance.adv_data, hdev->adv_instance.adv_data_len); ad_len += hdev->adv_instance.adv_data_len; } return ad_len; } Loading @@ -1032,10 +1061,7 @@ static void update_adv_data_for_instance(struct hci_request *req, u8 instance) memset(&cp, 0, sizeof(cp)); if (instance) len = create_instance_adv_data(hdev, cp.data); else len = create_default_adv_data(hdev, cp.data); len = create_instance_adv_data(hdev, instance, cp.data); /* There's nothing to do if the data hasn't changed */ if (hdev->adv_data_len == len && Loading @@ -1050,59 +1076,6 @@ static void update_adv_data_for_instance(struct hci_request *req, u8 instance) hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); } static u8 get_current_adv_instance(struct hci_dev *hdev) { /* The "Set Advertising" setting supersedes the "Add Advertising" * setting. Here we set the advertising data based on which * setting was set. When neither apply, default to the global settings, * represented by instance "0". */ if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) && !hci_dev_test_flag(hdev, HCI_ADVERTISING)) return 0x01; return 0x00; } static bool get_connectable(struct hci_dev *hdev) { struct mgmt_pending_cmd *cmd; /* If there's a pending mgmt command the flag will not yet have * it's final value, so check for this first. */ cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev); if (cmd) { struct mgmt_mode *cp = cmd->param; return cp->val; } return hci_dev_test_flag(hdev, HCI_CONNECTABLE); } static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance) { u32 flags; if (instance > 0x01) return 0; if (instance == 1) return hdev->adv_instance.flags; flags = 0; /* For instance 0, assemble the flags from global settings */ if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE) || get_connectable(hdev)) flags |= MGMT_ADV_FLAG_CONNECTABLE; /* TODO: Add the rest of the flags */ return flags; } static void update_adv_data(struct hci_request *req) { struct hci_dev *hdev = req->hdev; Loading