Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * BlueZ - Bluetooth protocol stack for Linux
0004  *
0005  * Copyright (C) 2021 Intel Corporation
0006  */
0007 
0008 #include <asm/unaligned.h>
0009 
0010 void eir_create(struct hci_dev *hdev, u8 *data);
0011 
0012 u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr);
0013 u8 eir_create_scan_rsp(struct hci_dev *hdev, u8 instance, u8 *ptr);
0014 u8 eir_create_per_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr);
0015 
0016 u8 eir_append_local_name(struct hci_dev *hdev, u8 *eir, u8 ad_len);
0017 u8 eir_append_appearance(struct hci_dev *hdev, u8 *ptr, u8 ad_len);
0018 u8 eir_append_service_data(u8 *eir, u16 eir_len, u16 uuid, u8 *data,
0019                u8 data_len);
0020 
0021 static inline u16 eir_precalc_len(u8 data_len)
0022 {
0023     return sizeof(u8) * 2 + data_len;
0024 }
0025 
0026 static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type,
0027                   u8 *data, u8 data_len)
0028 {
0029     eir[eir_len++] = sizeof(type) + data_len;
0030     eir[eir_len++] = type;
0031     memcpy(&eir[eir_len], data, data_len);
0032     eir_len += data_len;
0033 
0034     return eir_len;
0035 }
0036 
0037 static inline u16 eir_append_le16(u8 *eir, u16 eir_len, u8 type, u16 data)
0038 {
0039     eir[eir_len++] = sizeof(type) + sizeof(data);
0040     eir[eir_len++] = type;
0041     put_unaligned_le16(data, &eir[eir_len]);
0042     eir_len += sizeof(data);
0043 
0044     return eir_len;
0045 }
0046 
0047 static inline u16 eir_skb_put_data(struct sk_buff *skb, u8 type, u8 *data, u8 data_len)
0048 {
0049     u8 *eir;
0050     u16 eir_len;
0051 
0052     eir_len = eir_precalc_len(data_len);
0053     eir = skb_put(skb, eir_len);
0054     WARN_ON(sizeof(type) + data_len > U8_MAX);
0055     eir[0] = sizeof(type) + data_len;
0056     eir[1] = type;
0057     memcpy(&eir[2], data, data_len);
0058 
0059     return eir_len;
0060 }
0061 
0062 static inline void *eir_get_data(u8 *eir, size_t eir_len, u8 type,
0063                  size_t *data_len)
0064 {
0065     size_t parsed = 0;
0066 
0067     if (eir_len < 2)
0068         return NULL;
0069 
0070     while (parsed < eir_len - 1) {
0071         u8 field_len = eir[0];
0072 
0073         if (field_len == 0)
0074             break;
0075 
0076         parsed += field_len + 1;
0077 
0078         if (parsed > eir_len)
0079             break;
0080 
0081         if (eir[1] != type) {
0082             eir += field_len + 1;
0083             continue;
0084         }
0085 
0086         /* Zero length data */
0087         if (field_len == 1)
0088             return NULL;
0089 
0090         if (data_len)
0091             *data_len = field_len - 1;
0092 
0093         return &eir[2];
0094     }
0095 
0096     return NULL;
0097 }
0098 
0099 void *eir_get_service_data(u8 *eir, size_t eir_len, u16 uuid, size_t *len);