aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorMichał Narajowski <michal.narajowski@codecoup.pl>2016-09-18 06:50:03 -0400
committerMarcel Holtmann <marcel@holtmann.org>2016-09-19 14:19:34 -0400
commitc4960ecf2b09210930964ef2c05ce2590802ccf4 (patch)
tree9e9b497d8ddcf7f2aed5b1ada5735d40837429ef /net/bluetooth
parent7c295c4801b2de24fc25687eb0cb73cf0c99d114 (diff)
Bluetooth: Add support for appearance in scan rsp
This patch enables prepending appearance value to scan response data. It also adds support for setting appearance value through mgmt command. If currently advertised instance has apperance flag set it is expired immediately. Signed-off-by: Michał Narajowski <michal.narajowski@codecoup.pl> Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hci_request.c8
-rw-r--r--net/bluetooth/mgmt.c37
2 files changed, 45 insertions, 0 deletions
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index 0ce6cdd278b2..c8135680c43e 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -1015,6 +1015,14 @@ static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 instance,
1015 1015
1016 instance_flags = adv_instance->flags; 1016 instance_flags = adv_instance->flags;
1017 1017
1018 if ((instance_flags & MGMT_ADV_FLAG_APPEARANCE) && hdev->appearance) {
1019 ptr[0] = 3;
1020 ptr[1] = EIR_APPEARANCE;
1021 put_unaligned_le16(hdev->appearance, ptr + 2);
1022 scan_rsp_len += 4;
1023 ptr += 4;
1024 }
1025
1018 memcpy(ptr, adv_instance->scan_rsp_data, 1026 memcpy(ptr, adv_instance->scan_rsp_data,
1019 adv_instance->scan_rsp_len); 1027 adv_instance->scan_rsp_len);
1020 1028
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 89954bb19222..78d708851208 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -105,6 +105,7 @@ static const u16 mgmt_commands[] = {
105 MGMT_OP_GET_ADV_SIZE_INFO, 105 MGMT_OP_GET_ADV_SIZE_INFO,
106 MGMT_OP_START_LIMITED_DISCOVERY, 106 MGMT_OP_START_LIMITED_DISCOVERY,
107 MGMT_OP_READ_EXT_INFO, 107 MGMT_OP_READ_EXT_INFO,
108 MGMT_OP_SET_APPEARANCE,
108}; 109};
109 110
110static const u16 mgmt_events[] = { 111static const u16 mgmt_events[] = {
@@ -3143,6 +3144,34 @@ failed:
3143 return err; 3144 return err;
3144} 3145}
3145 3146
3147static int set_appearance(struct sock *sk, struct hci_dev *hdev, void *data,
3148 u16 len)
3149{
3150 struct mgmt_cp_set_appearance *cp = data;
3151 u16 apperance;
3152 int err;
3153
3154 BT_DBG("");
3155
3156 apperance = le16_to_cpu(cp->appearance);
3157
3158 hci_dev_lock(hdev);
3159
3160 if (hdev->appearance != apperance) {
3161 hdev->appearance = apperance;
3162
3163 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
3164 adv_expire(hdev, MGMT_ADV_FLAG_APPEARANCE);
3165 }
3166
3167 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_APPEARANCE, 0, NULL,
3168 0);
3169
3170 hci_dev_unlock(hdev);
3171
3172 return err;
3173}
3174
3146static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status, 3175static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
3147 u16 opcode, struct sk_buff *skb) 3176 u16 opcode, struct sk_buff *skb)
3148{ 3177{
@@ -5918,6 +5947,7 @@ static u32 get_supported_adv_flags(struct hci_dev *hdev)
5918 flags |= MGMT_ADV_FLAG_DISCOV; 5947 flags |= MGMT_ADV_FLAG_DISCOV;
5919 flags |= MGMT_ADV_FLAG_LIMITED_DISCOV; 5948 flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
5920 flags |= MGMT_ADV_FLAG_MANAGED_FLAGS; 5949 flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
5950 flags |= MGMT_ADV_FLAG_APPEARANCE;
5921 flags |= MGMT_ADV_FLAG_LOCAL_NAME; 5951 flags |= MGMT_ADV_FLAG_LOCAL_NAME;
5922 5952
5923 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) 5953 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID)
@@ -5999,6 +6029,9 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
5999 /* at least 1 byte of name should fit in */ 6029 /* at least 1 byte of name should fit in */
6000 if (adv_flags & MGMT_ADV_FLAG_LOCAL_NAME) 6030 if (adv_flags & MGMT_ADV_FLAG_LOCAL_NAME)
6001 max_len -= 3; 6031 max_len -= 3;
6032
6033 if (adv_flags & MGMT_ADV_FLAG_APPEARANCE)
6034 max_len -= 4;
6002 } 6035 }
6003 6036
6004 if (len > max_len) 6037 if (len > max_len)
@@ -6335,6 +6368,9 @@ static u8 tlv_data_max_len(u32 adv_flags, bool is_adv_data)
6335 /* at least 1 byte of name should fit in */ 6368 /* at least 1 byte of name should fit in */
6336 if (adv_flags & MGMT_ADV_FLAG_LOCAL_NAME) 6369 if (adv_flags & MGMT_ADV_FLAG_LOCAL_NAME)
6337 max_len -= 3; 6370 max_len -= 3;
6371
6372 if (adv_flags & (MGMT_ADV_FLAG_APPEARANCE))
6373 max_len -= 4;
6338 } 6374 }
6339 6375
6340 return max_len; 6376 return max_len;
@@ -6470,6 +6506,7 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
6470 { start_limited_discovery, MGMT_START_DISCOVERY_SIZE }, 6506 { start_limited_discovery, MGMT_START_DISCOVERY_SIZE },
6471 { read_ext_controller_info,MGMT_READ_EXT_INFO_SIZE, 6507 { read_ext_controller_info,MGMT_READ_EXT_INFO_SIZE,
6472 HCI_MGMT_UNTRUSTED }, 6508 HCI_MGMT_UNTRUSTED },
6509 { set_appearance, MGMT_SET_APPEARANCE_SIZE },
6473}; 6510};
6474 6511
6475void mgmt_index_added(struct hci_dev *hdev) 6512void mgmt_index_added(struct hci_dev *hdev)