eir.h 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * BlueZ - Bluetooth protocol stack for Linux
  4. *
  5. * Copyright (C) 2021 Intel Corporation
  6. */
  7. #include <linux/unaligned.h>
  8. void eir_create(struct hci_dev *hdev, u8 *data);
  9. u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr, u8 size);
  10. u8 eir_create_scan_rsp(struct hci_dev *hdev, u8 instance, u8 *ptr);
  11. u8 eir_create_per_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr);
  12. u8 eir_append_local_name(struct hci_dev *hdev, u8 *eir, u8 ad_len);
  13. u8 eir_append_appearance(struct hci_dev *hdev, u8 *ptr, u8 ad_len);
  14. u8 eir_append_service_data(u8 *eir, u16 eir_len, u16 uuid, u8 *data,
  15. u8 data_len);
  16. static inline u16 eir_precalc_len(u8 data_len)
  17. {
  18. return sizeof(u8) * 2 + data_len;
  19. }
  20. static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type,
  21. u8 *data, u8 data_len)
  22. {
  23. eir[eir_len++] = sizeof(type) + data_len;
  24. eir[eir_len++] = type;
  25. memcpy(&eir[eir_len], data, data_len);
  26. eir_len += data_len;
  27. return eir_len;
  28. }
  29. static inline u16 eir_append_le16(u8 *eir, u16 eir_len, u8 type, u16 data)
  30. {
  31. eir[eir_len++] = sizeof(type) + sizeof(data);
  32. eir[eir_len++] = type;
  33. put_unaligned_le16(data, &eir[eir_len]);
  34. eir_len += sizeof(data);
  35. return eir_len;
  36. }
  37. static inline u16 eir_skb_put_data(struct sk_buff *skb, u8 type, u8 *data, u8 data_len)
  38. {
  39. u8 *eir;
  40. u16 eir_len;
  41. eir_len = eir_precalc_len(data_len);
  42. eir = skb_put(skb, eir_len);
  43. WARN_ON(sizeof(type) + data_len > U8_MAX);
  44. eir[0] = sizeof(type) + data_len;
  45. eir[1] = type;
  46. memcpy(&eir[2], data, data_len);
  47. return eir_len;
  48. }
  49. static inline void *eir_get_data(u8 *eir, size_t eir_len, u8 type,
  50. size_t *data_len)
  51. {
  52. size_t parsed = 0;
  53. if (eir_len < 2)
  54. return NULL;
  55. while (parsed < eir_len - 1) {
  56. u8 field_len = eir[0];
  57. if (field_len == 0)
  58. break;
  59. parsed += field_len + 1;
  60. if (parsed > eir_len)
  61. break;
  62. if (eir[1] != type) {
  63. eir += field_len + 1;
  64. continue;
  65. }
  66. /* Zero length data */
  67. if (field_len == 1)
  68. return NULL;
  69. if (data_len)
  70. *data_len = field_len - 1;
  71. return &eir[2];
  72. }
  73. return NULL;
  74. }
  75. void *eir_get_service_data(u8 *eir, size_t eir_len, u16 uuid, size_t *len);