mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 22:56:12 -04:00
Implementation of BLE L2CAP connecting flow.
PiperOrigin-RevId: 749092197
This commit is contained in:
committed by
Copybara-Service
parent
24b8cff1a7
commit
4911d49f82
@@ -284,8 +284,14 @@ BleV2Socket BleV2Medium::Connect(const std::string& service_id,
|
||||
BleL2capSocket BleV2Medium::ConnectOverL2cap(
|
||||
const std::string& service_id, TxPowerLevel tx_power_level,
|
||||
const BleV2Peripheral& peripheral, CancellationFlag* cancellation_flag) {
|
||||
// TODO(mingshiouwu): Replace with a real implementation connecting flow.
|
||||
return BleL2capSocket(peripheral, nullptr);
|
||||
BleL2capSocket socket;
|
||||
peripheral.GetImpl([&](api::ble_v2::BlePeripheral& device) {
|
||||
socket = BleL2capSocket(
|
||||
peripheral,
|
||||
impl_->ConnectOverL2cap(peripheral.GetPsm(), service_id, tx_power_level,
|
||||
device, cancellation_flag));
|
||||
});
|
||||
return socket;
|
||||
}
|
||||
|
||||
bool BleV2Medium::IsExtendedAdvertisementsAvailable() {
|
||||
|
||||
@@ -336,6 +336,7 @@ class GattClient final {
|
||||
|
||||
class BleL2capSocket final {
|
||||
public:
|
||||
BleL2capSocket() = default;
|
||||
BleL2capSocket(BleV2Peripheral peripheral,
|
||||
std::unique_ptr<api::ble_v2::BleL2capSocket> socket)
|
||||
: peripheral_(peripheral) {}
|
||||
|
||||
@@ -45,6 +45,14 @@ typedef void (^GNCRequestDisconnectionHandler)(id<GNCPeripheral> peripheral);
|
||||
- (instancetype)initWithPeripheral:(id<GNCPeripheral>)peripheral
|
||||
requestDisconnectionHandler:(GNCRequestDisconnectionHandler)requestDisconnectionHandler;
|
||||
|
||||
/**
|
||||
* Opens a L2CAP channel with the @c PSM.
|
||||
*
|
||||
* @param PSM The PSM to use for opening the L2CAP channel.
|
||||
*/
|
||||
// TODO: b/399815436 - Add CompletionHandler for this method.
|
||||
- (void)openL2CAPChannelWithPSM:(uint16_t)PSM;
|
||||
|
||||
/** Cancels an active or pending local connection to a peripheral. */
|
||||
- (void)disconnect;
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ static char *const kGNCBLEL2CAPClientQueueLabel = "com.googlenearby.GNCBLEL2CAPC
|
||||
GNCRequestDisconnectionHandler _requestDisconnectionHandler;
|
||||
|
||||
// The L2CAP channel that is used to send and receive data.
|
||||
CBL2CAPChannel *_channel;
|
||||
CBL2CAPChannel *_l2CAPChannel;
|
||||
}
|
||||
|
||||
- (instancetype)initWithPeripheral:(id<GNCPeripheral>)peripheral
|
||||
@@ -58,6 +58,10 @@ static char *const kGNCBLEL2CAPClientQueueLabel = "com.googlenearby.GNCBLEL2CAPC
|
||||
return self;
|
||||
};
|
||||
|
||||
- (void)openL2CAPChannelWithPSM:(uint16_t)PSM {
|
||||
[_peripheral openL2CAPChannelWithPSM:PSM];
|
||||
}
|
||||
|
||||
- (void)disconnect {
|
||||
dispatch_async(_queue, ^{
|
||||
_requestDisconnectionHandler(_peripheral);
|
||||
@@ -74,7 +78,7 @@ static char *const kGNCBLEL2CAPClientQueueLabel = "com.googlenearby.GNCBLEL2CAPC
|
||||
return;
|
||||
}
|
||||
GTMLoggerInfo(@"[NEARBY] Opened L2CAP channel: %@", channel);
|
||||
_channel = channel;
|
||||
_l2CAPChannel = channel;
|
||||
// TODO: b/399815436 - Implement to wrap up l2cap channel.
|
||||
}
|
||||
|
||||
|
||||
@@ -211,6 +211,15 @@ typedef void (^GNCOpenL2CAPServerCompletionHandler)(GNCBLEL2CAPServer *_Nullable
|
||||
- (void)openL2CAPServerWithCompletionHandler:(GNCOpenL2CAPServerCompletionHandler)completionHandler
|
||||
peripheralManager:(nullable id<GNCPeripheralManager>)peripheralManager;
|
||||
|
||||
/**
|
||||
* Opens a L2CAP channel with the @c PSM on the remote peripheral.
|
||||
*
|
||||
* @param PSM The PSM to use for opening the L2CAP channel.
|
||||
* @param remotePeripheral The peripheral to which the L2CAP channel is being opened.
|
||||
*/
|
||||
// TODO: b/399815436 - Add CompletionHandler for this method.
|
||||
- (void)openL2CAPChannelWithPSM:(uint16_t)PSM peripheral:(id<GNCPeripheral>)remotePeripheral;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEGATTClient.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEGATTServer.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEL2CAPServer.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEL2CAPClient.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCCentralManager.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCPeripheral.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLEv2/NSData+GNCBase85.h"
|
||||
@@ -54,6 +55,7 @@ static GNCBLEL2CAPServer *_Nonnull CreateL2CapServer(
|
||||
// The active GATT server, or @nil if one hasn't been started yet.
|
||||
GNCBLEGATTServer *_server;
|
||||
GNCBLEL2CAPServer *_l2capServer;
|
||||
GNCBLEL2CAPClient *_l2capClient;
|
||||
|
||||
// The services that is being actively scanned for.
|
||||
NSMutableArray<CBUUID *> *_scanningServiceUUIDs;
|
||||
@@ -223,6 +225,18 @@ static GNCBLEL2CAPServer *_Nonnull CreateL2CapServer(
|
||||
});
|
||||
}
|
||||
|
||||
- (void)openL2CAPChannelWithPSM:(uint16_t)PSM peripheral:(id<GNCPeripheral>)remotePeripheral {
|
||||
dispatch_async(_queue, ^{
|
||||
if (!_l2capClient) {
|
||||
_l2capClient =
|
||||
[[GNCBLEL2CAPClient alloc] initWithPeripheral:remotePeripheral
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> _Nonnull peripheral){
|
||||
}];
|
||||
}
|
||||
[_l2capClient openL2CAPChannelWithPSM:PSM];
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Internal
|
||||
|
||||
- (void)internalStartScanningIfPoweredOn {
|
||||
|
||||
@@ -112,6 +112,18 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (void)readValueForCharacteristic:(CBCharacteristic *)characteristic;
|
||||
|
||||
/**
|
||||
* Opens an L2CAP channel with the specified PSM.
|
||||
*
|
||||
* When you call this method to open an L2CAP channel, the peripheral calls the
|
||||
* @c peripheral:didOpenL2CAPChannel:error: method of its delegate object. If the peripheral
|
||||
* successfully opens the L2CAP channel, you can access it through the peripheral’s @c l2capChannels
|
||||
* property.
|
||||
*
|
||||
* @param PSM The PSM value to use for the L2CAP channel.
|
||||
*/
|
||||
- (void)openL2CAPChannelWithPSM:(uint16_t)PSM;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
|
||||
@@ -55,6 +55,15 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/** Similates a delay in all delegate calls by the specified amount. */
|
||||
@property(nonatomic, readwrite) NSTimeInterval delegateDelay;
|
||||
|
||||
/**
|
||||
* Similates a @c openL2CAPChannelWithPSM: error.
|
||||
*
|
||||
* Setting this error to a value other than @c nil will simulate a failure when calling
|
||||
* @c openL2CAPChannelWithPSM: and will call the
|
||||
* @c gnc_peripheral:didOpenL2CAPChannel:error: delegate method with the provided error.
|
||||
*/
|
||||
@property(nonatomic, nullable, readwrite) NSError *openL2CAPChannelError;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -119,6 +119,18 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
}
|
||||
}
|
||||
|
||||
- (void)openL2CAPChannelWithPSM:(uint16_t)PSM {
|
||||
[self delayDelegateUsingBlock:^() {
|
||||
if (_openL2CAPChannelError) {
|
||||
CBL2CAPChannel *channel = [[CBL2CAPChannel alloc] init];
|
||||
[peripheralDelegate gnc_peripheral:self
|
||||
didOpenL2CAPChannel:channel
|
||||
error:_openL2CAPChannelError];
|
||||
}
|
||||
// TODO: b/399815436 - Add testing for L2CAP channels if error is nil.
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -147,6 +147,18 @@ class BleMedium : public api::ble_v2::BleMedium {
|
||||
api::ble_v2::BlePeripheral &peripheral,
|
||||
CancellationFlag *cancellation_flag) override;
|
||||
|
||||
// TODO(b/290385712): cancellation_flag support is not yet implemented.
|
||||
//
|
||||
// Connects to a BLE peripheral over L2CAP.
|
||||
//
|
||||
// The peripheral must outlive the socket or undefined behavior will occur. The peripheral
|
||||
// should not be modified by this method.
|
||||
//
|
||||
// On success, returns a new BleL2capSocket. On error, returns nullptr.
|
||||
std::unique_ptr<api::ble_v2::BleL2capSocket> ConnectOverL2cap(
|
||||
int psm, const std::string &service_id, api::ble_v2::TxPowerLevel tx_power_level,
|
||||
api::ble_v2::BlePeripheral &peripheral, CancellationFlag *cancellation_flag) override;
|
||||
|
||||
// Returns whether the hardware supports BOTH advertising extensions and extended scans.
|
||||
//
|
||||
// This is currently always false for all Apple hardware.
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEGATTServer.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEMedium.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCPeripheral.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEL2CAPClient.h"
|
||||
#import "internal/platform/implementation/apple/ble_gatt_client.h"
|
||||
#import "internal/platform/implementation/apple/ble_gatt_server.h"
|
||||
#import "internal/platform/implementation/apple/ble_l2cap_server_socket.h"
|
||||
@@ -461,6 +462,24 @@ std::unique_ptr<api::ble_v2::BleSocket> BleMedium::Connect(const std::string &se
|
||||
return std::move(socket);
|
||||
}
|
||||
|
||||
std::unique_ptr<api::ble_v2::BleL2capSocket> BleMedium::ConnectOverL2cap(
|
||||
int psm, const std::string &service_id, api::ble_v2::TxPowerLevel tx_power_level,
|
||||
api::ble_v2::BlePeripheral &peripheral, CancellationFlag *cancellation_flag) {
|
||||
// Check that the @c api::ble_v2::BlePeripheral is a @c nearby::apple::BlePeripheral and not a
|
||||
// @c nearby::apple::EmptyBlePeripheral instance, so we can retreive the CBPeripheral object.
|
||||
BlePeripheral *non_empty_peripheral = dynamic_cast<BlePeripheral *>(&peripheral);
|
||||
if (non_empty_peripheral == nullptr) {
|
||||
GTMLoggerError(@"[NEARBY] Failed to connect over L2CAP: peripheral is empty.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO: b/399815436 - Continue to add implementation for this method when BleL2capSocket is
|
||||
// ready.
|
||||
[medium_ openL2CAPChannelWithPSM:psm peripheral:non_empty_peripheral->GetPeripheral()];
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool BleMedium::IsExtendedAdvertisementsAvailable() {
|
||||
return [medium_ supportsExtendedAdvertisements];
|
||||
}
|
||||
|
||||
@@ -589,8 +589,9 @@ class BleMedium {
|
||||
//
|
||||
// On success, returns a new BleL2capSocket.
|
||||
// On error, returns nullptr.
|
||||
// Platform implementation should override this method if it supports L2CAP.
|
||||
virtual std::unique_ptr<BleL2capSocket> ConnectOverL2cap(
|
||||
const std::string& service_id, TxPowerLevel tx_power_level,
|
||||
int psm, const std::string& service_id, TxPowerLevel tx_power_level,
|
||||
BlePeripheral& peripheral, CancellationFlag* cancellation_flag) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user