mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1228546 - Implement peripheral mode support for GATT API. r=brsun, r=mrbkap
This commit is contained in:
parent
54c4ed1fef
commit
c6da2ff1c4
@ -588,9 +588,9 @@ nsresult
|
||||
BluetoothDaemonGattModule::ClientSetAdvDataCmd(
|
||||
int aServerIf, bool aIsScanRsp, bool aIsNameIncluded,
|
||||
bool aIsTxPowerIncluded, int aMinInterval, int aMaxInterval, int aApperance,
|
||||
uint16_t aManufacturerLen, char* aManufacturerData,
|
||||
uint16_t aServiceDataLen, char* aServiceData,
|
||||
uint16_t aServiceUuidLen, char* aServiceUuid,
|
||||
const nsTArray<uint8_t>& aManufacturerData,
|
||||
const nsTArray<uint8_t>& aServiceData,
|
||||
const nsTArray<BluetoothUuid>& aServiceUuids,
|
||||
BluetoothGattResultHandler* aRes)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
@ -598,6 +598,17 @@ BluetoothDaemonGattModule::ClientSetAdvDataCmd(
|
||||
nsAutoPtr<DaemonSocketPDU> pdu(
|
||||
new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_SET_ADV_DATA, 0));
|
||||
|
||||
uint16_t manufacturerDataByteLen =
|
||||
aManufacturerData.Length() * sizeof(uint8_t);
|
||||
uint16_t serviceDataByteLen = aServiceData.Length() * sizeof(uint8_t);
|
||||
uint16_t serviceUuidsByteLen =
|
||||
aServiceUuids.Length() * sizeof(BluetoothUuid::mUuid);
|
||||
uint8_t* manufacturerData =
|
||||
const_cast<uint8_t*>(aManufacturerData.Elements());
|
||||
uint8_t* serviceData = const_cast<uint8_t*>(aServiceData.Elements());
|
||||
BluetoothUuid* serviceUuids =
|
||||
const_cast<BluetoothUuid*>(aServiceUuids.Elements());
|
||||
|
||||
nsresult rv = PackPDU(
|
||||
PackConversion<int, int32_t>(aServerIf),
|
||||
PackConversion<bool, uint8_t>(aIsScanRsp),
|
||||
@ -606,10 +617,12 @@ BluetoothDaemonGattModule::ClientSetAdvDataCmd(
|
||||
PackConversion<int, int32_t>(aMinInterval),
|
||||
PackConversion<int, int32_t>(aMaxInterval),
|
||||
PackConversion<int, int32_t>(aApperance),
|
||||
aManufacturerLen, aServiceDataLen, aServiceUuidLen,
|
||||
PackArray<char>(aManufacturerData, aManufacturerLen),
|
||||
PackArray<char>(aServiceData, aServiceDataLen),
|
||||
PackArray<char>(aServiceUuid, aServiceUuidLen), *pdu);
|
||||
manufacturerDataByteLen, serviceDataByteLen, serviceUuidsByteLen,
|
||||
PackArray<uint8_t>(manufacturerData, aManufacturerData.Length()),
|
||||
PackArray<uint8_t>(serviceData, aServiceData.Length()),
|
||||
PackArray<PackReversed<BluetoothUuid>>(
|
||||
serviceUuids, aServiceUuids.Length()),
|
||||
*pdu);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -2415,17 +2428,17 @@ void
|
||||
BluetoothDaemonGattInterface::SetAdvData(
|
||||
int aServerIf, bool aIsScanRsp, bool aIsNameIncluded,
|
||||
bool aIsTxPowerIncluded, int aMinInterval, int aMaxInterval, int aApperance,
|
||||
uint16_t aManufacturerLen, char* aManufacturerData,
|
||||
uint16_t aServiceDataLen, char* aServiceData,
|
||||
uint16_t aServiceUUIDLen, char* aServiceUUID,
|
||||
const nsTArray<uint8_t>& aManufacturerData,
|
||||
const nsTArray<uint8_t>& aServiceData,
|
||||
const nsTArray<BluetoothUuid>& aServiceUuids,
|
||||
BluetoothGattResultHandler* aRes)
|
||||
{
|
||||
MOZ_ASSERT(mModule);
|
||||
|
||||
nsresult rv = mModule->ClientSetAdvDataCmd(
|
||||
aServerIf, aIsScanRsp, aIsNameIncluded, aIsTxPowerIncluded, aMinInterval,
|
||||
aMaxInterval, aApperance, aManufacturerLen, aManufacturerData,
|
||||
aServiceDataLen, aServiceData, aServiceUUIDLen, aServiceUUID, aRes);
|
||||
aMaxInterval, aApperance, aManufacturerData, aServiceData, aServiceUuids,
|
||||
aRes);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
DispatchError(aRes, rv);
|
||||
|
@ -203,12 +203,9 @@ public:
|
||||
int aMinInterval,
|
||||
int aMaxInterval,
|
||||
int aApperance,
|
||||
uint16_t aManufacturerLen,
|
||||
char* aManufacturerData,
|
||||
uint16_t aServiceDataLen,
|
||||
char* aServiceData,
|
||||
uint16_t aServiceUUIDLen,
|
||||
char* aServiceUUID,
|
||||
const nsTArray<uint8_t>& aManufacturerData,
|
||||
const nsTArray<uint8_t>& aServiceData,
|
||||
const nsTArray<BluetoothUuid>& aServiceUuids,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
|
||||
nsresult ClientTestCommandCmd(int aCommand,
|
||||
@ -908,9 +905,9 @@ public:
|
||||
int aMinInterval,
|
||||
int aMaxInterval,
|
||||
int aApperance,
|
||||
uint16_t aManufacturerLen, char* aManufacturerData,
|
||||
uint16_t aServiceDataLen, char* aServiceData,
|
||||
uint16_t aServiceUuidLen, char* aServiceUuid,
|
||||
const nsTArray<uint8_t>& aManufacturerData,
|
||||
const nsTArray<uint8_t>& aServiceData,
|
||||
const nsTArray<BluetoothUuid>& aServiceUuids,
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
void TestCommand(int aCommand,
|
||||
|
@ -190,6 +190,8 @@ public:
|
||||
int mClientIf;
|
||||
int mConnId;
|
||||
RefPtr<BluetoothReplyRunnable> mStartLeScanRunnable;
|
||||
RefPtr<BluetoothReplyRunnable> mStartAdvertisingRunnable;
|
||||
RefPtr<BluetoothReplyRunnable> mStopAdvertisingRunnable;
|
||||
RefPtr<BluetoothReplyRunnable> mConnectRunnable;
|
||||
RefPtr<BluetoothReplyRunnable> mDisconnectRunnable;
|
||||
RefPtr<BluetoothReplyRunnable> mDiscoverRunnable;
|
||||
@ -203,6 +205,8 @@ public:
|
||||
BluetoothGattClientReadDescState mReadDescriptorState;
|
||||
BluetoothGattClientWriteDescState mWriteDescriptorState;
|
||||
|
||||
BluetoothGattAdvertisingData mAdvertisingData;
|
||||
|
||||
/**
|
||||
* These temporary arrays are used only during discover operations.
|
||||
* All of them are empty if there are no ongoing discover operations.
|
||||
@ -293,6 +297,7 @@ public:
|
||||
*/
|
||||
bool mIsRegistering;
|
||||
|
||||
RefPtr<BluetoothReplyRunnable> mRegisterServerRunnable;
|
||||
RefPtr<BluetoothReplyRunnable> mConnectPeripheralRunnable;
|
||||
RefPtr<BluetoothReplyRunnable> mDisconnectPeripheralRunnable;
|
||||
RefPtr<BluetoothReplyRunnable> mUnregisterServerRunnable;
|
||||
@ -904,6 +909,195 @@ BluetoothGattManager::StopLeScan(const BluetoothUuid& aScanUuid,
|
||||
new StopLeScanResultHandler(aRunnable, client->mClientIf));
|
||||
}
|
||||
|
||||
class BluetoothGattManager::StartAdvertisingResultHandler final
|
||||
: public BluetoothGattResultHandler
|
||||
{
|
||||
public:
|
||||
StartAdvertisingResultHandler(BluetoothGattClient* aClient)
|
||||
: mClient(aClient)
|
||||
{
|
||||
MOZ_ASSERT(mClient);
|
||||
}
|
||||
|
||||
void Listen() override
|
||||
{
|
||||
MOZ_ASSERT(mClient->mStartAdvertisingRunnable);
|
||||
|
||||
DispatchReplySuccess(mClient->mStartAdvertisingRunnable);
|
||||
mClient->mStartAdvertisingRunnable = nullptr;
|
||||
}
|
||||
|
||||
void OnError(BluetoothStatus aStatus) override
|
||||
{
|
||||
BT_WARNING("BluetoothGattInterface::StartLeAdvertising failed: %d",
|
||||
(int)aStatus);
|
||||
MOZ_ASSERT(mClient->mStartAdvertisingRunnable);
|
||||
|
||||
// Unregister client if startAdvertising failed
|
||||
if (mClient->mClientIf > 0) {
|
||||
BluetoothGattManager* gattManager = BluetoothGattManager::Get();
|
||||
NS_ENSURE_TRUE_VOID(gattManager);
|
||||
|
||||
RefPtr<BluetoothVoidReplyRunnable> result =
|
||||
new BluetoothVoidReplyRunnable(nullptr);
|
||||
gattManager->UnregisterClient(mClient->mClientIf, result);
|
||||
}
|
||||
|
||||
DispatchReplyError(mClient->mStartAdvertisingRunnable, aStatus);
|
||||
mClient->mStartAdvertisingRunnable = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<BluetoothGattClient> mClient;
|
||||
};
|
||||
|
||||
class BluetoothGattManager::SetAdvDataResultHandler final
|
||||
: public BluetoothGattResultHandler
|
||||
{
|
||||
public:
|
||||
SetAdvDataResultHandler(BluetoothGattClient* aClient)
|
||||
: mClient(aClient)
|
||||
{
|
||||
MOZ_ASSERT(mClient);
|
||||
}
|
||||
|
||||
void SetAdvData() override
|
||||
{
|
||||
sBluetoothGattInterface->Listen(
|
||||
mClient->mClientIf,
|
||||
true /* Start */,
|
||||
new StartAdvertisingResultHandler(mClient));
|
||||
}
|
||||
|
||||
void OnError(BluetoothStatus aStatus) override
|
||||
{
|
||||
BT_WARNING("BluetoothGattInterface::StartLeAdvertising failed: %d",
|
||||
(int)aStatus);
|
||||
MOZ_ASSERT(mClient->mStartAdvertisingRunnable);
|
||||
|
||||
// Unregister client if startAdvertising failed
|
||||
if (mClient->mClientIf > 0) {
|
||||
BluetoothGattManager* gattManager = BluetoothGattManager::Get();
|
||||
NS_ENSURE_TRUE_VOID(gattManager);
|
||||
|
||||
RefPtr<BluetoothVoidReplyRunnable> result =
|
||||
new BluetoothVoidReplyRunnable(nullptr);
|
||||
gattManager->UnregisterClient(mClient->mClientIf, result);
|
||||
}
|
||||
|
||||
DispatchReplyError(mClient->mStartAdvertisingRunnable, aStatus);
|
||||
mClient->mStartAdvertisingRunnable = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<BluetoothGattClient> mClient;
|
||||
};
|
||||
|
||||
void
|
||||
BluetoothGattManager::StartAdvertising(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
const BluetoothGattAdvertisingData& aData,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
|
||||
// Reject the startAdvertising request if the clientIf is being used.
|
||||
if (NS_WARN_IF(index != sClients->NoIndex)) {
|
||||
DispatchReplyError(aRunnable,
|
||||
NS_LITERAL_STRING("start advertising failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
index = sClients->Length();
|
||||
sClients->AppendElement(new BluetoothGattClient(aAppUuid,
|
||||
BluetoothAddress::ANY));
|
||||
RefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
client->mStartAdvertisingRunnable = aRunnable;
|
||||
client->mAdvertisingData = aData;
|
||||
|
||||
// 'startAdvertising' will be proceeded after client registered
|
||||
sBluetoothGattInterface->RegisterClient(
|
||||
aAppUuid, new RegisterClientResultHandler(client));
|
||||
}
|
||||
|
||||
class BluetoothGattManager::StopAdvertisingResultHandler final
|
||||
: public BluetoothGattResultHandler
|
||||
{
|
||||
public:
|
||||
StopAdvertisingResultHandler(BluetoothGattClient* aClient)
|
||||
: mClient(aClient)
|
||||
{
|
||||
MOZ_ASSERT(mClient);
|
||||
}
|
||||
|
||||
void Listen() override
|
||||
{
|
||||
MOZ_ASSERT(mClient->mStopAdvertisingRunnable);
|
||||
|
||||
// Unregister client when stopLeScan succeeded
|
||||
if (mClient->mClientIf > 0) {
|
||||
BluetoothGattManager* gattManager = BluetoothGattManager::Get();
|
||||
NS_ENSURE_TRUE_VOID(gattManager);
|
||||
|
||||
RefPtr<BluetoothVoidReplyRunnable> result =
|
||||
new BluetoothVoidReplyRunnable(nullptr);
|
||||
gattManager->UnregisterClient(mClient->mClientIf, result);
|
||||
}
|
||||
|
||||
DispatchReplySuccess(mClient->mStopAdvertisingRunnable);
|
||||
mClient->mStopAdvertisingRunnable = nullptr;
|
||||
}
|
||||
|
||||
void OnError(BluetoothStatus aStatus) override
|
||||
{
|
||||
BT_WARNING("BluetoothGattInterface::StopAdvertising failed: %d",
|
||||
(int)aStatus);
|
||||
MOZ_ASSERT(mClient->mStopAdvertisingRunnable);
|
||||
|
||||
DispatchReplyError(mClient->mStopAdvertisingRunnable, aStatus);
|
||||
mClient->mStopAdvertisingRunnable = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<BluetoothGattClient> mClient;
|
||||
};
|
||||
|
||||
void
|
||||
BluetoothGattManager::StopAdvertising(const BluetoothUuid& aAppUuid,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
// Reject the stop advertising request
|
||||
DispatchReplyError(aRunnable, NS_LITERAL_STRING("StopAdvertising failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
|
||||
// Reject the stop advertising request if there is an ongoing one.
|
||||
if (client->mStopAdvertisingRunnable) {
|
||||
DispatchReplyError(aRunnable, STATUS_BUSY);
|
||||
return;
|
||||
}
|
||||
|
||||
client->mStopAdvertisingRunnable = aRunnable;
|
||||
sBluetoothGattInterface->Listen(
|
||||
client->mClientIf,
|
||||
false /* Stop */,
|
||||
new StopAdvertisingResultHandler(client));
|
||||
}
|
||||
|
||||
class BluetoothGattManager::ConnectResultHandler final
|
||||
: public BluetoothGattResultHandler
|
||||
{
|
||||
@ -1659,6 +1853,12 @@ public:
|
||||
mServer->mAddServiceState.Reset();
|
||||
}
|
||||
|
||||
if (mServer->mRegisterServerRunnable) {
|
||||
DispatchReplyError(mServer->mRegisterServerRunnable,
|
||||
NS_LITERAL_STRING("Register GATT server failed"));
|
||||
mServer->mRegisterServerRunnable = nullptr;
|
||||
}
|
||||
|
||||
mServer->mIsRegistering = false;
|
||||
sServers->RemoveElement(mServer);
|
||||
}
|
||||
@ -1667,6 +1867,48 @@ private:
|
||||
RefPtr<BluetoothGattServer> mServer;
|
||||
};
|
||||
|
||||
void
|
||||
BluetoothGattManager::RegisterServer(const BluetoothUuid& aAppUuid,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sServers->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (index == sServers->NoIndex) {
|
||||
index = sServers->Length();
|
||||
sServers->AppendElement(new BluetoothGattServer(aAppUuid));
|
||||
}
|
||||
RefPtr<BluetoothGattServer> server = (*sServers)[index];
|
||||
|
||||
/**
|
||||
* There are four cases here for handling aRunnable.
|
||||
* 1) Server interface is already registered: Resolve the runnable.
|
||||
* 2) Server interface is not registered, but there is
|
||||
* an existing |RegisterServerRunnable|: Reject with STATUS_BUSY.
|
||||
* 3) Server interface is registering without an existing
|
||||
* |RegisterServerRunnable|: Save the runnable into |GattServer| and will
|
||||
* resolve or reject it in |RegisterServerNotification| later.
|
||||
* 4) Server interface is neither registered nor registering: Save the
|
||||
* the runnable into |GattServer| and trigger a registration procedure.
|
||||
* The runnable will be resolved or rejected in
|
||||
* |RegisterServerNotification| later.
|
||||
*/
|
||||
if (server->mServerIf > 0) {
|
||||
DispatchReplySuccess(aRunnable);
|
||||
} else if (server->mRegisterServerRunnable) {
|
||||
DispatchReplyError(aRunnable, STATUS_BUSY);
|
||||
} else if (server->mIsRegistering) {
|
||||
server->mRegisterServerRunnable = aRunnable;
|
||||
} else {
|
||||
server->mRegisterServerRunnable = aRunnable;
|
||||
sBluetoothGattInterface->RegisterServer(
|
||||
aAppUuid, new RegisterServerResultHandler(server));
|
||||
}
|
||||
}
|
||||
|
||||
class BluetoothGattManager::ConnectPeripheralResultHandler final
|
||||
: public BluetoothGattResultHandler
|
||||
{
|
||||
@ -2569,7 +2811,9 @@ BluetoothGattManager::RegisterClientNotification(BluetoothGattStatus aStatus,
|
||||
NS_LITERAL_STRING(
|
||||
"StartLeScan failed due to registration failed"));
|
||||
client->mStartLeScanRunnable = nullptr;
|
||||
} else if (client->mConnectRunnable) {
|
||||
}
|
||||
|
||||
if (client->mConnectRunnable) {
|
||||
// Reject the connect request
|
||||
DispatchReplyError(client->mConnectRunnable,
|
||||
NS_LITERAL_STRING(
|
||||
@ -2577,6 +2821,15 @@ BluetoothGattManager::RegisterClientNotification(BluetoothGattStatus aStatus,
|
||||
client->mConnectRunnable = nullptr;
|
||||
}
|
||||
|
||||
if (client->mStartAdvertisingRunnable) {
|
||||
// Reject the start advertising request
|
||||
DispatchReplyError(
|
||||
client->mStartAdvertisingRunnable,
|
||||
NS_LITERAL_STRING(
|
||||
"StartAdvertising failed due to registration failed"));
|
||||
client->mStartAdvertisingRunnable = nullptr;
|
||||
}
|
||||
|
||||
sClients->RemoveElement(client);
|
||||
return;
|
||||
}
|
||||
@ -2594,7 +2847,9 @@ BluetoothGattManager::RegisterClientNotification(BluetoothGattStatus aStatus,
|
||||
sBluetoothGattInterface->Scan(
|
||||
aClientIf, true /* start */,
|
||||
new StartLeScanResultHandler(client));
|
||||
} else if (client->mConnectRunnable) {
|
||||
}
|
||||
|
||||
if (client->mConnectRunnable) {
|
||||
// Client just registered, proceed remaining connect request.
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(client->mConnectRunnable);
|
||||
sBluetoothGattInterface->Connect(
|
||||
@ -2602,6 +2857,17 @@ BluetoothGattManager::RegisterClientNotification(BluetoothGattStatus aStatus,
|
||||
TRANSPORT_AUTO,
|
||||
new ConnectResultHandler(client));
|
||||
}
|
||||
|
||||
if (client->mStartAdvertisingRunnable) {
|
||||
// StartAdvertising request will be proceed after SetAdvData succeeded.
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(client->mStartAdvertisingRunnable);
|
||||
BluetoothGattAdvertisingData* data = &(client->mAdvertisingData);
|
||||
sBluetoothGattInterface->SetAdvData(
|
||||
aClientIf, false /* isScanRsp */, data->mIncludeDevName,
|
||||
data->mIncludeTxPower, 0 /* min interval */, 0 /* max interval */,
|
||||
data->mAppearance, data->mManufacturerData, data->mServiceData,
|
||||
data->mServiceUuids, new SetAdvDataResultHandler(client));
|
||||
}
|
||||
}
|
||||
|
||||
class BluetoothGattManager::ScanDeviceTypeResultHandler final
|
||||
@ -3372,6 +3638,14 @@ BluetoothGattManager::RegisterServerNotification(BluetoothGattStatus aStatus,
|
||||
server->mAddServiceState.Reset();
|
||||
}
|
||||
|
||||
if (server->mRegisterServerRunnable) {
|
||||
// Reject the register server request
|
||||
DispatchReplyError(
|
||||
server->mRegisterServerRunnable,
|
||||
NS_LITERAL_STRING("Register server failed"));
|
||||
server->mRegisterServerRunnable = nullptr;
|
||||
}
|
||||
|
||||
sServers->RemoveElement(server);
|
||||
return;
|
||||
}
|
||||
@ -3399,6 +3673,11 @@ BluetoothGattManager::RegisterServerNotification(BluetoothGattStatus aStatus,
|
||||
server->mAddServiceState.mHandleCount,
|
||||
new ServerAddServiceResultHandler(server));
|
||||
}
|
||||
|
||||
if (server->mRegisterServerRunnable) {
|
||||
DispatchReplySuccess(server->mRegisterServerRunnable);
|
||||
server->mRegisterServerRunnable = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -35,6 +35,13 @@ public:
|
||||
void StopLeScan(const BluetoothUuid& aScanUuid,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
void StartAdvertising(const BluetoothUuid& aAppUuid,
|
||||
const BluetoothGattAdvertisingData& aData,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
void StopAdvertising(const BluetoothUuid& aAppUuid,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
void Connect(const BluetoothUuid& aAppUuid,
|
||||
const BluetoothAddress& aDeviceAddr,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
@ -92,6 +99,9 @@ public:
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
void RegisterServer(const BluetoothUuid& aAppUuid,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
void ConnectPeripheral(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
const BluetoothAddress& aAddress,
|
||||
@ -176,6 +186,9 @@ private:
|
||||
class UnregisterClientResultHandler;
|
||||
class StartLeScanResultHandler;
|
||||
class StopLeScanResultHandler;
|
||||
class StartAdvertisingResultHandler;
|
||||
class SetAdvDataResultHandler;
|
||||
class StopAdvertisingResultHandler;
|
||||
class ConnectResultHandler;
|
||||
class DisconnectResultHandler;
|
||||
class DiscoverResultHandler;
|
||||
|
@ -362,6 +362,35 @@ BluetoothServiceBluedroid::StopLeScanInternal(
|
||||
gatt->StopLeScan(aScanUuid, aRunnable);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceBluedroid::StartAdvertisingInternal(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
const BluetoothGattAdvertisingData& aAdvData,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ENSURE_BLUETOOTH_IS_ENABLED_VOID(aRunnable);
|
||||
|
||||
BluetoothGattManager* gatt = BluetoothGattManager::Get();
|
||||
ENSURE_GATT_MGR_IS_READY_VOID(gatt, aRunnable);
|
||||
|
||||
gatt->StartAdvertising(aAppUuid, aAdvData, aRunnable);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceBluedroid::StopAdvertisingInternal(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ENSURE_BLUETOOTH_IS_ENABLED_VOID(aRunnable);
|
||||
|
||||
BluetoothGattManager* gatt = BluetoothGattManager::Get();
|
||||
ENSURE_GATT_MGR_IS_READY_VOID(gatt, aRunnable);
|
||||
|
||||
gatt->StopAdvertising(aAppUuid, aRunnable);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceBluedroid::ConnectGattClientInternal(
|
||||
const BluetoothUuid& aAppUuid, const BluetoothAddress& aDeviceAddress,
|
||||
@ -543,6 +572,20 @@ BluetoothServiceBluedroid::GattClientWriteDescriptorValueInternal(
|
||||
}
|
||||
|
||||
// GATT Server
|
||||
void
|
||||
BluetoothServiceBluedroid::GattServerRegisterInternal(
|
||||
const BluetoothUuid& aAppUuid, BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
ENSURE_BLUETOOTH_IS_ENABLED_VOID(aRunnable);
|
||||
|
||||
BluetoothGattManager* gatt = BluetoothGattManager::Get();
|
||||
ENSURE_GATT_MGR_IS_READY_VOID(gatt, aRunnable);
|
||||
|
||||
gatt->RegisterServer(aAppUuid, aRunnable);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceBluedroid::GattServerConnectPeripheralInternal(
|
||||
const BluetoothUuid& aAppUuid, const BluetoothAddress& aAddress,
|
||||
|
@ -284,6 +284,15 @@ public:
|
||||
virtual void StopLeScanInternal(const BluetoothUuid& aScanUuid,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
virtual void StartAdvertisingInternal(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
const BluetoothGattAdvertisingData& aAdvData,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void StopAdvertisingInternal(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
ConnectGattClientInternal(const BluetoothUuid& aAppUuid,
|
||||
const BluetoothAddress& aDeviceAddress,
|
||||
@ -354,6 +363,11 @@ public:
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
GattServerRegisterInternal(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
GattServerConnectPeripheralInternal(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
|
@ -4301,6 +4301,21 @@ BluetoothDBusService::StopLeScanInternal(
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDBusService::StartAdvertisingInternal(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
const BluetoothGattAdvertisingData& aAdvData,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDBusService::StopAdvertisingInternal(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDBusService::ConnectGattClientInternal(
|
||||
const BluetoothUuid& aAppUuid, const BluetoothAddress& aDeviceAddress,
|
||||
@ -4513,6 +4528,12 @@ BluetoothDBusService::ReplyToMapMessageUpdate(long aMasId, bool aStatus,
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDBusService::GattServerRegisterInternal(
|
||||
const BluetoothUuid& aAppUuid, BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDBusService::GattServerConnectPeripheralInternal(
|
||||
const BluetoothUuid& aAppUuid, const BluetoothAddress& aAddress,
|
||||
|
@ -292,6 +292,15 @@ public:
|
||||
StopLeScanInternal(const BluetoothUuid& aAppUuid,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
StartAdvertisingInternal(const BluetoothUuid& aAppUuid,
|
||||
const BluetoothGattAdvertisingData& aAdvData,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
StopAdvertisingInternal(const BluetoothUuid& aAppUuid,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
ConnectGattClientInternal(const BluetoothUuid& aAppUuid,
|
||||
const BluetoothAddress& aDeviceAddress,
|
||||
@ -362,6 +371,11 @@ public:
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
GattServerRegisterInternal(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
GattServerConnectPeripheralInternal(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
|
@ -1307,6 +1307,62 @@ enum BluetoothGapDataType {
|
||||
GAP_COMPLETE_NAME = 0X09, // Complete Local Name
|
||||
};
|
||||
|
||||
struct BluetoothGattAdvertisingData {
|
||||
/**
|
||||
* Uuid value of Appearance characteristic of the GAP service which can be
|
||||
* mapped to an icon or string that describes the physical representation of
|
||||
* the device during the device discovery procedure.
|
||||
*/
|
||||
uint16_t mAppearance;
|
||||
|
||||
/**
|
||||
* Whether to broadcast with device name or not.
|
||||
*/
|
||||
bool mIncludeDevName;
|
||||
|
||||
/**
|
||||
* Whether to broadcast with TX power or not.
|
||||
*/
|
||||
bool mIncludeTxPower;
|
||||
|
||||
/**
|
||||
* Byte array of custom manufacturer specific data.
|
||||
*
|
||||
* The first 2 octets contain the Company Identifier Code followed by
|
||||
* additional manufacturer specific data. See Core Specification Supplement
|
||||
* (CSS) v6 1.4 for more details.
|
||||
*/
|
||||
nsTArray<uint8_t> mManufacturerData;
|
||||
|
||||
/**
|
||||
* Consists of a service UUID with the data associated with that service.
|
||||
* Please see Core Specification Supplement (CSS) v6 1.11 for more details.
|
||||
*/
|
||||
nsTArray<uint8_t> mServiceData;
|
||||
|
||||
/**
|
||||
* A list of Service or Service Class UUIDs.
|
||||
* Please see Core Specification Supplement (CSS) v6 1.1 for more details.
|
||||
*/
|
||||
nsTArray<BluetoothUuid> mServiceUuids;
|
||||
|
||||
BluetoothGattAdvertisingData()
|
||||
: mAppearance(0)
|
||||
, mIncludeDevName(false)
|
||||
, mIncludeTxPower(false)
|
||||
{ }
|
||||
|
||||
bool operator==(const BluetoothGattAdvertisingData& aOther) const
|
||||
{
|
||||
return mIncludeDevName == aOther.mIncludeDevName &&
|
||||
mIncludeTxPower == aOther.mIncludeTxPower &&
|
||||
mAppearance == aOther.mAppearance &&
|
||||
mManufacturerData == aOther.mManufacturerData &&
|
||||
mServiceData == aOther.mServiceData &&
|
||||
mServiceUuids == aOther.mServiceUuids;
|
||||
}
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_bluetooth_BluetoothCommon_h
|
||||
|
@ -1028,12 +1028,9 @@ public:
|
||||
int aMinInterval,
|
||||
int aMaxInterval,
|
||||
int aApperance,
|
||||
uint16_t aManufacturerLen,
|
||||
char* aManufacturerData,
|
||||
uint16_t aServiceDataLen,
|
||||
char* aServiceData,
|
||||
uint16_t aServiceUUIDLen,
|
||||
char* aServiceUUID,
|
||||
const nsTArray<uint8_t>& aManufacturerData,
|
||||
const nsTArray<uint8_t>& aServiceData,
|
||||
const nsTArray<BluetoothUuid>& aServiceUuids,
|
||||
BluetoothGattResultHandler* aRes) = 0;
|
||||
|
||||
virtual void TestCommand(int aCommand,
|
||||
|
@ -239,6 +239,18 @@ public:
|
||||
StartLeScanInternal(const nsTArray<BluetoothUuid>& aServiceUuids,
|
||||
BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
/**
|
||||
* Start/Stop advertising.
|
||||
*/
|
||||
virtual void
|
||||
StartAdvertisingInternal(const BluetoothUuid& aAppUuid,
|
||||
const BluetoothGattAdvertisingData& aAdvData,
|
||||
BluetoothReplyRunnable* aRunnable) { }
|
||||
|
||||
virtual void
|
||||
StopAdvertisingInternal(const BluetoothUuid& aAppUuid,
|
||||
BluetoothReplyRunnable* aRunnable) { }
|
||||
|
||||
/**
|
||||
* Set a property for the specified object
|
||||
*
|
||||
@ -586,6 +598,11 @@ public:
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
virtual void
|
||||
GattServerRegisterInternal(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
virtual void
|
||||
GattServerConnectPeripheralInternal(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "BluetoothService.h"
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/dom/BluetoothGattCharacteristicBinding.h"
|
||||
#include "mozilla/dom/BluetoothGattServerBinding.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "nsContentUtils.h"
|
||||
@ -413,7 +414,55 @@ GattPropertiesToBits(const GattCharacteristicProperties& aProperties,
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
AdvertisingDataToGattAdvertisingData(
|
||||
const BluetoothAdvertisingData& aAdvData,
|
||||
BluetoothGattAdvertisingData& aGattAdvData)
|
||||
{
|
||||
aGattAdvData.mAppearance = aAdvData.mAppearance;
|
||||
aGattAdvData.mIncludeDevName = aAdvData.mIncludeDevName;
|
||||
aGattAdvData.mIncludeTxPower = aAdvData.mIncludeTxPower;
|
||||
|
||||
for (size_t i = 0; i < aAdvData.mServiceUuids.Length(); i++) {
|
||||
BluetoothUuid uuid;
|
||||
if (NS_WARN_IF(NS_FAILED(StringToUuid(aAdvData.mServiceUuids[i], uuid)))) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
aGattAdvData.mServiceUuids.AppendElement(uuid);
|
||||
}
|
||||
|
||||
if (!aAdvData.mManufacturerData.IsNull()) {
|
||||
// First two bytes are manufacturer ID in little-endian.
|
||||
LittleEndian::writeUint16(aGattAdvData.mManufacturerData.Elements(),
|
||||
aAdvData.mManufacturerId);
|
||||
|
||||
// Concatenate custom manufacturer data.
|
||||
const ArrayBuffer& manufacturerData = aAdvData.mManufacturerData.Value();
|
||||
manufacturerData.ComputeLengthAndData();
|
||||
aGattAdvData.mManufacturerData.AppendElements(manufacturerData.Data(),
|
||||
manufacturerData.Length());
|
||||
}
|
||||
|
||||
if (!aAdvData.mServiceData.IsNull()) {
|
||||
BluetoothUuid uuid;
|
||||
if (NS_WARN_IF(NS_FAILED(StringToUuid(aAdvData.mServiceUuid, uuid)))) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
// First 16 bytes are service UUID in little-endian.
|
||||
for (size_t i = 0; i < sizeof(uuid.mUuid); i++) {
|
||||
aGattAdvData.mServiceData[i] = uuid.mUuid[sizeof(uuid.mUuid) - i - 1];
|
||||
}
|
||||
|
||||
// Concatenate custom service data.
|
||||
const ArrayBuffer& serviceData = aAdvData.mServiceData.Value();
|
||||
serviceData.ComputeLengthAndData();
|
||||
aGattAdvData.mServiceData.AppendElements(serviceData.Data(),
|
||||
serviceData.Length());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
GeneratePathFromGattId(const BluetoothGattId& aId,
|
||||
|
@ -14,6 +14,7 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
class GattPermissions;
|
||||
class GattCharacteristicProperties;
|
||||
class BluetoothAdvertisingData;
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,6 +176,19 @@ void
|
||||
GeneratePathFromGattId(const BluetoothGattId& aId,
|
||||
nsAString& aPath);
|
||||
|
||||
/**
|
||||
* Convert BluetoothAdvertisingData object used by applications to
|
||||
* BluetoothGattAdvertisingData object used by gecko backend.
|
||||
*
|
||||
* @param aAdvData [in] BluetoothAdvertisingData object.
|
||||
* @param aGattAdData [out] Target BluetoothGattAdvertisingData.
|
||||
* @return NS_OK on success, NS_ERROR_ILLEGAL_VALUE otherwise.
|
||||
*/
|
||||
nsresult
|
||||
AdvertisingDataToGattAdvertisingData(
|
||||
const BluetoothAdvertisingData& aAdvData,
|
||||
BluetoothGattAdvertisingData& aGattAdvData);
|
||||
|
||||
//
|
||||
// Register/Unregister bluetooth signal handlers
|
||||
//
|
||||
|
@ -374,6 +374,195 @@ BluetoothGattServer::Disconnect(const nsAString& aAddress, ErrorResult& aRv)
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
class BluetoothGattServer::StartAdvertisingTask final
|
||||
: public BluetoothVoidReplyRunnable
|
||||
{
|
||||
public:
|
||||
StartAdvertisingTask(BluetoothGattServer* aServer, Promise* aPromise)
|
||||
: BluetoothVoidReplyRunnable(nullptr, aPromise)
|
||||
, mServer(aServer)
|
||||
{
|
||||
MOZ_ASSERT(aServer);
|
||||
MOZ_ASSERT(aPromise);
|
||||
}
|
||||
|
||||
virtual void
|
||||
ReleaseMembers() override
|
||||
{
|
||||
BluetoothReplyRunnable::ReleaseMembers();
|
||||
mServer = nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void OnErrorFired() override
|
||||
{
|
||||
mServer->mAdvertisingAppUuid.Clear();
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<BluetoothGattServer> mServer;
|
||||
};
|
||||
|
||||
class BluetoothGattServer::RegisterServerAndStartAdvertisingTask final
|
||||
: public BluetoothVoidReplyRunnable
|
||||
{
|
||||
public:
|
||||
RegisterServerAndStartAdvertisingTask(
|
||||
BluetoothGattServer* aServer,
|
||||
const BluetoothGattAdvertisingData& aAdvData,
|
||||
Promise* aPromise)
|
||||
: BluetoothVoidReplyRunnable(nullptr, nullptr)
|
||||
/**
|
||||
* aPromise is not managed by BluetoothVoidReplyRunnable. It would be
|
||||
* passed to |StartAdvertisingTask| after this one executes successfully.
|
||||
*/
|
||||
, mServer(aServer)
|
||||
, mAdvData(aAdvData)
|
||||
, mPromise(aPromise)
|
||||
{
|
||||
MOZ_ASSERT(mServer);
|
||||
MOZ_ASSERT(mPromise);
|
||||
}
|
||||
|
||||
void ReleaseMembers() override
|
||||
{
|
||||
BluetoothReplyRunnable::ReleaseMembers();
|
||||
mServer = nullptr;
|
||||
mPromise = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void OnSuccessFired() override
|
||||
{
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
if (NS_WARN_IF(!bs)) {
|
||||
mPromise->MaybeReject(NS_ERROR_NOT_AVAILABLE);
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(mServer->mAdvertisingAppUuid.IsCleared())) {
|
||||
mPromise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
bs->StartAdvertisingInternal(
|
||||
mServer->mAdvertisingAppUuid, mAdvData,
|
||||
new StartAdvertisingTask(mServer, mPromise));
|
||||
}
|
||||
|
||||
virtual void OnErrorFired() override
|
||||
{
|
||||
mServer->mAdvertisingAppUuid.Clear();
|
||||
mPromise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
|
||||
}
|
||||
|
||||
RefPtr<BluetoothGattServer> mServer;
|
||||
BluetoothGattAdvertisingData mAdvData;
|
||||
RefPtr<Promise> mPromise;
|
||||
};
|
||||
|
||||
already_AddRefed<Promise>
|
||||
BluetoothGattServer::StartAdvertising(const BluetoothAdvertisingData& aAdvData,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
|
||||
if (!global) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
|
||||
|
||||
BT_ENSURE_TRUE_REJECT(mValid, promise, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
BT_ENSURE_TRUE_REJECT(mAdvertisingAppUuid.IsCleared(),
|
||||
promise,
|
||||
NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
|
||||
nsresult rv = GenerateUuid(mAdvertisingAppUuid);
|
||||
BT_ENSURE_TRUE_REJECT(NS_SUCCEEDED(rv) && !mAdvertisingAppUuid.IsCleared(),
|
||||
promise,
|
||||
NS_ERROR_DOM_OPERATION_ERR);
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
BT_ENSURE_TRUE_REJECT(bs, promise, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
BluetoothGattAdvertisingData data;
|
||||
rv = AdvertisingDataToGattAdvertisingData(aAdvData, data);
|
||||
BT_ENSURE_TRUE_REJECT(NS_SUCCEEDED(rv), promise, rv);
|
||||
|
||||
BluetoothUuid appUuid;
|
||||
rv = StringToUuid(mAppUuid, appUuid);
|
||||
BT_ENSURE_TRUE_REJECT(NS_SUCCEEDED(rv), promise, rv);
|
||||
|
||||
bs->GattServerRegisterInternal(
|
||||
appUuid,
|
||||
new RegisterServerAndStartAdvertisingTask(this, data, promise));
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
class BluetoothGattServer::StopAdvertisingTask final
|
||||
: public BluetoothVoidReplyRunnable
|
||||
{
|
||||
public:
|
||||
StopAdvertisingTask(BluetoothGattServer* aServer, Promise* aPromise)
|
||||
: BluetoothVoidReplyRunnable(nullptr, aPromise)
|
||||
, mServer(aServer)
|
||||
{
|
||||
MOZ_ASSERT(aPromise);
|
||||
MOZ_ASSERT(aServer);
|
||||
}
|
||||
|
||||
virtual void
|
||||
ReleaseMembers() override
|
||||
{
|
||||
BluetoothReplyRunnable::ReleaseMembers();
|
||||
mServer = nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void OnSuccessFired() override
|
||||
{
|
||||
mServer->mAdvertisingAppUuid.Clear();
|
||||
}
|
||||
|
||||
virtual void OnErrorFired() override
|
||||
{
|
||||
mServer->mAdvertisingAppUuid.Clear();
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<BluetoothGattServer> mServer;
|
||||
};
|
||||
|
||||
already_AddRefed<Promise>
|
||||
BluetoothGattServer::StopAdvertising(ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
|
||||
if (!global) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
|
||||
|
||||
BT_ENSURE_TRUE_REJECT(mValid, promise, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
if (mAdvertisingAppUuid.IsCleared()) {
|
||||
promise->MaybeResolve(JS::UndefinedHandleValue);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
BT_ENSURE_TRUE_REJECT(bs, promise, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
bs->StopAdvertisingInternal(mAdvertisingAppUuid,
|
||||
new StopAdvertisingTask(this, promise));
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
class BluetoothGattServer::AddIncludedServiceTask final
|
||||
: public BluetoothReplyTaskQueue::SubTask
|
||||
{
|
||||
|
@ -19,6 +19,7 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Promise;
|
||||
struct BluetoothAdvertisingData;
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,10 +58,16 @@ public:
|
||||
const nsAString& aAddress, ErrorResult& aRv);
|
||||
already_AddRefed<Promise> Disconnect(
|
||||
const nsAString& aAddress, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> StartAdvertising(
|
||||
const BluetoothAdvertisingData& aAdvData, ErrorResult& aRv);
|
||||
already_AddRefed<Promise> StopAdvertising(ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> AddService(BluetoothGattService& aService,
|
||||
ErrorResult& aRv);
|
||||
already_AddRefed<Promise> RemoveService(BluetoothGattService& aService,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> NotifyCharacteristicChanged(
|
||||
const nsAString& aAddress,
|
||||
BluetoothGattCharacteristic& aCharacteristic,
|
||||
@ -97,6 +104,9 @@ public:
|
||||
private:
|
||||
~BluetoothGattServer();
|
||||
|
||||
class StartAdvertisingTask;
|
||||
class RegisterServerAndStartAdvertisingTask;
|
||||
class StopAdvertisingTask;
|
||||
class AddIncludedServiceTask;
|
||||
class AddCharacteristicTask;
|
||||
class AddDescriptorTask;
|
||||
@ -106,6 +116,9 @@ private:
|
||||
class AddServiceTask;
|
||||
class RemoveServiceTask;
|
||||
|
||||
friend class StartAdvertisingTask;
|
||||
friend class RegisterServerAndStartAdvertisingTask;
|
||||
friend class StopAdvertisingTask;
|
||||
friend class AddIncludedServiceTask;
|
||||
friend class AddCharacteristicTask;
|
||||
friend class AddDescriptorTask;
|
||||
@ -171,6 +184,11 @@ private:
|
||||
* Map request information from the request ID.
|
||||
*/
|
||||
nsClassHashtable<nsUint32HashKey, RequestData> mRequestMap;
|
||||
|
||||
/**
|
||||
* AppUuid of the GATT client interface which is used to advertise.
|
||||
*/
|
||||
BluetoothUuid mAdvertisingAppUuid;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
@ -337,6 +337,36 @@ struct ParamTraits<mozilla::dom::bluetooth::ControlPlayStatus>
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::dom::bluetooth::BluetoothGattAdvertisingData>
|
||||
{
|
||||
typedef mozilla::dom::bluetooth::BluetoothGattAdvertisingData paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mAppearance);
|
||||
WriteParam(aMsg, aParam.mIncludeDevName);
|
||||
WriteParam(aMsg, aParam.mIncludeTxPower);
|
||||
WriteParam(aMsg, aParam.mManufacturerData);
|
||||
WriteParam(aMsg, aParam.mServiceData);
|
||||
WriteParam(aMsg, aParam.mServiceUuids);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
if (!ReadParam(aMsg, aIter, &(aResult->mAppearance)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mIncludeDevName)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mIncludeTxPower)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mManufacturerData)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mServiceData)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mServiceUuids))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif // mozilla_dom_bluetooth_ipc_BluetoothMessageUtils_h
|
||||
|
@ -206,6 +206,10 @@ BluetoothParent::RecvPBluetoothRequestConstructor(
|
||||
return actor->DoRequest(aRequest.get_StartLeScanRequest());
|
||||
case Request::TStopLeScanRequest:
|
||||
return actor->DoRequest(aRequest.get_StopLeScanRequest());
|
||||
case Request::TStartAdvertisingRequest:
|
||||
return actor->DoRequest(aRequest.get_StartAdvertisingRequest());
|
||||
case Request::TStopAdvertisingRequest:
|
||||
return actor->DoRequest(aRequest.get_StopAdvertisingRequest());
|
||||
case Request::TPairRequest:
|
||||
return actor->DoRequest(aRequest.get_PairRequest());
|
||||
case Request::TUnpairRequest:
|
||||
@ -308,6 +312,9 @@ BluetoothParent::RecvPBluetoothRequestConstructor(
|
||||
case Request::TGattClientWriteDescriptorValueRequest:
|
||||
return actor->DoRequest(
|
||||
aRequest.get_GattClientWriteDescriptorValueRequest());
|
||||
case Request::TGattServerRegisterRequest:
|
||||
return actor->DoRequest(
|
||||
aRequest.get_GattServerRegisterRequest());
|
||||
case Request::TGattServerConnectPeripheralRequest:
|
||||
return actor->DoRequest(
|
||||
aRequest.get_GattServerConnectPeripheralRequest());
|
||||
@ -496,6 +503,30 @@ BluetoothRequestParent::DoRequest(const StopLeScanRequest& aRequest)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothRequestParent::DoRequest(const StartAdvertisingRequest& aRequest)
|
||||
{
|
||||
MOZ_ASSERT(mService);
|
||||
MOZ_ASSERT(mRequestType == Request::TStartAdvertisingRequest);
|
||||
|
||||
mService->StartAdvertisingInternal(aRequest.appUuid(),
|
||||
aRequest.data(),
|
||||
mReplyRunnable.get());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothRequestParent::DoRequest(const StopAdvertisingRequest& aRequest)
|
||||
{
|
||||
MOZ_ASSERT(mService);
|
||||
MOZ_ASSERT(mRequestType == Request::TStopAdvertisingRequest);
|
||||
|
||||
mService->StopAdvertisingInternal(aRequest.appUuid(), mReplyRunnable.get());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothRequestParent::DoRequest(const PairRequest& aRequest)
|
||||
{
|
||||
@ -1119,6 +1150,18 @@ BluetoothRequestParent::DoRequest(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothRequestParent::DoRequest(const GattServerRegisterRequest& aRequest)
|
||||
{
|
||||
MOZ_ASSERT(mService);
|
||||
MOZ_ASSERT(mRequestType == Request::TGattServerRegisterRequest);
|
||||
|
||||
mService->GattServerRegisterInternal(aRequest.appUuid(),
|
||||
mReplyRunnable.get());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothRequestParent::DoRequest(
|
||||
const GattServerConnectPeripheralRequest& aRequest)
|
||||
|
@ -152,6 +152,12 @@ protected:
|
||||
bool
|
||||
DoRequest(const StopLeScanRequest& aRequest);
|
||||
|
||||
bool
|
||||
DoRequest(const StartAdvertisingRequest& aRequest);
|
||||
|
||||
bool
|
||||
DoRequest(const StopAdvertisingRequest& aRequest);
|
||||
|
||||
bool
|
||||
DoRequest(const PairRequest& aRequest);
|
||||
|
||||
@ -295,6 +301,9 @@ protected:
|
||||
bool
|
||||
DoRequest(const GattClientWriteDescriptorValueRequest& aRequest);
|
||||
|
||||
bool
|
||||
DoRequest(const GattServerRegisterRequest& aRequest);
|
||||
|
||||
bool
|
||||
DoRequest(const GattServerConnectPeripheralRequest& aRequest);
|
||||
|
||||
|
@ -177,6 +177,23 @@ BluetoothServiceChildProcess::StartLeScanInternal(
|
||||
SendRequest(aRunnable, StartLeScanRequest(aServiceUuids));
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceChildProcess::StartAdvertisingInternal(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
const BluetoothGattAdvertisingData& aAdvData,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
SendRequest(aRunnable, StartAdvertisingRequest(aAppUuid, aAdvData));
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceChildProcess::StopAdvertisingInternal(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
SendRequest(aRunnable, StopAdvertisingRequest(aAppUuid));
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothServiceChildProcess::SetProperty(BluetoothObjectType aType,
|
||||
const BluetoothNamedValue& aValue,
|
||||
@ -668,6 +685,14 @@ BluetoothServiceChildProcess::GattClientWriteDescriptorValueInternal(
|
||||
aValue));
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceChildProcess::GattServerRegisterInternal(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
SendRequest(aRunnable,GattServerRegisterRequest(aAppUuid));
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceChildProcess::GattServerConnectPeripheralInternal(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
|
@ -67,6 +67,15 @@ public:
|
||||
StartLeScanInternal(const nsTArray<BluetoothUuid>& aServiceUuids,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
StartAdvertisingInternal(const BluetoothUuid& aAppUuid,
|
||||
const BluetoothGattAdvertisingData& aAdvData,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
StopAdvertisingInternal(const BluetoothUuid& aAppUuid,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual nsresult
|
||||
SetProperty(BluetoothObjectType aType,
|
||||
const BluetoothNamedValue& aValue,
|
||||
@ -353,6 +362,11 @@ public:
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
GattServerRegisterInternal(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
GattServerConnectPeripheralInternal(
|
||||
const BluetoothUuid& aAppUuid,
|
||||
|
@ -14,6 +14,8 @@ include "mozilla/dom/bluetooth/ipc/BluetoothMessageUtils.h";
|
||||
|
||||
using mozilla::dom::bluetooth::BluetoothAddress
|
||||
from "mozilla/dom/bluetooth/BluetoothCommon.h";
|
||||
using mozilla::dom::bluetooth::BluetoothGattAdvertisingData
|
||||
from "mozilla/dom/bluetooth/BluetoothCommon.h";
|
||||
using mozilla::dom::bluetooth::BluetoothObjectType
|
||||
from "mozilla/dom/bluetooth/BluetoothCommon.h";
|
||||
using mozilla::dom::bluetooth::BluetoothPinCode
|
||||
@ -70,6 +72,17 @@ struct StopLeScanRequest
|
||||
BluetoothUuid scanUuid;
|
||||
};
|
||||
|
||||
struct StartAdvertisingRequest
|
||||
{
|
||||
BluetoothUuid appUuid;
|
||||
BluetoothGattAdvertisingData data;
|
||||
};
|
||||
|
||||
struct StopAdvertisingRequest
|
||||
{
|
||||
BluetoothUuid appUuid;
|
||||
};
|
||||
|
||||
struct PairRequest
|
||||
{
|
||||
BluetoothAddress address;
|
||||
@ -348,6 +361,11 @@ struct GattClientWriteDescriptorValueRequest
|
||||
uint8_t[] value;
|
||||
};
|
||||
|
||||
struct GattServerRegisterRequest
|
||||
{
|
||||
BluetoothUuid appUuid;
|
||||
};
|
||||
|
||||
struct GattServerConnectPeripheralRequest
|
||||
{
|
||||
BluetoothUuid appUuid;
|
||||
@ -444,6 +462,8 @@ union Request
|
||||
StopDiscoveryRequest;
|
||||
StartLeScanRequest;
|
||||
StopLeScanRequest;
|
||||
StartAdvertisingRequest;
|
||||
StopAdvertisingRequest;
|
||||
PairRequest;
|
||||
UnpairRequest;
|
||||
PinReplyRequest;
|
||||
@ -491,6 +511,7 @@ union Request
|
||||
GattClientWriteCharacteristicValueRequest;
|
||||
GattClientReadDescriptorValueRequest;
|
||||
GattClientWriteDescriptorValueRequest;
|
||||
GattServerRegisterRequest;
|
||||
GattServerConnectPeripheralRequest;
|
||||
GattServerDisconnectPeripheralRequest;
|
||||
UnregisterGattServerRequest;
|
||||
|
@ -4,6 +4,68 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
dictionary BluetoothAdvertisingData
|
||||
{
|
||||
/**
|
||||
* Uuid value of Appearance characteristic of the GAP service which can be
|
||||
* mapped to an icon or string that describes the physical representation of
|
||||
* the device during the device discovery procedure.
|
||||
*/
|
||||
unsigned short appearance = 0;
|
||||
|
||||
/**
|
||||
* Whether to broadcast with device name or not.
|
||||
*/
|
||||
boolean includeDevName = false;
|
||||
|
||||
/**
|
||||
* Whether to broadcast with TX power or not.
|
||||
*/
|
||||
boolean includeTxPower = false;
|
||||
|
||||
/**
|
||||
* Company Identifier Code for manufacturer data.
|
||||
*
|
||||
* This ID will be combined with |manufacturerData| byte array specified
|
||||
* below as the broadcasting manufacturer data. Please see Core Specification
|
||||
* Supplement (CSS) v6 1.4 for more details.
|
||||
*/
|
||||
unsigned short manufacturerId = 0;
|
||||
|
||||
/**
|
||||
* Byte array of custom manufacturer specific data.
|
||||
*
|
||||
* These bytes will be appended to |manufacturerId| specified above as the
|
||||
* broadcasting manufacturer data. Please see Core Specification Supplement
|
||||
* (CSS) v6 1.4 for more details.
|
||||
*/
|
||||
ArrayBuffer? manufacturerData = null;
|
||||
|
||||
/**
|
||||
* 128-bit Service UUID for service data.
|
||||
*
|
||||
* This UUID will be combinded with |serviceData| specified below as the
|
||||
* broadcasting service data. Please see Core Specification Supplement (CSS)
|
||||
* v6 1.11 for more details.
|
||||
*/
|
||||
DOMString serviceUuid = "";
|
||||
|
||||
/**
|
||||
* Data associated with |serviceUuid|.
|
||||
*
|
||||
* These bytes will be appended to |serviceUuid| specified above as the
|
||||
* broadcasting manufacturer data. Please see Core Specification Supplement
|
||||
* (CSS) v6 1.11 for more details.
|
||||
*/
|
||||
ArrayBuffer? serviceData = null;
|
||||
|
||||
/**
|
||||
* A list of Service or Service Class UUIDs.
|
||||
* Please see Core Specification Supplement (CSS) v6 1.1 for more details.
|
||||
*/
|
||||
sequence<DOMString> serviceUuids = [];
|
||||
};
|
||||
|
||||
[CheckAnyPermissions="bluetooth"]
|
||||
interface BluetoothGattServer : EventTarget
|
||||
{
|
||||
@ -28,6 +90,20 @@ interface BluetoothGattServer : EventTarget
|
||||
[NewObject]
|
||||
Promise<void> disconnect(DOMString address);
|
||||
|
||||
/**
|
||||
* Start or stop advertising data to nearby devices.
|
||||
*
|
||||
* Application may customize the advertising data by passing advData to
|
||||
* |startAdvertising|. By performing |startAdvertising|, remote central
|
||||
* devices can then discover and initiate a connection with our local device.
|
||||
* A 'connectionstatechanged' event will be fired when a remote central
|
||||
* device connects to the local device.
|
||||
*/
|
||||
[NewObject]
|
||||
Promise<void> startAdvertising(optional BluetoothAdvertisingData advData);
|
||||
[NewObject]
|
||||
Promise<void> stopAdvertising();
|
||||
|
||||
/**
|
||||
* Add a BLE service to the local GATT server.
|
||||
*
|
||||
|
@ -325,6 +325,42 @@ PackPDU(const PackReversed<PackArray<U>>& aIn, DaemonSocketPDU& aPDU)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* |PackArray<PackReversed<U>>| is a helper for packing data of each element in
|
||||
* the reversed order. Pass an instance of this structure as the first argument
|
||||
* to |PackPDU| to pack data of each array element in the reversed order.
|
||||
*
|
||||
* Unlike |PackReversed<PackArray<U>>| which packed array elements in the
|
||||
* reversed order, here we use |PackReversed<U>| to pack data of each element
|
||||
* of |PackArray| in the reversed order.
|
||||
*/
|
||||
template<typename U>
|
||||
struct PackArray<PackReversed<U>>
|
||||
{
|
||||
PackArray(const U* aData, size_t aLength)
|
||||
: mData(aData)
|
||||
, mLength(aLength)
|
||||
{ }
|
||||
|
||||
const U* mData;
|
||||
size_t mLength;
|
||||
};
|
||||
|
||||
/* This implementation of |PackPDU| packs data of each element in |PackArray|
|
||||
* in the reversed order. (ex. reversed GATT UUID, see bug 1171866)
|
||||
*/
|
||||
template<typename U>
|
||||
inline nsresult
|
||||
PackPDU(const PackArray<PackReversed<U>>& aIn, DaemonSocketPDU& aPDU)
|
||||
{
|
||||
for (size_t i = 0; i < aIn.mLength; ++i) {
|
||||
nsresult rv = PackPDU(PackReversed<U>(aIn.mData[i]), aPDU);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline nsresult
|
||||
PackPDU(const T1& aIn1, const T2& aIn2, DaemonSocketPDU& aPDU)
|
||||
|
Loading…
Reference in New Issue
Block a user