Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/sync-upstream.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Sync fork with upstream bluez/bluer
name: Sync Upstream

on:
schedule:
# Run daily at 00:00 UTC
- cron: '0 0 * * *'
workflow_dispatch: # Allow manual trigger

jobs:
sync:
runs-on: ubuntu-latest
permissions:
contents: write

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Configure Git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Add upstream remote
run: git remote add upstream https://github.com/bluez/bluer.git

- name: Fetch upstream
run: git fetch upstream

- name: Sync main branch
run: |
git checkout main
git merge upstream/main --no-edit
git push origin main

- name: Rebase feature branch
run: |
git checkout feature/scan-response-data
git rebase main
git push origin feature/scan-response-data --force-with-lease
continue-on-error: true
72 changes: 72 additions & 0 deletions bluer/src/adv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,41 @@ pub struct Advertisement {
/// provided value must be in range [-127 to +20], where
/// units are in dBm.
pub tx_power: Option<i16>,

// ========== Scan Response Data (BlueZ experimental) ==========

/// List of UUIDs to include in the "Service UUID" field of
/// the Scan Response Data.
///
/// Note: This is an experimental BlueZ feature. Requires
/// `Experimental = true` in `/etc/bluetooth/main.conf`.
pub scan_response_service_uuids: BTreeSet<Uuid>,
/// Manufacturer Data fields to include in the Scan Response Data.
///
/// Keys are the Manufacturer ID to associate with the data.
///
/// Note: This is an experimental BlueZ feature.
pub scan_response_manufacturer_data: BTreeMap<u16, Vec<u8>>,
/// Array of UUIDs to include in "Service Solicitation"
/// field of the Scan Response Data.
///
/// Note: This is an experimental BlueZ feature.
pub scan_response_solicit_uuids: BTreeSet<Uuid>,
/// Service Data elements to include in the Scan Response Data.
///
/// The keys are the UUID to associate with the data.
/// This is useful for Legacy Advertising where you need to
/// split data between the main advertising packet and scan response.
///
/// Note: This is an experimental BlueZ feature.
pub scan_response_service_data: BTreeMap<Uuid, Vec<u8>>,
/// Raw Scan Response Data to include.
///
/// Key is the advertising type and value is the data as byte array.
///
/// Note: This is an experimental BlueZ feature.
pub scan_response_data: BTreeMap<u8, Vec<u8>>,

#[doc(hidden)]
pub _non_exhaustive: (),
}
Expand Down Expand Up @@ -290,6 +325,43 @@ impl Advertisement {
cr_property!(ib, "TxPower", la => {
la.tx_power
});

// Scan Response properties (BlueZ experimental)
cr_property!(ib, "ScanResponseServiceUUIDs", la => {
if la.scan_response_service_uuids.is_empty() {
None
} else {
Some(la.scan_response_service_uuids.iter().map(|uuid| uuid.to_string()).collect::<Vec<_>>())
}
});
cr_property!(ib, "ScanResponseManufacturerData", la => {
if la.scan_response_manufacturer_data.is_empty() {
None
} else {
Some(la.scan_response_manufacturer_data.clone().into_iter().map(|(k, v)| (k, Variant(v))).collect::<HashMap<_, _>>())
}
});
cr_property!(ib, "ScanResponseSolicitUUIDs", la => {
if la.scan_response_solicit_uuids.is_empty() {
None
} else {
Some(la.scan_response_solicit_uuids.iter().map(|uuid| uuid.to_string()).collect::<Vec<_>>())
}
});
cr_property!(ib, "ScanResponseServiceData", la => {
if la.scan_response_service_data.is_empty() {
None
} else {
Some(la.scan_response_service_data.iter().map(|(k, v)| (k.to_string(), Variant(v.clone()))).collect::<HashMap<_, _>>())
}
});
cr_property!(ib, "ScanResponseData", la => {
if la.scan_response_data.is_empty() {
None
} else {
Some(la.scan_response_data.iter().map(|(k, v)| (*k, Variant(v.clone()))).collect::<HashMap<_, _>>())
}
});
})
}

Expand Down