-
Notifications
You must be signed in to change notification settings - Fork 32
Add PA sync service #352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Add PA sync service #352
Changes from all commits
121d22a
809afcf
6b70a80
4a30d68
c95da27
f41d3bb
9124539
ffd1d71
43dce33
5f7f759
6dd6be5
99037c4
99b396b
f75ec66
736fc64
d7c9c60
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -18,6 +18,10 @@ | |||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| #include "advertiser_data.h" | ||||||||||||||||||||||||||||||||||
| #include "bt_debug.h" | ||||||||||||||||||||||||||||||||||
| #ifdef CONFIG_BLUETOOTH_PA_SYNC | ||||||||||||||||||||||||||||||||||
| #include "bt_pa_sync.h" | ||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||
| #include "bt_utils.h" | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| typedef struct { | ||||||||||||||||||||||||||||||||||
| uint8_t ad_type; | ||||||||||||||||||||||||||||||||||
|
|
@@ -213,3 +217,92 @@ bool advertiser_data_dump(uint8_t* data, uint16_t len, ad_dump_cb_t dump) | |||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| bool advertiser_data_parse(const uint8_t* data, uint8_t len, ad_parse_cb_t cb, void* context) | ||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||
| adv_data_t* ad; | ||||||||||||||||||||||||||||||||||
| uint16_t offset = 0; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if (!cb) | ||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| while (offset < len) { | ||||||||||||||||||||||||||||||||||
| ad = (adv_data_t*)&data[offset]; | ||||||||||||||||||||||||||||||||||
| if (ad->len == 0) { /**< AD Type does not exist */ | ||||||||||||||||||||||||||||||||||
| offset += sizeof(ad->len); /**< Skip this entry */ | ||||||||||||||||||||||||||||||||||
| continue; /**< Goto the next item */ | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| offset += sizeof(ad->len) + ad->len; | ||||||||||||||||||||||||||||||||||
| if (offset > len) | ||||||||||||||||||||||||||||||||||
| return false; /**< Incomplete AD Data */ | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| cb(ad, context); | ||||||||||||||||||||||||||||||||||
gzh-terry marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| #ifdef CONFIG_BLUETOOTH_PA_SYNC | ||||||||||||||||||||||||||||||||||
| static void adv_data_parse_uuid_16(bt_pa_sync_info_t* info, uint16_t uuid_16, | ||||||||||||||||||||||||||||||||||
| const adv_data_t* data) | ||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||
| const uint8_t* p = data->data + sizeof(uint16_t); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| switch (uuid_16) { | ||||||||||||||||||||||||||||||||||
| #ifdef CONFIG_BLUETOOTH_AURACAST_SINK | ||||||||||||||||||||||||||||||||||
| case BT_UUID_BROADCAST_AUDIO_ANNOUNCEMENT: | ||||||||||||||||||||||||||||||||||
| if (data->len < 1 + sizeof(uuid_16) + 3) | ||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could we make the magic number easy to understand? l
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any suggestions? The name of this uuid is
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggest macro for special size or struct size |
||||||||||||||||||||||||||||||||||
| break; /* less than AD Type (1 octet) + UUID16 (2 octets) + Broadcast ID (3 octets)*/ | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| STREAM_TO_UINT24(info->broadcast_id, p); | ||||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||
| default: | ||||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| static void adv_data_parsed(const adv_data_t* data, void* context) | ||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||
| bt_pa_sync_info_t* info = (bt_pa_sync_info_t*)context; | ||||||||||||||||||||||||||||||||||
| const uint8_t* p = data->data; | ||||||||||||||||||||||||||||||||||
| uint16_t uuid_16; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| switch (data->type) { | ||||||||||||||||||||||||||||||||||
| case BT_AD_NAME_SHORT: | ||||||||||||||||||||||||||||||||||
| case BT_AD_NAME_COMPLETE: | ||||||||||||||||||||||||||||||||||
| strlcpy(info->name, (char*)data->data, MIN(sizeof(info->name), data->len)); | ||||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| #ifdef CONFIG_BLUETOOTH_AURACAST_SINK | ||||||||||||||||||||||||||||||||||
| case BT_AD_BROADCAST_NAME: | ||||||||||||||||||||||||||||||||||
| strlcpy(info->broadcast_name, (char*)data->data, | ||||||||||||||||||||||||||||||||||
| MIN(sizeof(info->broadcast_name), data->len)); | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+275
to
+281
|
||||||||||||||||||||||||||||||||||
| strlcpy(info->name, (char*)data->data, MIN(sizeof(info->name), data->len)); | |
| break; | |
| #ifdef CONFIG_BLUETOOTH_AURACAST_SINK | |
| case BT_AD_BROADCAST_NAME: | |
| strlcpy(info->broadcast_name, (char*)data->data, | |
| MIN(sizeof(info->broadcast_name), data->len)); | |
| strlcpy(info->name, (char*)data->data, MIN(sizeof(info->name), data->len - 1)); | |
| break; | |
| #ifdef CONFIG_BLUETOOTH_AURACAST_SINK | |
| case BT_AD_BROADCAST_NAME: | |
| strlcpy(info->broadcast_name, (char*)data->data, | |
| MIN(sizeof(info->broadcast_name), data->len - 1)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ADV data is a string but without an ending '\0'.
Therefore we need the length data->len, which is exactly the length of the string, plus a space for '\0'.
Copilot
AI
Jan 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The strlcpy function call specifies a maximum copy length using MIN(sizeof(info->broadcast_name), data->len). However, data->len includes the AD Type byte (1 octet), which should not be counted in the data length for the broadcast name. This means an extra byte from the next AD entry could be copied into the broadcast_name buffer. The correct length should be data->len - 1 to account for the AD Type byte that has already been excluded from data->data.
| MIN(sizeof(info->broadcast_name), data->len)); | |
| MIN(sizeof(info->broadcast_name), data->len > 0 ? data->len - 1 : 0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
data->len does not include the ending '\0', so we do need the orignal data to get the full string.
gzh-terry marked this conversation as resolved.
Show resolved
Hide resolved
gzh-terry marked this conversation as resolved.
Show resolved
Hide resolved
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -349,6 +349,11 @@ typedef uint8_t bt_128key_t[16]; | |
| #define BT_UUID_MAX_NUM (32) | ||
| #define BT_UUID_128_LEN (16) | ||
|
|
||
| /* `Broadcast_ID` is 24-bit (0x000000-0xFFFFFF). Other values are invalid. */ | ||
| #define BT_INVALID_BROADCAST_ID (0xFFFFFFFF) | ||
|
|
||
| #define BT_BROADCAST_NAME_MAX_LEN (128) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change BROADCAST to ADV will be better.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the same reason, I would prefer to keep the official names.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No it doesn't, because there is actually a |
||
|
|
||
| typedef struct { | ||
| bt_address_t addr; | ||
| int8_t rssi; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| /**************************************************************************** | ||
| * Copyright (C) 2025 Xiaomi Corporation | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| ***************************************************************************/ | ||
| #ifndef __BT_PA_SYNC_H__ | ||
| #define __BT_PA_SYNC_H__ | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| #include "bt_le_scan.h" | ||
|
|
||
| #ifndef BTSYMBOLS | ||
| #define BTSYMBOLS(s) s | ||
| #endif | ||
|
|
||
| /** | ||
| * @brief Information about the periodic advertising sync. | ||
| */ | ||
| typedef struct bt_pa_sync_info { | ||
| /** Present if available: Broadcast_ID from Broadcast Audio Announcement. | ||
| * Otherwise, `BT_INVALID_BROADCAST_ID` */ | ||
| uint32_t broadcast_id; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change it to
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| /** UTF-8 string of the remote device name */ | ||
| char name[BT_REM_NAME_MAX_LEN + 1]; | ||
|
|
||
| /** UTF-8 string of the `Broadcast_Name` field in `AdvData` (if present) */ | ||
| char broadcast_name[BT_BROADCAST_NAME_MAX_LEN + 1]; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change it to
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| } bt_pa_sync_info_t; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why there is no
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These info is parsed from secondary advertising. Especially from "LE Extended Advertising Report event".
|
||
|
|
||
| /** | ||
| * @brief Parse an advertising report and check if periodic advertising is present. | ||
| * | ||
| * @param[out] info Buffer to store the parsed periodic advertising info | ||
| * @param[in] result Advertising report from the scan result callback | ||
| * | ||
| * @return `BT_STATUS_SUCCESS` if periodic advertising is found | ||
| * @return `BT_STATUS_NOT_FOUND` if no periodic advertising is found | ||
| * @return Other negative `bt_status_t` error codes on failure. | ||
| */ | ||
| bt_status_t bt_pa_sync_parse_adv_data(bt_pa_sync_info_t* info, const ble_scan_result_t* result); | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
|
|
||
| #endif | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| /**************************************************************************** | ||
| * Copyright (C) 2025 Xiaomi Corporation | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| ***************************************************************************/ | ||
|
|
||
| #include "bt_pa_sync.h" | ||
gzh-terry marked this conversation as resolved.
Show resolved
Hide resolved
|
||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ad = (adv_data_t*)&data[offset];This line may cause memory alignment issues.Here you are casting data[offset] to the
adv_data_t*type. Assuming data is just a raw byte array, the adv_data_t structure may have memory alignment problems on certain platforms.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I noticed it as well since there were warnings when printing the data.
However, I’d like to follow the existing code patterns, like
advertiser_data_dump.Otherwise, this PR would include many changes irrelevant to Auracast itself.