aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/bluetooth/hci_core.h1
-rw-r--r--include/net/bluetooth/mgmt.h6
-rw-r--r--net/bluetooth/hci_request.c8
-rw-r--r--net/bluetooth/mgmt.c37
4 files changed, 52 insertions, 0 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index a48f71d73dc8..f00bf667ec33 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -211,6 +211,7 @@ struct hci_dev {
211 __u8 dev_name[HCI_MAX_NAME_LENGTH]; 211 __u8 dev_name[HCI_MAX_NAME_LENGTH];
212 __u8 short_name[HCI_MAX_SHORT_NAME_LENGTH]; 212 __u8 short_name[HCI_MAX_SHORT_NAME_LENGTH];
213 __u8 eir[HCI_MAX_EIR_LENGTH]; 213 __u8 eir[HCI_MAX_EIR_LENGTH];
214 __u16 appearance;
214 __u8 dev_class[3]; 215 __u8 dev_class[3];
215 __u8 major_class; 216 __u8 major_class;
216 __u8 minor_class; 217 __u8 minor_class;
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 611b243713ea..72a456bbbcd5 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -598,6 +598,12 @@ struct mgmt_rp_read_ext_info {
598 __u8 eir[0]; 598 __u8 eir[0];
599} __packed; 599} __packed;
600 600
601#define MGMT_OP_SET_APPEARANCE 0x0043
602struct mgmt_cp_set_appearance {
603 __u16 appearance;
604} __packed;
605#define MGMT_SET_APPEARANCE_SIZE 2
606
601#define MGMT_EV_CMD_COMPLETE 0x0001 607#define MGMT_EV_CMD_COMPLETE 0x0001
602struct mgmt_ev_cmd_complete { 608struct mgmt_ev_cmd_complete {
603 __le16 opcode; 609 __le16 opcode;
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)