mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 21:05:36 +00:00
Bug 1181480 - Add and implement GATT server connection related Web APIs. r=btian, r=mrbkap
This commit is contained in:
parent
5e46105d5c
commit
a81cf1b3e6
@ -1847,7 +1847,7 @@ public:
|
||||
return rv;
|
||||
}
|
||||
/* Read connected */
|
||||
rv = UnpackPDU(pdu, aArg3);
|
||||
rv = UnpackPDU(pdu, UnpackConversion<int32_t, bool>(aArg3));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -14,14 +14,15 @@
|
||||
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#define ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(runnable) \
|
||||
#define ENSURE_GATT_INTF_IS_READY_VOID(runnable) \
|
||||
do { \
|
||||
if (!sBluetoothGattInterface) { \
|
||||
DispatchReplyError(runnable, \
|
||||
NS_LITERAL_STRING("BluetoothGattClientInterface is not ready")); \
|
||||
NS_LITERAL_STRING("BluetoothGattInterface is not ready")); \
|
||||
return; \
|
||||
} \
|
||||
} while(0)
|
||||
@ -29,6 +30,8 @@
|
||||
using namespace mozilla;
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothGattServer;
|
||||
|
||||
namespace {
|
||||
StaticRefPtr<BluetoothGattManager> sBluetoothGattManager;
|
||||
static BluetoothGattInterface* sBluetoothGattInterface;
|
||||
@ -37,6 +40,7 @@ namespace {
|
||||
bool BluetoothGattManager::mInShutdown = false;
|
||||
|
||||
static StaticAutoPtr<nsTArray<nsRefPtr<BluetoothGattClient> > > sClients;
|
||||
static StaticAutoPtr<nsTArray<nsRefPtr<BluetoothGattServer> > > sServers;
|
||||
|
||||
struct BluetoothGattClientReadCharState
|
||||
{
|
||||
@ -202,6 +206,32 @@ private:
|
||||
|
||||
NS_IMPL_ISUPPORTS0(BluetoothGattClient)
|
||||
|
||||
class BluetoothGattServer final : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
BluetoothGattServer(const nsAString& aAppUuid)
|
||||
: mAppUuid(aAppUuid)
|
||||
, mServerIf(0)
|
||||
{ }
|
||||
|
||||
nsString mAppUuid;
|
||||
int mServerIf;
|
||||
|
||||
nsRefPtr<BluetoothReplyRunnable> mConnectPeripheralRunnable;
|
||||
nsRefPtr<BluetoothReplyRunnable> mDisconnectPeripheralRunnable;
|
||||
nsRefPtr<BluetoothReplyRunnable> mUnregisterServerRunnable;
|
||||
|
||||
// Map connection id from device address
|
||||
nsDataHashtable<nsStringHashKey, int> mConnectionMap;
|
||||
private:
|
||||
~BluetoothGattServer()
|
||||
{ }
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS0(BluetoothGattServer)
|
||||
|
||||
class UuidComparator
|
||||
{
|
||||
public:
|
||||
@ -210,9 +240,15 @@ public:
|
||||
{
|
||||
return aClient->mAppUuid.Equals(aAppUuid);
|
||||
}
|
||||
|
||||
bool Equals(const nsRefPtr<BluetoothGattServer>& aServer,
|
||||
const nsAString& aAppUuid) const
|
||||
{
|
||||
return aServer->mAppUuid.Equals(aAppUuid);
|
||||
}
|
||||
};
|
||||
|
||||
class ClientIfComparator
|
||||
class InterfaceIdComparator
|
||||
{
|
||||
public:
|
||||
bool Equals(const nsRefPtr<BluetoothGattClient>& aClient,
|
||||
@ -220,6 +256,12 @@ public:
|
||||
{
|
||||
return aClient->mClientIf == aClientIf;
|
||||
}
|
||||
|
||||
bool Equals(const nsRefPtr<BluetoothGattServer>& aServer,
|
||||
int aServerIf) const
|
||||
{
|
||||
return aServer->mServerIf == aServerIf;
|
||||
}
|
||||
};
|
||||
|
||||
class ConnIdComparator
|
||||
@ -305,6 +347,10 @@ BluetoothGattManager::InitGattInterface(BluetoothProfileResultHandler* aRes)
|
||||
sClients = new nsTArray<nsRefPtr<BluetoothGattClient> >;
|
||||
}
|
||||
|
||||
if (!sServers) {
|
||||
sServers = new nsTArray<nsRefPtr<BluetoothGattServer> >;
|
||||
}
|
||||
|
||||
BluetoothGattManager* gattManager = BluetoothGattManager::Get();
|
||||
sBluetoothGattInterface->Init(gattManager,
|
||||
new InitGattResultHandler(aRes));
|
||||
@ -331,6 +377,7 @@ public:
|
||||
{
|
||||
sBluetoothGattInterface = nullptr;
|
||||
sClients = nullptr;
|
||||
sServers = nullptr;
|
||||
|
||||
if (mRes) {
|
||||
mRes->Deinit();
|
||||
@ -434,10 +481,8 @@ public:
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
// Notify BluetoothGatt to clear the clientIf
|
||||
bs->DistributeSignal(
|
||||
NS_LITERAL_STRING("ClientUnregistered"),
|
||||
mClient->mAppUuid,
|
||||
BluetoothValue(true));
|
||||
bs->DistributeSignal(NS_LITERAL_STRING("ClientUnregistered"),
|
||||
mClient->mAppUuid);
|
||||
|
||||
// Resolve the unregister request
|
||||
DispatchReplySuccess(mClient->mUnregisterClientRunnable);
|
||||
@ -469,10 +514,10 @@ BluetoothGattManager::UnregisterClient(int aClientIf,
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
|
||||
ClientIfComparator());
|
||||
InterfaceIdComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
@ -569,7 +614,7 @@ BluetoothGattManager::StartLeScan(const nsTArray<nsString>& aServiceUuids,
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
nsString appUuidStr;
|
||||
GenerateUuid(appUuidStr);
|
||||
@ -603,7 +648,7 @@ BluetoothGattManager::StopLeScan(const nsAString& aScanUuid,
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aScanUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
@ -662,7 +707,7 @@ BluetoothGattManager::Connect(const nsAString& aAppUuid,
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (index == sClients->NoIndex) {
|
||||
@ -732,7 +777,7 @@ BluetoothGattManager::Disconnect(const nsAString& aAppUuid,
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
@ -779,7 +824,7 @@ BluetoothGattManager::Discover(const nsAString& aAppUuid,
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
@ -850,10 +895,10 @@ BluetoothGattManager::ReadRemoteRssi(int aClientIf,
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
|
||||
ClientIfComparator());
|
||||
InterfaceIdComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
@ -918,7 +963,7 @@ BluetoothGattManager::RegisterNotifications(
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
@ -994,7 +1039,7 @@ BluetoothGattManager::DeregisterNotifications(
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
@ -1057,7 +1102,7 @@ BluetoothGattManager::ReadCharacteristicValue(
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
@ -1137,7 +1182,7 @@ BluetoothGattManager::WriteCharacteristicValue(
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
@ -1219,7 +1264,7 @@ BluetoothGattManager::ReadDescriptorValue(
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
@ -1300,7 +1345,7 @@ BluetoothGattManager::WriteDescriptorValue(
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
@ -1342,6 +1387,278 @@ BluetoothGattManager::WriteDescriptorValue(
|
||||
new WriteDescriptorValueResultHandler(client));
|
||||
}
|
||||
|
||||
class BluetoothGattManager::RegisterServerResultHandler final
|
||||
: public BluetoothGattResultHandler
|
||||
{
|
||||
public:
|
||||
RegisterServerResultHandler(BluetoothGattServer* aServer)
|
||||
: mServer(aServer)
|
||||
{
|
||||
MOZ_ASSERT(mServer);
|
||||
}
|
||||
|
||||
void OnError(BluetoothStatus aStatus) override
|
||||
{
|
||||
BT_WARNING("BluetoothGattServerInterface::RegisterServer failed: %d",
|
||||
(int)aStatus);
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
// Reject the connect request
|
||||
if (mServer->mConnectPeripheralRunnable) {
|
||||
DispatchReplyError(mServer->mConnectPeripheralRunnable,
|
||||
NS_LITERAL_STRING("Register GATT server failed"));
|
||||
mServer->mConnectPeripheralRunnable = nullptr;
|
||||
}
|
||||
|
||||
sServers->RemoveElement(mServer);
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothGattServer> mServer;
|
||||
};
|
||||
|
||||
class BluetoothGattManager::ConnectPeripheralResultHandler final
|
||||
: public BluetoothGattResultHandler
|
||||
{
|
||||
public:
|
||||
ConnectPeripheralResultHandler(BluetoothGattServer* aServer,
|
||||
const nsAString& aDeviceAddr)
|
||||
: mServer(aServer)
|
||||
, mDeviceAddr(aDeviceAddr)
|
||||
{
|
||||
MOZ_ASSERT(mServer);
|
||||
MOZ_ASSERT(!mDeviceAddr.IsEmpty());
|
||||
}
|
||||
|
||||
void OnError(BluetoothStatus aStatus) override
|
||||
{
|
||||
BT_WARNING("BluetoothGattServerInterface::ConnectPeripheral failed: %d",
|
||||
(int)aStatus);
|
||||
MOZ_ASSERT(mServer->mConnectPeripheralRunnable);
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
DispatchReplyError(mServer->mConnectPeripheralRunnable,
|
||||
NS_LITERAL_STRING("ConnectPeripheral failed"));
|
||||
mServer->mConnectPeripheralRunnable = nullptr;
|
||||
mServer->mConnectionMap.Remove(mDeviceAddr);
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothGattServer> mServer;
|
||||
nsString mDeviceAddr;
|
||||
};
|
||||
|
||||
void
|
||||
BluetoothGattManager::ConnectPeripheral(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
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));
|
||||
}
|
||||
nsRefPtr<BluetoothGattServer> server = (*sServers)[index];
|
||||
|
||||
/**
|
||||
* Early resolve or reject the request based on the current status before
|
||||
* sending a request to bluetooth stack.
|
||||
*
|
||||
* case 1) Connecting/Disconnecting: If connect/disconnect peripheral
|
||||
* runnable exists, reject the request since the local GATT server is
|
||||
* busy connecting or disconnecting to a device.
|
||||
* case 2) Connected: If there is an entry whose key is |aAddress| in the
|
||||
* connection map, resolve the request. Since disconnected devices
|
||||
* will not be in the map, all entries in the map are connected
|
||||
* devices.
|
||||
*/
|
||||
if (server->mConnectPeripheralRunnable ||
|
||||
server->mDisconnectPeripheralRunnable) {
|
||||
DispatchReplyError(aRunnable, STATUS_BUSY);
|
||||
return;
|
||||
}
|
||||
|
||||
int connId = 0;
|
||||
if (server->mConnectionMap.Get(aAddress, &connId)) {
|
||||
MOZ_ASSERT(connId > 0);
|
||||
DispatchReplySuccess(aRunnable);
|
||||
return;
|
||||
}
|
||||
|
||||
server->mConnectionMap.Put(aAddress, 0);
|
||||
server->mConnectPeripheralRunnable = aRunnable;
|
||||
|
||||
if (server->mServerIf > 0) {
|
||||
sBluetoothGattInterface->ConnectPeripheral(
|
||||
server->mServerIf,
|
||||
aAddress,
|
||||
true, // direct connect
|
||||
TRANSPORT_AUTO,
|
||||
new ConnectPeripheralResultHandler(server, aAddress));
|
||||
} else {
|
||||
BluetoothUuid uuid;
|
||||
StringToUuid(NS_ConvertUTF16toUTF8(aAppUuid).get(), uuid);
|
||||
|
||||
// connect will be proceeded after server registered
|
||||
sBluetoothGattInterface->RegisterServer(
|
||||
uuid, new RegisterServerResultHandler(server));
|
||||
}
|
||||
}
|
||||
|
||||
class BluetoothGattManager::DisconnectPeripheralResultHandler final
|
||||
: public BluetoothGattResultHandler
|
||||
{
|
||||
public:
|
||||
DisconnectPeripheralResultHandler(BluetoothGattServer* aServer)
|
||||
: mServer(aServer)
|
||||
{
|
||||
MOZ_ASSERT(mServer);
|
||||
}
|
||||
|
||||
void OnError(BluetoothStatus aStatus) override
|
||||
{
|
||||
BT_WARNING("BluetoothGattServerInterface::DisconnectPeripheral failed: %d",
|
||||
(int)aStatus);
|
||||
MOZ_ASSERT(mServer->mDisconnectPeripheralRunnable);
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
// Reject the disconnect request
|
||||
DispatchReplyError(mServer->mDisconnectPeripheralRunnable,
|
||||
NS_LITERAL_STRING("DisconnectPeripheral failed"));
|
||||
mServer->mDisconnectPeripheralRunnable = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothGattServer> mServer;
|
||||
};
|
||||
|
||||
void
|
||||
BluetoothGattManager::DisconnectPeripheral(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
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 (NS_WARN_IF(index == sServers->NoIndex)) {
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
nsRefPtr<BluetoothGattServer> server = (*sServers)[index];
|
||||
|
||||
if (NS_WARN_IF(server->mServerIf <= 0)) {
|
||||
DispatchReplyError(aRunnable,
|
||||
NS_LITERAL_STRING("Disconnect failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Reject the request if there is an ongoing connect/disconnect request.
|
||||
if (server->mConnectPeripheralRunnable ||
|
||||
server->mDisconnectPeripheralRunnable) {
|
||||
DispatchReplyError(aRunnable, STATUS_BUSY);
|
||||
return;
|
||||
}
|
||||
|
||||
// Resolve the request if the device is not connected.
|
||||
int connId = 0;
|
||||
if (!server->mConnectionMap.Get(aAddress, &connId)) {
|
||||
DispatchReplySuccess(aRunnable);
|
||||
return;
|
||||
}
|
||||
|
||||
server->mDisconnectPeripheralRunnable = aRunnable;
|
||||
|
||||
sBluetoothGattInterface->DisconnectPeripheral(
|
||||
server->mServerIf,
|
||||
aAddress,
|
||||
connId,
|
||||
new DisconnectPeripheralResultHandler(server));
|
||||
}
|
||||
|
||||
class BluetoothGattManager::UnregisterServerResultHandler final
|
||||
: public BluetoothGattResultHandler
|
||||
{
|
||||
public:
|
||||
UnregisterServerResultHandler(BluetoothGattServer* aServer)
|
||||
: mServer(aServer)
|
||||
{
|
||||
MOZ_ASSERT(mServer);
|
||||
}
|
||||
|
||||
void UnregisterServer() override
|
||||
{
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
// Notify BluetoothGattServer to clear the serverIf
|
||||
bs->DistributeSignal(NS_LITERAL_STRING("ServerUnregistered"),
|
||||
mServer->mAppUuid);
|
||||
|
||||
// Resolve the unregister request
|
||||
if (mServer->mUnregisterServerRunnable) {
|
||||
DispatchReplySuccess(mServer->mUnregisterServerRunnable);
|
||||
mServer->mUnregisterServerRunnable = nullptr;
|
||||
}
|
||||
|
||||
sServers->RemoveElement(mServer);
|
||||
}
|
||||
|
||||
void OnError(BluetoothStatus aStatus) override
|
||||
{
|
||||
BT_WARNING("BluetoothGattServerInterface::UnregisterServer failed: %d",
|
||||
(int)aStatus);
|
||||
|
||||
// Reject the unregister request
|
||||
if (mServer->mUnregisterServerRunnable) {
|
||||
DispatchReplyError(mServer->mUnregisterServerRunnable,
|
||||
NS_LITERAL_STRING("Unregister GATT Server failed"));
|
||||
mServer->mUnregisterServerRunnable = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothGattServer> mServer;
|
||||
};
|
||||
|
||||
void
|
||||
BluetoothGattManager::UnregisterServer(int aServerIf,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sServers->IndexOf(aServerIf, 0 /* Start */,
|
||||
InterfaceIdComparator());
|
||||
if (NS_WARN_IF(index == sServers->NoIndex)) {
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothGattServer> server = (*sServers)[index];
|
||||
server->mUnregisterServerRunnable = aRunnable;
|
||||
|
||||
sBluetoothGattInterface->UnregisterServer(
|
||||
aServerIf,
|
||||
new UnregisterServerResultHandler(server));
|
||||
}
|
||||
|
||||
//
|
||||
// Notification Handlers
|
||||
//
|
||||
@ -1486,7 +1803,7 @@ BluetoothGattManager::ConnectNotification(int aConnId,
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
|
||||
ClientIfComparator());
|
||||
InterfaceIdComparator());
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
@ -1538,7 +1855,7 @@ BluetoothGattManager::DisconnectNotification(int aConnId,
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
|
||||
ClientIfComparator());
|
||||
InterfaceIdComparator());
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
@ -2064,7 +2381,7 @@ BluetoothGattManager::ReadRemoteRssiNotification(int aClientIf,
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
|
||||
ClientIfComparator());
|
||||
InterfaceIdComparator());
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
@ -2097,6 +2414,110 @@ BluetoothGattManager::ListenNotification(BluetoothGattStatus aStatus,
|
||||
int aServerIf)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothGattManager::RegisterServerNotification(BluetoothGattStatus aStatus,
|
||||
int aServerIf,
|
||||
const BluetoothUuid& aAppUuid)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsString uuid;
|
||||
UuidToString(aAppUuid, uuid);
|
||||
|
||||
size_t index = sServers->IndexOf(uuid, 0 /* Start */, UuidComparator());
|
||||
NS_ENSURE_TRUE_VOID(index != sServers->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattServer> server = (*sServers)[index];
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
if (aStatus != GATT_STATUS_SUCCESS) {
|
||||
BT_LOGD("RegisterServer failed: serverIf = %d, status = %d, appUuid = %s",
|
||||
aServerIf, aStatus, NS_ConvertUTF16toUTF8(uuid).get());
|
||||
|
||||
if (server->mConnectPeripheralRunnable) {
|
||||
// Reject the connect peripheral request
|
||||
DispatchReplyError(
|
||||
server->mConnectPeripheralRunnable,
|
||||
NS_LITERAL_STRING(
|
||||
"ConnectPeripheral failed due to registration failed"));
|
||||
server->mConnectPeripheralRunnable = nullptr;
|
||||
}
|
||||
|
||||
sServers->RemoveElement(server);
|
||||
}
|
||||
|
||||
server->mServerIf = aServerIf;
|
||||
|
||||
// Notify BluetoothGattServer to update the serverIf
|
||||
bs->DistributeSignal(
|
||||
NS_LITERAL_STRING("ServerRegistered"),
|
||||
uuid, BluetoothValue(uint32_t(aServerIf)));
|
||||
|
||||
if (server->mConnectPeripheralRunnable) {
|
||||
// Only one entry exists in the map during first connect peripheral request
|
||||
nsString deviceAddr(server->mConnectionMap.Iter().Key());
|
||||
|
||||
sBluetoothGattInterface->ConnectPeripheral(
|
||||
aServerIf, deviceAddr, true /* direct connect */, TRANSPORT_AUTO,
|
||||
new ConnectPeripheralResultHandler(server, deviceAddr));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothGattManager::ConnectionNotification(int aConnId,
|
||||
int aServerIf,
|
||||
bool aConnected,
|
||||
const nsAString& aBdAddr)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
size_t index = sServers->IndexOf(aServerIf, 0 /* Start */,
|
||||
InterfaceIdComparator());
|
||||
NS_ENSURE_TRUE_VOID(index != sServers->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattServer> server = (*sServers)[index];
|
||||
|
||||
// Update the connection map based on the connection status
|
||||
if (aConnected) {
|
||||
server->mConnectionMap.Put(aBdAddr, aConnId);
|
||||
} else {
|
||||
server->mConnectionMap.Remove(aBdAddr);
|
||||
}
|
||||
|
||||
// Notify BluetoothGattServer that connection status changed
|
||||
InfallibleTArray<BluetoothNamedValue> props;
|
||||
BT_APPEND_NAMED_VALUE(props, "Connected", aConnected);
|
||||
BT_APPEND_NAMED_VALUE(props, "Address", nsString(aBdAddr));
|
||||
bs->DistributeSignal(
|
||||
NS_LITERAL_STRING(GATT_CONNECTION_STATE_CHANGED_ID),
|
||||
server->mAppUuid,
|
||||
BluetoothValue(props));
|
||||
|
||||
// Resolve or reject connect/disconnect peripheral requests
|
||||
if (server->mConnectPeripheralRunnable) {
|
||||
if (aConnected) {
|
||||
DispatchReplySuccess(server->mConnectPeripheralRunnable);
|
||||
} else {
|
||||
DispatchReplyError(server->mConnectPeripheralRunnable,
|
||||
NS_LITERAL_STRING("ConnectPeripheral failed"));
|
||||
}
|
||||
server->mConnectPeripheralRunnable = nullptr;
|
||||
} else if (server->mDisconnectPeripheralRunnable) {
|
||||
if (!aConnected) {
|
||||
DispatchReplySuccess(server->mDisconnectPeripheralRunnable);
|
||||
} else {
|
||||
DispatchReplyError(server->mDisconnectPeripheralRunnable,
|
||||
NS_LITERAL_STRING("DisconnectPeripheral failed"));
|
||||
}
|
||||
server->mDisconnectPeripheralRunnable = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
BluetoothGattManager::BluetoothGattManager()
|
||||
{ }
|
||||
|
||||
@ -2132,6 +2553,7 @@ BluetoothGattManager::HandleShutdown()
|
||||
mInShutdown = true;
|
||||
sBluetoothGattManager = nullptr;
|
||||
sClients = nullptr;
|
||||
sServers = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -90,6 +90,19 @@ public:
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
void ConnectPeripheral(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
void DisconnectPeripheral(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
void UnregisterServer(int aServerIf,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
private:
|
||||
~BluetoothGattManager();
|
||||
|
||||
@ -112,6 +125,11 @@ private:
|
||||
class WriteDescriptorValueResultHandler;
|
||||
class ScanDeviceTypeResultHandler;
|
||||
|
||||
class RegisterServerResultHandler;
|
||||
class ConnectPeripheralResultHandler;
|
||||
class DisconnectPeripheralResultHandler;
|
||||
class UnregisterServerResultHandler;
|
||||
|
||||
BluetoothGattManager();
|
||||
|
||||
void HandleShutdown();
|
||||
@ -200,6 +218,15 @@ private:
|
||||
void ProceedDiscoverProcess(BluetoothGattClient* aClient,
|
||||
const BluetoothGattServiceId& aServiceId);
|
||||
|
||||
void RegisterServerNotification(BluetoothGattStatus aStatus,
|
||||
int aServerIf,
|
||||
const BluetoothUuid& aAppUuid) override;
|
||||
|
||||
void ConnectionNotification(int aConnId,
|
||||
int aServerIf,
|
||||
bool aConnected,
|
||||
const nsAString& aBdAddr) override;
|
||||
|
||||
static bool mInShutdown;
|
||||
};
|
||||
|
||||
|
@ -552,6 +552,51 @@ BluetoothServiceBluedroid::GattClientWriteDescriptorValueInternal(
|
||||
aDescriptorId, aValue, aRunnable);
|
||||
}
|
||||
|
||||
// GATT Server
|
||||
void
|
||||
BluetoothServiceBluedroid::GattServerConnectPeripheralInternal(
|
||||
const nsAString& aAppUuid, const nsAString& aAddress,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
ENSURE_BLUETOOTH_IS_READY_VOID(aRunnable);
|
||||
|
||||
BluetoothGattManager* gatt = BluetoothGattManager::Get();
|
||||
ENSURE_GATT_MGR_IS_READY_VOID(gatt, aRunnable);
|
||||
|
||||
gatt->ConnectPeripheral(aAppUuid, aAddress, aRunnable);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceBluedroid::GattServerDisconnectPeripheralInternal(
|
||||
const nsAString& aAppUuid, const nsAString& aAddress,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
ENSURE_BLUETOOTH_IS_READY_VOID(aRunnable);
|
||||
|
||||
BluetoothGattManager* gatt = BluetoothGattManager::Get();
|
||||
ENSURE_GATT_MGR_IS_READY_VOID(gatt, aRunnable);
|
||||
|
||||
gatt->DisconnectPeripheral(aAppUuid, aAddress, aRunnable);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceBluedroid::UnregisterGattServerInternal(
|
||||
int aServerIf, BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
ENSURE_BLUETOOTH_IS_READY_VOID(aRunnable);
|
||||
|
||||
BluetoothGattManager* gatt = BluetoothGattManager::Get();
|
||||
ENSURE_GATT_MGR_IS_READY_VOID(gatt, aRunnable);
|
||||
|
||||
gatt->UnregisterServer(aServerIf, aRunnable);
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothServiceBluedroid::GetAdaptersInternal(
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
|
@ -290,6 +290,22 @@ public:
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
GattServerConnectPeripheralInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
GattServerDisconnectPeripheralInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
UnregisterGattServerInternal(int aServerIf,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
//
|
||||
// Bluetooth notifications
|
||||
//
|
||||
|
@ -23,7 +23,6 @@ NS_IMPL_RELEASE_INHERITED(BluetoothDiscoveryHandle, DOMEventTargetHelper)
|
||||
|
||||
BluetoothDiscoveryHandle::BluetoothDiscoveryHandle(nsPIDOMWindow* aWindow)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
, mLeScanUuid(EmptyString())
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
}
|
||||
|
@ -51,7 +51,6 @@ NS_IMPL_RELEASE_INHERITED(BluetoothGatt, DOMEventTargetHelper)
|
||||
BluetoothGatt::BluetoothGatt(nsPIDOMWindow* aWindow,
|
||||
const nsAString& aDeviceAddr)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
, mAppUuid(EmptyString())
|
||||
, mClientIf(0)
|
||||
, mConnectionState(BluetoothConnectionState::Disconnected)
|
||||
, mDeviceAddr(aDeviceAddr)
|
||||
|
@ -6,32 +6,91 @@
|
||||
|
||||
#include "BluetoothGattServer.h"
|
||||
|
||||
#include "BluetoothReplyRunnable.h"
|
||||
#include "BluetoothService.h"
|
||||
#include "BluetoothUtils.h"
|
||||
#include "mozilla/dom/BluetoothStatusChangedEvent.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(BluetoothGattServer,
|
||||
mOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothGattServer)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(BluetoothGattServer)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(BluetoothGattServer)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BluetoothGattServer)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothGattServer,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
|
||||
|
||||
/**
|
||||
* Unregister the bluetooth signal handler after unlinked.
|
||||
*
|
||||
* This is needed to avoid ending up with exposing a deleted object to JS or
|
||||
* accessing deleted objects while receiving signals from parent process
|
||||
* after unlinked. Please see Bug 1138267 for detail informations.
|
||||
*/
|
||||
UnregisterBluetoothSignalHandler(tmp->mAppUuid, tmp);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothGattServer,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothGattServer)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(BluetoothGattServer, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(BluetoothGattServer, DOMEventTargetHelper)
|
||||
|
||||
BluetoothGattServer::BluetoothGattServer(nsPIDOMWindow* aOwner)
|
||||
: mOwner(aOwner)
|
||||
, mServerIf(0)
|
||||
, mValid(true)
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
BluetoothGattServer::~BluetoothGattServer()
|
||||
{
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothGattServer::Notify(const BluetoothSignal& aData)
|
||||
{
|
||||
BT_LOGD("[GattServer] %s", NS_ConvertUTF16toUTF8(aData.name()).get());
|
||||
NS_ENSURE_TRUE_VOID(mSignalRegistered);
|
||||
|
||||
BluetoothValue v = aData.value();
|
||||
if (aData.name().EqualsLiteral("ServerRegistered")) {
|
||||
MOZ_ASSERT(v.type() == BluetoothValue::Tuint32_t);
|
||||
mServerIf = v.get_uint32_t();
|
||||
} else if (aData.name().EqualsLiteral("ServerUnregistered")) {
|
||||
mServerIf = 0;
|
||||
} else if (aData.name().EqualsLiteral(GATT_CONNECTION_STATE_CHANGED_ID)) {
|
||||
MOZ_ASSERT(v.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
|
||||
const InfallibleTArray<BluetoothNamedValue>& arr =
|
||||
v.get_ArrayOfBluetoothNamedValue();
|
||||
|
||||
MOZ_ASSERT(arr.Length() == 2 &&
|
||||
arr[0].value().type() == BluetoothValue::Tbool &&
|
||||
arr[1].value().type() == BluetoothValue::TnsString);
|
||||
|
||||
BluetoothStatusChangedEventInit init;
|
||||
init.mStatus = arr[0].value().get_bool();
|
||||
init.mAddress = arr[1].value().get_nsString();
|
||||
|
||||
nsRefPtr<BluetoothStatusChangedEvent> event =
|
||||
BluetoothStatusChangedEvent::Constructor(
|
||||
this, NS_LITERAL_STRING(GATT_CONNECTION_STATE_CHANGED_ID), init);
|
||||
|
||||
DispatchTrustedEvent(event);
|
||||
} else {
|
||||
BT_WARNING("Not handling GATT signal: %s",
|
||||
NS_ConvertUTF16toUTF8(aData.name()).get());
|
||||
}
|
||||
}
|
||||
|
||||
JSObject*
|
||||
BluetoothGattServer::WrapObject(JSContext* aContext,
|
||||
JS::Handle<JSObject*> aGivenProto)
|
||||
@ -39,12 +98,76 @@ BluetoothGattServer::WrapObject(JSContext* aContext,
|
||||
return BluetoothGattServerBinding::Wrap(aContext, this, aGivenProto);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothGattServer::DisconnectFromOwner()
|
||||
{
|
||||
DOMEventTargetHelper::DisconnectFromOwner();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothGattServer::Invalidate()
|
||||
{
|
||||
mValid = false;
|
||||
|
||||
/* TODO: add tear down stuff here */
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
return;
|
||||
}
|
||||
if (mServerIf > 0) {
|
||||
bs->UnregisterGattServerInternal(mServerIf, nullptr);
|
||||
}
|
||||
|
||||
UnregisterBluetoothSignalHandler(mAppUuid, this);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
BluetoothGattServer::Connect(const nsAString& aAddress, ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
|
||||
if (!global) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
|
||||
|
||||
BT_ENSURE_TRUE_REJECT(mValid, promise, NS_ERROR_NOT_AVAILABLE);
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
BT_ENSURE_TRUE_REJECT(bs, promise, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
if (mAppUuid.IsEmpty()) {
|
||||
GenerateUuid(mAppUuid);
|
||||
BT_ENSURE_TRUE_REJECT(!mAppUuid.IsEmpty(),
|
||||
promise,
|
||||
NS_ERROR_DOM_OPERATION_ERR);
|
||||
RegisterBluetoothSignalHandler(mAppUuid, this);
|
||||
}
|
||||
|
||||
bs->GattServerConnectPeripheralInternal(
|
||||
mAppUuid, aAddress, new BluetoothVoidReplyRunnable(nullptr, promise));
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
BluetoothGattServer::Disconnect(const nsAString& aAddress, ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
|
||||
if (!global) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
|
||||
|
||||
BT_ENSURE_TRUE_REJECT(mValid, promise, NS_ERROR_NOT_AVAILABLE);
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
BT_ENSURE_TRUE_REJECT(bs, promise, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
bs->GattServerDisconnectPeripheralInternal(
|
||||
mAppUuid, aAddress, new BluetoothVoidReplyRunnable(nullptr, promise));
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
@ -7,20 +7,29 @@
|
||||
#ifndef mozilla_dom_bluetooth_BluetoothGattServer_h
|
||||
#define mozilla_dom_bluetooth_BluetoothGattServer_h
|
||||
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/dom/BluetoothGattServerBinding.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Promise;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothGattServer final : public nsISupports
|
||||
, public nsWrapperCache
|
||||
class BluetoothSignal;
|
||||
|
||||
class BluetoothGattServer final : public DOMEventTargetHelper
|
||||
, public BluetoothSignalObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BluetoothGattServer)
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BluetoothGattServer,
|
||||
DOMEventTargetHelper)
|
||||
|
||||
/****************************************************************************
|
||||
* Attribute Getters
|
||||
@ -29,14 +38,21 @@ public:
|
||||
/****************************************************************************
|
||||
* Event Handlers
|
||||
***************************************************************************/
|
||||
IMPL_EVENT_HANDLER(connectionstatechanged);
|
||||
|
||||
/****************************************************************************
|
||||
* Methods (Web API Implementation)
|
||||
***************************************************************************/
|
||||
already_AddRefed<Promise> Connect(
|
||||
const nsAString& aAddress, ErrorResult& aRv);
|
||||
already_AddRefed<Promise> Disconnect(
|
||||
const nsAString& aAddress, ErrorResult& aRv);
|
||||
|
||||
/****************************************************************************
|
||||
* Others
|
||||
***************************************************************************/
|
||||
void Notify(const BluetoothSignal& aData); // BluetoothSignalObserver
|
||||
|
||||
nsPIDOMWindow* GetParentObject() const
|
||||
{
|
||||
return mOwner;
|
||||
@ -45,6 +61,7 @@ public:
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
virtual void DisconnectFromOwner() override;
|
||||
BluetoothGattServer(nsPIDOMWindow* aOwner);
|
||||
|
||||
/* Invalidate the GATT server.
|
||||
@ -61,6 +78,17 @@ private:
|
||||
***************************************************************************/
|
||||
nsCOMPtr<nsPIDOMWindow> mOwner;
|
||||
|
||||
/**
|
||||
* Random generated UUID of this GATT client.
|
||||
*/
|
||||
nsString mAppUuid;
|
||||
|
||||
/**
|
||||
* Id of the GATT server interface given by bluetooth stack.
|
||||
* 0 if the interface is not registered yet, nonzero otherwise.
|
||||
*/
|
||||
int mServerIf;
|
||||
|
||||
bool mValid;
|
||||
};
|
||||
|
||||
|
@ -490,6 +490,25 @@ public:
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
virtual void
|
||||
GattServerConnectPeripheralInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
virtual void
|
||||
GattServerDisconnectPeripheralInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
/**
|
||||
* Unregister a GATT server. (platform specific implementation)
|
||||
*/
|
||||
virtual void
|
||||
UnregisterGattServerInternal(int aServerIf,
|
||||
BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
bool
|
||||
IsEnabled() const
|
||||
{
|
||||
|
@ -292,6 +292,14 @@ BluetoothParent::RecvPBluetoothRequestConstructor(
|
||||
case Request::TGattClientWriteDescriptorValueRequest:
|
||||
return actor->DoRequest(
|
||||
aRequest.get_GattClientWriteDescriptorValueRequest());
|
||||
case Request::TGattServerConnectPeripheralRequest:
|
||||
return actor->DoRequest(
|
||||
aRequest.get_GattServerConnectPeripheralRequest());
|
||||
case Request::TGattServerDisconnectPeripheralRequest:
|
||||
return actor->DoRequest(
|
||||
aRequest.get_GattServerDisconnectPeripheralRequest());
|
||||
case Request::TUnregisterGattServerRequest:
|
||||
return actor->DoRequest(aRequest.get_UnregisterGattServerRequest());
|
||||
default:
|
||||
MOZ_CRASH("Unknown type!");
|
||||
}
|
||||
@ -973,3 +981,45 @@ BluetoothRequestParent::DoRequest(
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothRequestParent::DoRequest(
|
||||
const GattServerConnectPeripheralRequest& aRequest)
|
||||
{
|
||||
MOZ_ASSERT(mService);
|
||||
MOZ_ASSERT(mRequestType ==
|
||||
Request::TGattServerConnectPeripheralRequest);
|
||||
|
||||
mService->GattServerConnectPeripheralInternal(aRequest.appUuid(),
|
||||
aRequest.address(),
|
||||
mReplyRunnable.get());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothRequestParent::DoRequest(
|
||||
const GattServerDisconnectPeripheralRequest& aRequest)
|
||||
{
|
||||
MOZ_ASSERT(mService);
|
||||
MOZ_ASSERT(mRequestType ==
|
||||
Request::TGattServerDisconnectPeripheralRequest);
|
||||
|
||||
mService->GattServerDisconnectPeripheralInternal(aRequest.appUuid(),
|
||||
aRequest.address(),
|
||||
mReplyRunnable.get());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothRequestParent::DoRequest(const UnregisterGattServerRequest& aRequest)
|
||||
{
|
||||
MOZ_ASSERT(mService);
|
||||
MOZ_ASSERT(mRequestType == Request::TUnregisterGattServerRequest);
|
||||
|
||||
mService->UnregisterGattServerInternal(aRequest.serverIf(),
|
||||
mReplyRunnable.get());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -270,6 +270,15 @@ protected:
|
||||
|
||||
bool
|
||||
DoRequest(const GattClientWriteDescriptorValueRequest& aRequest);
|
||||
|
||||
bool
|
||||
DoRequest(const GattServerConnectPeripheralRequest& aRequest);
|
||||
|
||||
bool
|
||||
DoRequest(const GattServerDisconnectPeripheralRequest& aRequest);
|
||||
|
||||
bool
|
||||
DoRequest(const UnregisterGattServerRequest& aRequest);
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
@ -598,6 +598,35 @@ BluetoothServiceChildProcess::GattClientWriteDescriptorValueInternal(
|
||||
aValue));
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceChildProcess::GattServerConnectPeripheralInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
SendRequest(aRunnable,
|
||||
GattServerConnectPeripheralRequest(nsString(aAppUuid),
|
||||
nsString(aAddress)));
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceChildProcess::GattServerDisconnectPeripheralInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
SendRequest(aRunnable,
|
||||
GattServerDisconnectPeripheralRequest(nsString(aAppUuid),
|
||||
nsString(aAddress)));
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceChildProcess::UnregisterGattServerInternal(
|
||||
int aServerIf, BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
SendRequest(aRunnable, UnregisterGattServerRequest(aServerIf));
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothServiceChildProcess::HandleStartup()
|
||||
{
|
||||
|
@ -298,6 +298,22 @@ public:
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
virtual void
|
||||
GattServerConnectPeripheralInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
virtual void
|
||||
GattServerDisconnectPeripheralInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
virtual void
|
||||
UnregisterGattServerInternal(int aServerIf,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
protected:
|
||||
BluetoothServiceChildProcess();
|
||||
virtual ~BluetoothServiceChildProcess();
|
||||
|
@ -292,6 +292,23 @@ struct GattClientWriteDescriptorValueRequest
|
||||
uint8_t[] value;
|
||||
};
|
||||
|
||||
struct GattServerConnectPeripheralRequest
|
||||
{
|
||||
nsString appUuid;
|
||||
nsString address;
|
||||
};
|
||||
|
||||
struct GattServerDisconnectPeripheralRequest
|
||||
{
|
||||
nsString appUuid;
|
||||
nsString address;
|
||||
};
|
||||
|
||||
struct UnregisterGattServerRequest
|
||||
{
|
||||
int serverIf;
|
||||
};
|
||||
|
||||
union Request
|
||||
{
|
||||
GetAdaptersRequest;
|
||||
@ -342,6 +359,9 @@ union Request
|
||||
GattClientWriteCharacteristicValueRequest;
|
||||
GattClientReadDescriptorValueRequest;
|
||||
GattClientWriteDescriptorValueRequest;
|
||||
GattServerConnectPeripheralRequest;
|
||||
GattServerDisconnectPeripheralRequest;
|
||||
UnregisterGattServerRequest;
|
||||
};
|
||||
|
||||
protocol PBluetooth
|
||||
|
@ -4379,6 +4379,26 @@ BluetoothDBusService::GattClientWriteDescriptorValueInternal(
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDBusService::GattServerConnectPeripheralInternal(
|
||||
const nsAString& aAppUuid, const nsAString& aAddress,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDBusService::GattServerDisconnectPeripheralInternal(
|
||||
const nsAString& aAppUuid, const nsAString& aAddress,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDBusService::UnregisterGattServerInternal(
|
||||
int aServerIf, BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDBusService::ReplyTovCardPulling(
|
||||
BlobParent* aBlobParent,
|
||||
|
@ -305,6 +305,22 @@ public:
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
GattServerConnectPeripheralInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
GattServerDisconnectPeripheralInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
UnregisterGattServerInternal(int aServerIf,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
private:
|
||||
nsresult SendGetPropertyMessage(const nsAString& aPath,
|
||||
const char* aInterface,
|
||||
|
@ -5,9 +5,19 @@
|
||||
*/
|
||||
|
||||
[CheckAnyPermissions="bluetooth"]
|
||||
interface BluetoothGattServer
|
||||
interface BluetoothGattServer : EventTarget
|
||||
{
|
||||
/* The implementation of BluetoothGattServer will come later.
|
||||
* (see dependent bugs of bug 933358)
|
||||
// Fired when a remote device has been connected/disconnected
|
||||
attribute EventHandler onconnectionstatechanged;
|
||||
|
||||
/**
|
||||
* Connect/Disconnect to the remote BLE device with the target address.
|
||||
*
|
||||
* Promise will be rejected if the local GATT server is busy connecting or
|
||||
* disconnecting to other devices.
|
||||
*/
|
||||
[NewObject]
|
||||
Promise<void> connect(DOMString address);
|
||||
[NewObject]
|
||||
Promise<void> disconnect(DOMString address);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user