mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 10:49:33 +00:00
![Luiz Augusto von Dentz](/assets/img/avatar_default.png)
This adds initial support for BIS/BIG which includes: == Broadcaster role: Setup a periodic advertising and create a BIG == > tools/isotest -s 00:00:00:00:00:00 isotest[63]: Connected [00:00:00:00:00:00] isotest[63]: QoS BIG 0x00 BIS 0x00 Packing 0x00 Framing 0x00] isotest[63]: Output QoS [Interval 10000 us Latency 10 ms SDU 40 PHY 0x02 RTN 2] isotest[63]: Sending ... isotest[63]: Number of packets: 1 isotest[63]: Socket jitter buffer: 80 buffer < HCI Command: LE Set Perio.. (0x08|0x003e) plen 7 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Parameters (0x08|0x003e) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Perio.. (0x08|0x003f) plen 7 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Data (0x08|0x003f) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Perio.. (0x08|0x0040) plen 2 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Enable (0x08|0x0040) ncmd 1 Status: Success (0x00) < HCI Command: LE Create B.. (0x08|0x0068) plen 31 ... > HCI Event: Command Status (0x0f) plen 4 LE Create Broadcast Isochronous Group (0x08|0x0068) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 21 LE Broadcast Isochronous Group Complete (0x1b) ... == Broadcast Receiver role: Create a PA Sync and BIG Sync == > tools/isotest -i hci1 -d 00:AA:01:00:00:00 isotest[66]: Waiting for connection 00:AA:01:00:00:00... < HCI Command: LE Periodic Advert.. (0x08|0x0044) plen 14 ... > HCI Event: Command Status (0x0f) plen 4 LE Periodic Advertising Create Sync (0x08|0x0044) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Extended Sca.. (0x08|0x0041) plen 8 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Scan Parameters (0x08|0x0041) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Extended Sca.. (0x08|0x0042) plen 6 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Scan Enable (0x08|0x0042) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 29 LE Extended Advertising Report (0x0d) ... > HCI Event: LE Meta Event (0x3e) plen 16 LE Periodic Advertising Sync Established (0x0e) ... < HCI Command: LE Broadcast Isoch.. (0x08|0x006b) plen 25 ... > HCI Event: Command Status (0x0f) plen 4 LE Broadcast Isochronous Group Create Sync (0x08|0x006b) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 17 LE Broadcast Isochronous Group Sync Estabilished (0x1d) ... Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
99 lines
2.1 KiB
C
99 lines
2.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* BlueZ - Bluetooth protocol stack for Linux
|
|
*
|
|
* Copyright (C) 2021 Intel Corporation
|
|
*/
|
|
|
|
#include <asm/unaligned.h>
|
|
|
|
void eir_create(struct hci_dev *hdev, u8 *data);
|
|
|
|
u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr);
|
|
u8 eir_create_scan_rsp(struct hci_dev *hdev, u8 instance, u8 *ptr);
|
|
u8 eir_create_per_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr);
|
|
|
|
u8 eir_append_local_name(struct hci_dev *hdev, u8 *eir, u8 ad_len);
|
|
u8 eir_append_appearance(struct hci_dev *hdev, u8 *ptr, u8 ad_len);
|
|
u8 eir_append_service_data(u8 *eir, u16 eir_len, u16 uuid, u8 *data,
|
|
u8 data_len);
|
|
|
|
static inline u16 eir_precalc_len(u8 data_len)
|
|
{
|
|
return sizeof(u8) * 2 + data_len;
|
|
}
|
|
|
|
static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type,
|
|
u8 *data, u8 data_len)
|
|
{
|
|
eir[eir_len++] = sizeof(type) + data_len;
|
|
eir[eir_len++] = type;
|
|
memcpy(&eir[eir_len], data, data_len);
|
|
eir_len += data_len;
|
|
|
|
return eir_len;
|
|
}
|
|
|
|
static inline u16 eir_append_le16(u8 *eir, u16 eir_len, u8 type, u16 data)
|
|
{
|
|
eir[eir_len++] = sizeof(type) + sizeof(data);
|
|
eir[eir_len++] = type;
|
|
put_unaligned_le16(data, &eir[eir_len]);
|
|
eir_len += sizeof(data);
|
|
|
|
return eir_len;
|
|
}
|
|
|
|
static inline u16 eir_skb_put_data(struct sk_buff *skb, u8 type, u8 *data, u8 data_len)
|
|
{
|
|
u8 *eir;
|
|
u16 eir_len;
|
|
|
|
eir_len = eir_precalc_len(data_len);
|
|
eir = skb_put(skb, eir_len);
|
|
WARN_ON(sizeof(type) + data_len > U8_MAX);
|
|
eir[0] = sizeof(type) + data_len;
|
|
eir[1] = type;
|
|
memcpy(&eir[2], data, data_len);
|
|
|
|
return eir_len;
|
|
}
|
|
|
|
static inline void *eir_get_data(u8 *eir, size_t eir_len, u8 type,
|
|
size_t *data_len)
|
|
{
|
|
size_t parsed = 0;
|
|
|
|
if (eir_len < 2)
|
|
return NULL;
|
|
|
|
while (parsed < eir_len - 1) {
|
|
u8 field_len = eir[0];
|
|
|
|
if (field_len == 0)
|
|
break;
|
|
|
|
parsed += field_len + 1;
|
|
|
|
if (parsed > eir_len)
|
|
break;
|
|
|
|
if (eir[1] != type) {
|
|
eir += field_len + 1;
|
|
continue;
|
|
}
|
|
|
|
/* Zero length data */
|
|
if (field_len == 1)
|
|
return NULL;
|
|
|
|
if (data_len)
|
|
*data_len = field_len - 1;
|
|
|
|
return &eir[2];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void *eir_get_service_data(u8 *eir, size_t eir_len, u16 uuid, size_t *len);
|