blob: 2d0541a2f22de6213d1efce26e300192dc50b345 [file]
/*
*
* Copyright (c) 2026 Project CHIP Authors
* All rights reserved.
*
* 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.
*/
#pragma once
#include <lib/core/CHIPError.h>
#include <lib/support/Span.h>
#include <cstdint>
namespace chip {
namespace app {
namespace Clusters {
namespace CommissioningProxy {
/**
* @brief The BLE operations a commissioning proxy needs that have no portable form.
*
* Everything else the BLE transport does — the BTP handshake, endpoint bookkeeping,
* message relay — goes through chip::Ble, which every platform with a BLE stack
* provides. Two things do not: switching the local BLE role, and driving a scan that
* reports commissionable devices. Those live here so CommissioningProxyBleTransport
* stays free of any platform header, and so a test can drive it against a fake.
*
* One implementation per platform. The application owns the instance and passes it to
* the transport, which keeps a reference and never takes ownership.
*/
class CommissioningProxyBleAdapter
{
public:
/**
* Fired once per discovered commissionable device, on the Matter event loop, with
* @p context passed back unchanged.
*
* Reported as scalars rather than as a cluster struct: the transport has to build
* the ScanResultStruct from its own stored copy anyway (the emit path outlives this
* call), so building one here too would duplicate that mapping. A BLE
* advertisement carries no extended data and no Wi-Fi band, so there is nothing
* else to report.
*
* @p address is the 6-byte BD_ADDR and is only valid for the duration of the call.
*/
using DiscoveryCallback = void (*)(void * context, ByteSpan address, uint16_t discriminator, uint16_t vendorId,
uint16_t productId);
virtual ~CommissioningProxyBleAdapter() = default;
/**
* Switch the local BLE role from peripheral to central.
*
* A commissioning proxy advertises as a peripheral so it can be commissioned onto
* the fabric itself, then has to act as a central to reach the device it proxies
* for. Called on the first ProxyConnectRequest over BLE, and again on later ones,
* so it must succeed when the stack is already central.
*
* - CHIP_NO_ERROR: the stack is in central role.
* - CHIP_ERROR_BUSY: prior peripheral activity is still winding down; the
* ProxyConnectRequest is answered BUSY and may be retried.
* - other error: the switch failed; the request is answered FAILURE.
*/
virtual CHIP_ERROR EnableCentralRole() = 0;
/**
* Start reporting commissionable devices through @p cb.
*
* BLE has a single scanner, shared by the foreground scan, the background scan and
* connect, so this reports CHIP_ERROR_BUSY when the scanner is already held. The
* transport arbitrates between its own users, so BUSY here means something outside
* it holds the radio; the background-scan registry treats that as "defer and retry".
*/
virtual CHIP_ERROR StartScan(DiscoveryCallback cb, void * context) = 0;
/**
* Stop a scan started by StartScan and release the scanner. A no-op when no scan is
* running, so teardown paths can call it unconditionally.
*
* Once this returns, nothing discovered by the stopped scan may be reported —
* including a result the platform has already queued but not yet delivered. A
* platform that discovers on one thread and reports on the Matter event loop has to
* invalidate what is in flight, not merely stop discovering: the next StartScan can
* be a different scan with different results, and a leaked result would be counted
* as one of its own. The Linux implementation stamps each queued result with a scan
* generation and drops any whose stamp is no longer current.
*/
virtual void StopScan() = 0;
};
} // namespace CommissioningProxy
} // namespace Clusters
} // namespace app
} // namespace chip