diff options
-rw-r--r-- | include/net/bluetooth/hci_core.h | 1 | ||||
-rw-r--r-- | include/net/bluetooth/mgmt.h | 6 | ||||
-rw-r--r-- | net/bluetooth/hci_request.c | 8 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 37 |
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 | ||
602 | struct 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 |
602 | struct mgmt_ev_cmd_complete { | 608 | struct 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 | ||
110 | static const u16 mgmt_events[] = { | 111 | static const u16 mgmt_events[] = { |
@@ -3143,6 +3144,34 @@ failed: | |||
3143 | return err; | 3144 | return err; |
3144 | } | 3145 | } |
3145 | 3146 | ||
3147 | static 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 | |||
3146 | static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status, | 3175 | static 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 | ||
6475 | void mgmt_index_added(struct hci_dev *hdev) | 6512 | void mgmt_index_added(struct hci_dev *hdev) |