Skip to content

Bluetooth: LE: Add PA support#527

Closed
expliyh wants to merge 33 commits into
open-vela:devfrom
expliyh:pa
Closed

Bluetooth: LE: Add PA support#527
expliyh wants to merge 33 commits into
open-vela:devfrom
expliyh:pa

Conversation

@expliyh
Copy link
Copy Markdown
Contributor

@expliyh expliyh commented Mar 19, 2026

No description provided.

gzh-terry
gzh-terry previously approved these changes Mar 19, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds LE Periodic Advertising (PA) sync support across the stack (Zephyr SAL → service layer → IPC/socket → framework API) and introduces an Auracast sink bttool command that leverages PA scan parsing.

Changes:

  • Add PA sync service + Zephyr SAL implementation and wire it into adapter lifecycle.
  • Extend LE scan result plumbing to carry PA-related fields (SID/interval/tx power/flags) and update IPC scan callback codes.
  • Add PA sync IPC messages + socket client/server handling and expose a framework API, plus an Auracast sink tool command.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tools/utils.h Add BTTOOL_STRCAT helper macro for safe-ish log concatenation.
tools/bt_tools.h Declare Auracast sink command entrypoints.
tools/bt_tools.c Register/init/uninit Auracast sink command behind config.
tools/auracast_sink.c New bttool command to scan for Auracast sources and (eventually) sync.
service/stacks/zephyr/sal_pa_sync_interface.c New Zephyr SAL implementation for PA sync creation and callbacks.
service/stacks/zephyr/sal_le_scan_interface.c Switch to Zephyr scan recv callback + propagate SID/interval/tx power.
service/stacks/include/sal_pa_sync_interface.h New SAL PA sync API definitions/options and prototypes.
service/src/scan_manager.h Update scan result data update signature to const uint8_t*.
service/src/scan_manager.c Mark scan results as periodic advertising based on interval.
service/src/pa_sync_service.h New PA sync service API and SAL-to-service callback hooks.
service/src/pa_sync_service.c New PA sync service implementation + event dispatch.
service/src/pa_sync_event.h Define PA sync event types and payload structs.
service/src/adapter_service.c Start/stop PA sync service with LE enable/disable.
service/ipc/socket/src/bt_socket_server.c Route PA sync IPC commands to new handler.
service/ipc/socket/src/bt_socket_scan.c Adjust scan callback handling for new IPC subcode scheme.
service/ipc/socket/src/bt_socket_pa_sync.c New PA sync socket IPC server/client callback implementation.
service/ipc/socket/src/bt_socket_client.c Register PA sync callback range dispatch.
service/ipc/socket/include/bt_socket.h Expose PA sync socket process/callback APIs.
service/ipc/socket/include/bt_message_scan.h Keep old enum stable; add new IPC subcodes/codes for scan result callback.
service/ipc/socket/include/bt_message_pa_sync.h New PA sync IPC codes and message/callback payloads.
service/ipc/socket/include/bt_message.h Add PA sync payload unions to the common packet.
service/ipc/socket/include/bt_ipc_code.h Add new IPC code groups for PA / PA sync.
framework/socket/bt_pa_sync.c New socket-based framework wrapper for bt_pa_sync_create.
framework/include/bt_uuid.h Add Broadcast Audio Announcement UUID (0x1852).
framework/include/bt_pa_sync.h New public PA sync API and parsed info struct.
framework/include/bt_le_scan.h Extend scan result struct with SID/interval/tx power/flags and constants.
framework/include/bluetooth.h Add broadcast ID invalid constant and broadcast name max length.
framework/include/advertiser_data.h Add generic advertiser_data_parse() callback type + API.
framework/common/advertiser_data_helper.c Implement advertiser_data_parse() and PA-sync advertising parsing helper.
framework/api/bt_pa_sync.c Add direct API binding to pa_sync_create() (non-socket path).
Makefile Build integration for PA sync and Auracast sink tool.
Kconfig Add BLUETOOTH_PA_SYNC and BLUETOOTH_AURACAST_SINK configs.
CMakeLists.txt CMake build integration for PA sync and Auracast sink tool.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread service/ipc/socket/src/bt_socket_pa_sync.c
Comment thread service/stacks/zephyr/sal_pa_sync_interface.c
Comment thread tools/auracast_sink.c
bt_addr_set(&prev->addr, result->addr.addr);
prev->life = BTTOOL_PA_SYNC_PA_REPORT_LIFE;
prev->type = result->addr_type;
prev->sid = result->sid;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the previous one is not valid when the new value arrives.

Comment on lines +272 to +282
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));
break;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both sizeof(info->broadcast_name) and data->len are length of the string + 1

Comment on lines +126 to +130
device = zalloc(sizeof(pa_sync_device_t));
if (device == NULL)
goto error;

memcpy(&sal_params.addr, &msg->addr, sizeof(bt_le_address_t));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already fixed in the next PR.
The final version is:

error:
    sync_terminated_callback(params->cbs, &msg->addr, msg->sid, params->context);
    free(device);

Comment on lines +289 to +309
if (!cbs || sid > BLE_SCAN_SID_MAX)
return BT_STATUS_PARM_INVALID;

if (!params)
params = &default_params;

if (params->skip > BT_PA_SYNC_SKIP_MAX)
return BT_STATUS_PARM_INVALID;

if (params->timeout > BT_PA_SYNC_TIMEOUT_MAX)
return BT_STATUS_PARM_INVALID;

msg = zalloc(sizeof(pa_sync_event_t) + sizeof(pa_sync_event_create_sync_t));
if (!msg) {
BT_LOGE("%s, malloc failed", __func__);
return BT_STATUS_NOMEM;
}

param = (pa_sync_event_create_sync_t*)msg->data;
memcpy(&msg->addr, addr, sizeof(bt_le_address_t));
msg->event = CREATE_SYNC;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the other services/profiles, we do not check if address is empty.

Copy link
Copy Markdown
Contributor

@huangyulong3 huangyulong3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General PR Feedback:

  1. The PR description is empty. For a feature of this size (2000+ lines, 33 files), please add a description covering: what PA sync is, the design approach, and any known limitations.

  2. Copyright year inconsistency: bt_message_pa_sync.h and framework/api/bt_pa_sync.c use 2026, while all other new files use 2025. Please align.

  3. sal_pa_sync_interface.h is missing a trailing newline at end of file.

sal_pa_sync_device_t* device = (sal_pa_sync_device_t*)data;
struct bt_le_per_adv_sync* sync = (struct bt_le_per_adv_sync*)context;

if (!device)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

device_delete() calls pa_sync_on_terminated() then free(device). But in create_sync() error path, if bt_le_per_adv_sync_cb_register fails, device_delete(device) is called which triggers pa_sync_on_terminated — this is incorrect because the sync was never established. Consider separating the cleanup logic from the termination notification. A simple free() would suffice in the error path of create_sync().

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When create_sync failed, there should be a terminated callback even if it's not established. Since we don't really have a "establish failed" callback.


memcpy(device->info, info, sizeof(struct bt_le_per_adv_sync_synced_info));

pa_sync_on_established(device->id, &device->addr, device->sid);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on_synced(): The info pointer from Zephyr is likely stack-allocated or transient. You are doing a shallow memcpy of struct bt_le_per_adv_sync_synced_info, but this struct may contain pointers (e.g., addr) that become dangling after the callback returns. Verify that all fields in the copied struct are value types, or deep-copy any pointer members.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

info->addr is not used, we use device->addr instead.
info->conn is not used too.

err = bt_le_per_adv_sync_create(z_param, &device->sync);
if (err)
goto error;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bt_sal_pa_sync_cleanup(): The TODO comment says "add unregisteration for stack callbacks" — this should be addressed before merging. Without calling bt_le_per_adv_sync_cb_unregister(&sal_pa_sync_cbs), the Zephyr stack will still invoke on_synced after cleanup, leading to use-after-free on g_sal_pa_sync_info. Also, typo: "unregisteration" → "unregistration".

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Zephyr do not really have a bt_le_per_adv_sync_cb_unregister

break;
}
}
#endif
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: In bt_socket_client_pa_sync_callback, the SYNC_TERMINATED_CALLBACK and SYNC_REPORT_CALLBACK cases both read from _on_sync_established instead of their respective union members (_on_sync_terminated and _on_sync_report). While the struct layout happens to be identical today, this is fragile and will break silently if the structs diverge. Please use the correct union member for each case:

case PA_SYNC_SUBCODE_SYNC_TERMINATED_CALLBACK:
    if (cbs->on_sync_terminated) {
        cbs->on_sync_terminated(&packet->pa_sync_cb._on_sync_terminated.addr,
            packet->pa_sync_cb._on_sync_terminated.sid, context);
    }
    break;
case PA_SYNC_SUBCODE_SYNC_REPORT_CALLBACK:
    if (cbs->on_sync_report) {
        cbs->on_sync_report(&packet->pa_sync_cb._on_sync_report.addr,
            packet->pa_sync_cb._on_sync_report.sid, context);
    }
    break;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already fixed in the next PR.

The final version is:

    case PA_SYNC_SUBCODE_SYNC_TERMINATED_CALLBACK:
        if (cbs->on_sync_terminated) {
            cbs->on_sync_terminated(&packet->pa_sync_cb._on_sync_terminated.addr,
                packet->pa_sync_cb._on_sync_terminated.sid, context);
        }
        break;
    case PA_SYNC_SUBCODE_SYNC_REPORT_CALLBACK:
        if (cbs->on_sync_report) {
            bt_pa_sync_report_t report = { 0 };
            report.tx_power = packet->pa_sync_cb._on_sync_report.tx_power;
            report.rssi = packet->pa_sync_cb._on_sync_report.rssi;
            report.cnt = packet->pa_sync_cb._on_sync_report.cnt;
            report.subevent = packet->pa_sync_cb._on_sync_report.subevent;
            report.adv_data_len = packet->pa_sync_cb._on_sync_report.adv_data_len;
            if (report.adv_data_len)
                report.data = packet->pa_sync_cb._on_sync_report.data;

            cbs->on_sync_report(&packet->pa_sync_cb._on_sync_report.addr,
                packet->pa_sync_cb._on_sync_report.sid, &report, context);
        }
        break;

Comment thread tools/auracast_sink.c
{
switch (type) {
case BT_LE_ADDR_TYPE_PUBLIC:
return "Public";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: update_neaby_paupdate_nearby_pa. This function name is also referenced in the call site.

Comment thread tools/auracast_sink.c
{
if (!g_auracast_sink) {
PRINT("Not initialized");
return CMD_INVALID_OPT;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sync_create_cmd(): All option cases are empty — the parsed values from optarg are never stored or used. This means the sync command accepts arguments but silently ignores them. Either implement the option handling or add TODO comments explaining the plan. As-is, this is dead code that misleads users.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented in the next PR.

sal_params.options &= ~BT_SAL_PA_SYNC_OPTION_USE_LIST; /**< not supported */
sal_params.options |= params->params.no_report ? BT_SAL_PA_SYNC_OPTION_REPORTING_DISABLED : 0;
sal_params.options |= params->params.filter ? BT_SAL_PA_SYNC_OPTION_FILTER_ENABLED : 0;
sal_params.cte = 0; /**< nothing specified */
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create_sync(): sal_params.options &= ~BT_SAL_PA_SYNC_OPTION_USE_LIST on a zero-initialized struct is a no-op. The comment says "not supported" — if the Periodic Advertiser List is truly not supported, consider adding validation in pa_sync_create() to reject such requests early, rather than silently clearing the flag here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The accept list mechanism in not used in vela Bluetooth service.

{
pa_sync_device_t* device = (pa_sync_device_t*)data;

BT_LOGD("%s", __func__);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

process_sync_terminated() removes the device from the list while iterating via bt_list_foreachfunc_for_device. Calling bt_list_remove() during iteration can corrupt the list iterator or cause use-after-free depending on the bt_list implementation. Consider collecting devices to remove and doing the removal after iteration completes, or using a safe-iteration pattern.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a standard utilization of the finalizing hook function.


static void create_sync(const pa_sync_event_t* msg)
{
pa_sync_event_create_sync_t* params = (pa_sync_event_create_sync_t*)msg->data;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create_sync(): The cbs pointer is stored directly in pa_sync_device_t without any lifetime guarantee. If the caller frees or invalidates the callback struct after pa_sync_create() returns, the stored pointer becomes dangling. Consider either: (1) documenting that cbs must remain valid for the lifetime of the sync, or (2) copying the callbacks struct into the device.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is assumed that cbs must be valid until the periodic connection is terminated.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They're typically const static variables.

return BT_LE_EXT_ADV_SCAN_IND;
if (info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE)
return BT_LE_EXT_ADV_IND;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scan_recv_cb is invoked from the Zephyr BT RX thread context. The scan_on_result_data_update() call does a malloc + memcpy + do_in_service_loop, which is fine. However, scan_cbs is a file-scope static — if bt_le_scan_cb_register is called multiple times (e.g., rapid start/stop), the -EEXIST check in start_scan handles it, but stop_scan unconditionally calls bt_le_scan_cb_unregister. If another scan start races with stop, the callback could be unregistered while still in use. Consider adding a reference count or ensuring serialization.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This case is handled in adapter service. And is not considered in this PR.


STREAM_TO_UINT16(uuid_16, p);
adv_data_parse_uuid_16(info, uuid_16, data);
break;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adv_data_parsed() for BT_AD_NAME_SHORT/BT_AD_NAME_COMPLETE: strlcpy with MIN(sizeof(info->name), data->len) — note that data->len includes the AD Type byte (1 octet), so the actual name data length is data->len - 1. The data pointer data->data already skips the type byte, but the length passed should be data->len - 1 (or data->len since len field = total_length which includes type). Please double-check the adv_data_t struct semantics: if len = length_byte (which includes the type octet), then the payload is len - 1 bytes, and you should use MIN(sizeof(info->name), data->len - 1 + 1) to account for the null terminator. The current code may copy one extra byte.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "one extra byte" is reserved for the \0

Comment thread tools/utils.h

#include "bluetooth.h"

#define BTTOOL_STRCAT(dst, size, src, ...) \
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utils.h is missing an include guard (#ifndef __UTILS_H__ / #define __UTILS_H__). Multiple inclusion will cause redefinition errors for the BTTOOL_STRCAT macro and the function declarations.

static struct bt_le_per_adv_sync_cb sal_pa_sync_cbs = {
.synced = on_synced,
.term = NULL,
.recv = NULL,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sal_pa_sync_cbs: The term and recv callbacks are set to NULL. Without a term callback, the SAL layer will never know when Zephyr terminates a sync (e.g., due to timeout or remote side stopping). This means pa_sync_on_terminated() will only be called from device_delete() during cleanup, but never during normal operation when the controller loses sync. This seems like a significant missing piece — at minimum, a term callback should be implemented to properly notify the service layer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemanted in the next PR.

*/
typedef void (*on_sync_report_callback)(const bt_le_address_t* addr, uint8_t sid, void* context);

typedef struct {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on_sync_report_callback signature only passes addr, sid, and context — but no actual report data (tx_power, rssi, cte, adv_data, etc.). The pa_sync_event_report_data_t struct in pa_sync_event.h defines all these fields, but they are never surfaced to the API consumer. This makes the report callback unusable in practice. Consider adding a report data parameter to the callback signature.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented in the next PR

typedef void (*on_pa_sync_report_callback)(const bt_le_address_t* addr, uint8_t sid,
    const bt_pa_sync_report_t* report, void* context);

{
pa_sync_event_t* msg = (pa_sync_event_t*)data;

BT_LOGD("%s, event = %s(%d)", __func__, pa_sync_event_to_string(msg->event), msg->event);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pa_sync_process_message(): The TERMINATE_SYNC and SYNC_REPORT events are defined in the enum but not handled in the switch. TERMINATE_SYNC falls through to default silently. At minimum, add a log warning for unhandled events, or implement the terminate path since pa_sync_terminate() currently returns BT_STATUS_UNSUPPORTED.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented in the next PR.

    switch (msg->event) {
    case CREATE_SYNC:
        create_sync(msg);
        break;
    case TERMINATE_SYNC:
        terminate_sync(msg);
        break;
    case SYNC_ESTABLISHED:
        sync_established(msg);
        break;
    case SYNC_TERMINATED:
        sync_terminated(msg);
        break;
    case SYNC_REPORT:
        sync_report(msg);
        break;
    case BIGINFO_RECEIVED:
        biginfo_received(msg);
        break;
    default:
        break;
    }

break;
}
case BLE_SCAN_SUBCODE_SCAN_CALLBACK: {
bt_scan_remote_t* scan = INT2PTR(bt_scan_remote_t*) packet->scan_cb._on_scan_result_cb.scanner;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new BLE_SCAN_SUBCODE_SCAN_CALLBACK handler does not check if tmp is NULL after malloc. If allocation fails, the subsequent memcpy(tmp, ...) will crash. Add a NULL check:

ble_scan_result_t* tmp = malloc(sizeof(ble_scan_result_t) + result->length);
if (!tmp)
    break;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This keeps the code exactly same as it was before.

return BT_STATUS_FAIL;
}

bt_status_t bt_sal_pa_sync_cleanup(void)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bt_sal_pa_create_sync(): In the error path, both z_param and req are freed. However, req->context points to z_param. If sal_send_req fails after the request has been partially processed (unlikely but possible in edge cases), z_param could be double-freed — once here and once in create_sync(). Consider setting req->context = NULL before freeing, or restructuring ownership so only one path frees z_param.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If sal_send_req failed, create_sync will not be invoked.

* 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,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bt_pa_sync_create() in the direct API path does not validate ins or addr for NULL. The socket path (framework/socket/bt_pa_sync.c) does validate with BT_SOCKET_INS_VALID and BT_SOCKET_PTR_VALID. Add similar NULL checks here for consistency and safety.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as all the other profiles, we do not check instance for local apis. Because they're never used.

@@ -0,0 +1,79 @@
/****************************************************************************
* Copyright (C) 2025 Xiaomi Corporation
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is developed in 2025.

@@ -0,0 +1,95 @@
/****************************************************************************
* Copyright (C) 2025 Xiaomi Corporation
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is developped in 2025

#include "bluetooth.h"

#ifndef SAL_BIT
#define SAL_BIT(x) (1UL << (x))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Used the BIT is better.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BIT() is not provided now.
We will have BIT() since #473

gzh-terry and others added 27 commits March 23, 2026 15:01
bug: v/82379

Periodic advertising often comes from extended scanning, so we add an parser here.
An alternative is Periodic Advertising Sync Transfer (to be implemented later).

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82379

Parse the scan result at the client side, so we can reduce the uplink data.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82275

Add TxPower, Periodic Advertising Interval, and correct the conversion of adv_type.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82380

Initial version of Auracast sink test tool

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82380

Add scan command to search active Auracast sources.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82379

Parse scan result at bttol to check if there is an Auracast source available.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82379

Skip logs that are not available.
Add more debug logs on error.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82379

Allow to stop scanning for periodic advertisers.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82820

Not sure the reason but we decided to add an extra flag to indicate whether periodic advertising is present in the scan result.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82820

Modify message codes so its safe when client and server have different version of codes.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82379

Record a nearby advertiser for easier testing.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82379

A command to initiate a sync connection.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82581

A initial version of PA sync API.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82581

A initial version of ipc codes.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82581

Allow to generate a create sync message to socket server.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82581

Extract message from ipc and relay to the service

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82581

All the actions shall be in service loop.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82581

This patch sends the create sync command to SAL.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82275

Allow to transfer to service loop at SAL.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82275

A device list is necessary at SAL to record the sync object from Zephyr.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82275

Generate callback from SAL and post to service loop.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82275

Generate a sync establish or terminated callback when sync success and failed.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82275

Add `new` and `delete` function for sync devices.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82380

Use `pa_sync_send_message` for all pa sync messages.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82380

Allow to generate callback for each applications that watching a specific device.

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82380

Allow to generate ipc message from server to client

Signed-off-by: Zihao Gao <gaozihao@xiaomi.com>
bug: v/82380

Fix typo: rename update_neaby_pa to update_nearby_pa.

Signed-off-by: liyuheng <liyuheng@xiaomi.com>
@chengkai15
Copy link
Copy Markdown
Contributor

PR #527 初步审查 — Bluetooth: LE: Add PA support

概述: 33 文件 2084+/36-,添加 LE Periodic Advertising Sync 支持。

❌ 阻断级问题

1. PR body 为空

  • 2084 行代码、33 个文件的大型 PR,body 为空字符串
  • 必须补充:架构设计、测试方案、与 Auracast #546 (Auracast) 的关系、已知限制

2. 与 #546 的关联性不明

  • PA sync 是 Auracast 的前置依赖
  • 需确认:是否为 Auracast #546 的拆分?两者的依赖关系和合并顺序?

请补充完整 PR 描述后我进行深入审查。

@expliyh expliyh closed this Mar 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants