Bug 1228546 - Implement peripheral mode support for GATT API. r=brsun, r=mrbkap

This commit is contained in:
Jocelyn Liu 2016-01-15 09:50:54 +08:00
parent 54c4ed1fef
commit c6da2ff1c4
23 changed files with 1017 additions and 29 deletions

View File

@ -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);

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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
//

View File

@ -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
{

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -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;

View File

@ -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.
*

View File

@ -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)