mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-15 06:15:43 +00:00
Bug 1140952 - Implement read/write value of a descriptor for GATT client API (ipc part). f=jocelyn, r=btian
This commit is contained in:
parent
ea2fb4850a
commit
056f82d8c9
@ -768,16 +768,15 @@ public:
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
int aAuthReq,
|
||||
BluetoothGattAuthReq aAuthReq,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
virtual void WriteDescriptor(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
int aWriteType,
|
||||
int aLen,
|
||||
int aAuthReq,
|
||||
const ArrayBuffer& aValue,
|
||||
BluetoothGattWriteType aWriteType,
|
||||
BluetoothGattAuthReq aAuthReq,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
|
||||
/* Execute / Abort Prepared Write*/
|
||||
|
@ -814,19 +814,21 @@ BluetoothGattClientHALInterface::ReadDescriptor(
|
||||
int aConnId, const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
int aAuthReq, BluetoothGattClientResultHandler* aRes)
|
||||
BluetoothGattAuthReq aAuthReq, BluetoothGattClientResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
#if ANDROID_VERSION >= 19
|
||||
btgatt_srvc_id_t serviceId;
|
||||
btgatt_gatt_id_t charId;
|
||||
btgatt_gatt_id_t descriptorId;
|
||||
int authReq;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aServiceId, serviceId)) &&
|
||||
NS_SUCCEEDED(Convert(aCharId, charId)) &&
|
||||
NS_SUCCEEDED(Convert(aDescriptorId, descriptorId))) {
|
||||
NS_SUCCEEDED(Convert(aDescriptorId, descriptorId)) &&
|
||||
NS_SUCCEEDED(Convert(aAuthReq, authReq))) {
|
||||
status = mInterface->read_descriptor(aConnId, &serviceId, &charId,
|
||||
&descriptorId, aAuthReq);
|
||||
&descriptorId, authReq);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
@ -846,8 +848,9 @@ BluetoothGattClientHALInterface::WriteDescriptor(
|
||||
int aConnId, const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
int aWriteType, int aLen, int aAuthReq,
|
||||
const ArrayBuffer& aValue,
|
||||
BluetoothGattWriteType aWriteType,
|
||||
BluetoothGattAuthReq aAuthReq,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothGattClientResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
@ -855,15 +858,18 @@ BluetoothGattClientHALInterface::WriteDescriptor(
|
||||
btgatt_srvc_id_t serviceId;
|
||||
btgatt_gatt_id_t charId;
|
||||
btgatt_gatt_id_t descriptorId;
|
||||
char value[aLen + 1];
|
||||
int writeType;
|
||||
int authReq;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aServiceId, serviceId)) &&
|
||||
NS_SUCCEEDED(Convert(aCharId, charId)) &&
|
||||
NS_SUCCEEDED(Convert(aDescriptorId, descriptorId)) &&
|
||||
NS_SUCCEEDED(Convert(aValue, value))) {
|
||||
status = mInterface->write_descriptor(aConnId, &serviceId, &charId,
|
||||
&descriptorId, aWriteType, aLen,
|
||||
aAuthReq, value);
|
||||
NS_SUCCEEDED(Convert(aWriteType, writeType)) &&
|
||||
NS_SUCCEEDED(Convert(aAuthReq, authReq))) {
|
||||
status = mInterface->write_descriptor(
|
||||
aConnId, &serviceId, &charId, &descriptorId, writeType,
|
||||
aValue.Length() * sizeof(uint8_t), authReq,
|
||||
reinterpret_cast<char*>(const_cast<uint8_t*>(aValue.Elements())));
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
|
@ -93,16 +93,15 @@ public:
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
int aAuthReq,
|
||||
BluetoothGattAuthReq aAuthReq,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void WriteDescriptor(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
int aWriteType,
|
||||
int aLen,
|
||||
int aAuthReq,
|
||||
const ArrayBuffer& aValue,
|
||||
BluetoothGattWriteType aWriteType,
|
||||
BluetoothGattAuthReq aAuthReq,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
/* Execute / Abort Prepared Write*/
|
||||
|
@ -85,6 +85,48 @@ struct BluetoothGattClientWriteCharState
|
||||
}
|
||||
};
|
||||
|
||||
struct BluetoothGattClientReadDescState
|
||||
{
|
||||
bool mAuthRetry;
|
||||
nsRefPtr<BluetoothReplyRunnable> mRunnable;
|
||||
|
||||
void Assign(bool aAuthRetry,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
mAuthRetry = aAuthRetry;
|
||||
mRunnable = aRunnable;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
mAuthRetry = false;
|
||||
mRunnable = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
struct BluetoothGattClientWriteDescState
|
||||
{
|
||||
nsTArray<uint8_t> mWriteValue;
|
||||
bool mAuthRetry;
|
||||
nsRefPtr<BluetoothReplyRunnable> mRunnable;
|
||||
|
||||
void Assign(const nsTArray<uint8_t>& aWriteValue,
|
||||
bool aAuthRetry,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
mWriteValue = aWriteValue;
|
||||
mAuthRetry = aAuthRetry;
|
||||
mRunnable = aRunnable;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
mWriteValue.Clear();
|
||||
mAuthRetry = false;
|
||||
mRunnable = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class mozilla::dom::bluetooth::BluetoothGattClient final : public nsISupports
|
||||
{
|
||||
public:
|
||||
@ -108,6 +150,8 @@ public:
|
||||
mDeregisterNotificationsRunnable = nullptr;
|
||||
mReadCharacteristicState.Reset();
|
||||
mWriteCharacteristicState.Reset();
|
||||
mReadDescriptorState.Reset();
|
||||
mWriteDescriptorState.Reset();
|
||||
}
|
||||
|
||||
void NotifyDiscoverCompleted(bool aSuccess)
|
||||
@ -154,6 +198,8 @@ public:
|
||||
|
||||
BluetoothGattClientReadCharState mReadCharacteristicState;
|
||||
BluetoothGattClientWriteCharState mWriteCharacteristicState;
|
||||
BluetoothGattClientReadDescState mReadDescriptorState;
|
||||
BluetoothGattClientWriteDescState mWriteDescriptorState;
|
||||
|
||||
/**
|
||||
* These temporary arrays are used only during discover operations.
|
||||
@ -1000,6 +1046,173 @@ BluetoothGattManager::WriteCharacteristicValue(
|
||||
new WriteCharacteristicValueResultHandler(client));
|
||||
}
|
||||
|
||||
class BluetoothGattManager::ReadDescriptorValueResultHandler final
|
||||
: public BluetoothGattClientResultHandler
|
||||
{
|
||||
public:
|
||||
ReadDescriptorValueResultHandler(BluetoothGattClient* aClient)
|
||||
: mClient(aClient)
|
||||
{
|
||||
MOZ_ASSERT(mClient);
|
||||
}
|
||||
|
||||
void OnError(BluetoothStatus aStatus) override
|
||||
{
|
||||
BT_WARNING("BluetoothGattClientInterface::ReadDescriptorValue failed: %d",
|
||||
(int)aStatus);
|
||||
MOZ_ASSERT(mClient->mReadDescriptorState.mRunnable);
|
||||
|
||||
nsRefPtr<BluetoothReplyRunnable> runnable =
|
||||
mClient->mReadDescriptorState.mRunnable;
|
||||
mClient->mReadDescriptorState.Reset();
|
||||
|
||||
// Reject the read descriptor value request
|
||||
DispatchReplyError(runnable,
|
||||
NS_LITERAL_STRING("ReadDescriptorValue failed"));
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothGattClient> mClient;
|
||||
};
|
||||
|
||||
void
|
||||
BluetoothGattManager::ReadDescriptorValue(
|
||||
const nsAString& aAppUuid,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharacteristicId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
// Reject the read descriptor value request
|
||||
DispatchReplyError(aRunnable,
|
||||
NS_LITERAL_STRING("ReadDescriptorValue failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
|
||||
/**
|
||||
* Reject subsequent reading requests to follow ATT sequential protocol that
|
||||
* handles one request at a time. Otherwise underlying layers would drop the
|
||||
* subsequent requests silently.
|
||||
*
|
||||
* Bug 1147776 intends to solve a larger problem that other kind of requests
|
||||
* may still interfere the ongoing request.
|
||||
*/
|
||||
if (client->mReadDescriptorState.mRunnable) {
|
||||
DispatchReplyError(aRunnable,
|
||||
NS_LITERAL_STRING("ReadDescriptorValue failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
client->mReadDescriptorState.Assign(false, aRunnable);
|
||||
|
||||
/**
|
||||
* First, read the descriptor value through an unauthenticated physical
|
||||
* link. If the operation fails due to insufficient authentication/encryption
|
||||
* key size, retry to read through an authenticated physical link.
|
||||
*/
|
||||
sBluetoothGattClientInterface->ReadDescriptor(
|
||||
client->mConnId,
|
||||
aServiceId,
|
||||
aCharacteristicId,
|
||||
aDescriptorId,
|
||||
GATT_AUTH_REQ_NONE,
|
||||
new ReadDescriptorValueResultHandler(client));
|
||||
}
|
||||
|
||||
class BluetoothGattManager::WriteDescriptorValueResultHandler final
|
||||
: public BluetoothGattClientResultHandler
|
||||
{
|
||||
public:
|
||||
WriteDescriptorValueResultHandler(BluetoothGattClient* aClient)
|
||||
: mClient(aClient)
|
||||
{
|
||||
MOZ_ASSERT(mClient);
|
||||
}
|
||||
|
||||
void OnError(BluetoothStatus aStatus) override
|
||||
{
|
||||
BT_WARNING("BluetoothGattClientInterface::WriteDescriptorValue failed: %d",
|
||||
(int)aStatus);
|
||||
MOZ_ASSERT(mClient->mWriteDescriptorState.mRunnable);
|
||||
|
||||
nsRefPtr<BluetoothReplyRunnable> runnable =
|
||||
mClient->mWriteDescriptorState.mRunnable;
|
||||
mClient->mWriteDescriptorState.Reset();
|
||||
|
||||
// Reject the write descriptor value request
|
||||
DispatchReplyError(runnable,
|
||||
NS_LITERAL_STRING("WriteDescriptorValue failed"));
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothGattClient> mClient;
|
||||
};
|
||||
|
||||
void
|
||||
BluetoothGattManager::WriteDescriptorValue(
|
||||
const nsAString& aAppUuid,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharacteristicId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
// Reject the write descriptor value request
|
||||
DispatchReplyError(aRunnable,
|
||||
NS_LITERAL_STRING("WriteDescriptorValue failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
|
||||
/**
|
||||
* Reject subsequent writing requests to follow ATT sequential protocol that
|
||||
* handles one request at a time. Otherwise underlying layers would drop the
|
||||
* subsequent requests silently.
|
||||
*
|
||||
* Bug 1147776 intends to solve a larger problem that other kind of requests
|
||||
* may still interfere the ongoing request.
|
||||
*/
|
||||
if (client->mWriteDescriptorState.mRunnable) {
|
||||
DispatchReplyError(aRunnable,
|
||||
NS_LITERAL_STRING("WriteDescriptorValue failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* First, write the descriptor value through an unauthenticated physical
|
||||
* link. If the operation fails due to insufficient authentication/encryption
|
||||
* key size, retry to write through an authenticated physical link.
|
||||
*/
|
||||
client->mWriteDescriptorState.Assign(aValue, false, aRunnable);
|
||||
|
||||
sBluetoothGattClientInterface->WriteDescriptor(
|
||||
client->mConnId,
|
||||
aServiceId,
|
||||
aCharacteristicId,
|
||||
aDescriptorId,
|
||||
GATT_WRITE_TYPE_NORMAL,
|
||||
GATT_AUTH_REQ_NONE,
|
||||
aValue,
|
||||
new WriteDescriptorValueResultHandler(client));
|
||||
}
|
||||
|
||||
//
|
||||
// Notification Handlers
|
||||
//
|
||||
@ -1494,13 +1707,97 @@ void
|
||||
BluetoothGattManager::ReadDescriptorNotification(
|
||||
int aConnId, BluetoothGattStatus aStatus,
|
||||
const BluetoothGattReadParam& aReadParam)
|
||||
{ }
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
size_t index = sClients->IndexOf(aConnId, 0 /* Start */, ConnIdComparator());
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
|
||||
MOZ_ASSERT(client->mReadDescriptorState.mRunnable);
|
||||
nsRefPtr<BluetoothReplyRunnable> runnable =
|
||||
client->mReadDescriptorState.mRunnable;
|
||||
|
||||
if (aStatus == GATT_STATUS_SUCCESS) {
|
||||
client->mReadDescriptorState.Reset();
|
||||
// Notify BluetoothGattDescriptor to update descriptor value
|
||||
nsString path;
|
||||
GeneratePathFromGattId(aReadParam.mDescriptorId, path);
|
||||
|
||||
nsTArray<uint8_t> value;
|
||||
value.AppendElements(aReadParam.mValue, aReadParam.mValueLength);
|
||||
|
||||
bs->DistributeSignal(NS_LITERAL_STRING("DescriptorValueUpdated"),
|
||||
path,
|
||||
BluetoothValue(value));
|
||||
|
||||
// Resolve the promise
|
||||
DispatchReplySuccess(runnable, BluetoothValue(value));
|
||||
} else if (!client->mReadDescriptorState.mAuthRetry &&
|
||||
(aStatus == GATT_STATUS_INSUFFICIENT_AUTHENTICATION ||
|
||||
aStatus == GATT_STATUS_INSUFFICIENT_ENCRYPTION)) {
|
||||
client->mReadDescriptorState.mAuthRetry = true;
|
||||
// Retry with another authentication requirement
|
||||
sBluetoothGattClientInterface->ReadDescriptor(
|
||||
aConnId,
|
||||
aReadParam.mServiceId,
|
||||
aReadParam.mCharId,
|
||||
aReadParam.mDescriptorId,
|
||||
GATT_AUTH_REQ_MITM,
|
||||
new ReadDescriptorValueResultHandler(client));
|
||||
} else {
|
||||
client->mReadDescriptorState.Reset();
|
||||
// Reject the promise
|
||||
DispatchReplyError(runnable,
|
||||
NS_LITERAL_STRING("ReadDescriptorValue failed"));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothGattManager::WriteDescriptorNotification(
|
||||
int aConnId, BluetoothGattStatus aStatus,
|
||||
const BluetoothGattWriteParam& aWriteParam)
|
||||
{ }
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
size_t index = sClients->IndexOf(aConnId, 0 /* Start */, ConnIdComparator());
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
|
||||
MOZ_ASSERT(client->mWriteDescriptorState.mRunnable);
|
||||
nsRefPtr<BluetoothReplyRunnable> runnable =
|
||||
client->mWriteDescriptorState.mRunnable;
|
||||
|
||||
if (aStatus == GATT_STATUS_SUCCESS) {
|
||||
client->mWriteDescriptorState.Reset();
|
||||
// Resolve the promise
|
||||
DispatchReplySuccess(runnable);
|
||||
} else if (!client->mWriteDescriptorState.mAuthRetry &&
|
||||
(aStatus == GATT_STATUS_INSUFFICIENT_AUTHENTICATION ||
|
||||
aStatus == GATT_STATUS_INSUFFICIENT_ENCRYPTION)) {
|
||||
client->mWriteDescriptorState.mAuthRetry = true;
|
||||
// Retry with another authentication requirement
|
||||
sBluetoothGattClientInterface->WriteDescriptor(
|
||||
aConnId,
|
||||
aWriteParam.mServiceId,
|
||||
aWriteParam.mCharId,
|
||||
aWriteParam.mDescriptorId,
|
||||
GATT_WRITE_TYPE_NORMAL,
|
||||
GATT_AUTH_REQ_MITM,
|
||||
client->mWriteDescriptorState.mWriteValue,
|
||||
new WriteDescriptorValueResultHandler(client));
|
||||
} else {
|
||||
client->mWriteDescriptorState.Reset();
|
||||
// Reject the promise
|
||||
DispatchReplyError(runnable,
|
||||
NS_LITERAL_STRING("WriteDescriptorValue failed"));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothGattManager::ExecuteWriteNotification(int aConnId,
|
||||
|
@ -70,6 +70,21 @@ public:
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
void ReadDescriptorValue(
|
||||
const nsAString& aAppUuid,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharacteristicId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
void WriteDescriptorValue(
|
||||
const nsAString& aAppUuid,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharacteristicId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
private:
|
||||
class CleanupResultHandler;
|
||||
class CleanupResultHandlerRunnable;
|
||||
@ -84,6 +99,8 @@ private:
|
||||
class DeregisterNotificationsResultHandler;
|
||||
class ReadCharacteristicValueResultHandler;
|
||||
class WriteCharacteristicValueResultHandler;
|
||||
class ReadDescriptorValueResultHandler;
|
||||
class WriteDescriptorValueResultHandler;
|
||||
|
||||
BluetoothGattManager();
|
||||
|
||||
|
@ -527,6 +527,45 @@ BluetoothServiceBluedroid::GattClientWriteCharacteristicValueInternal(
|
||||
gatt->WriteCharacteristicValue(aAppUuid, aServiceId, aCharacteristicId,
|
||||
aWriteType, aValue, aRunnable);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceBluedroid::GattClientReadDescriptorValueInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharacteristicId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
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->ReadDescriptorValue(aAppUuid, aServiceId, aCharacteristicId,
|
||||
aDescriptorId, aRunnable);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceBluedroid::GattClientWriteDescriptorValueInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharacteristicId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
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->WriteDescriptorValue(aAppUuid, aServiceId, aCharacteristicId,
|
||||
aDescriptorId, aValue, aRunnable);
|
||||
}
|
||||
#else
|
||||
|
||||
#define ENSURE_BLUETOOTH_IS_READY(runnable, result) \
|
||||
|
@ -244,6 +244,23 @@ public:
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
GattClientReadDescriptorValueInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharacteristicId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
GattClientWriteDescriptorValueInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharacteristicId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
//
|
||||
// Bluetooth notifications
|
||||
//
|
||||
|
@ -4,12 +4,14 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "BluetoothReplyRunnable.h"
|
||||
#include "BluetoothService.h"
|
||||
#include "BluetoothUtils.h"
|
||||
#include "mozilla/dom/BluetoothGattDescriptorBinding.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothGattCharacteristic.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothGattDescriptor.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothGattService.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
|
||||
using namespace mozilla;
|
||||
@ -37,13 +39,47 @@ BluetoothGattDescriptor::BluetoothGattDescriptor(
|
||||
MOZ_ASSERT(aOwner);
|
||||
MOZ_ASSERT(aCharacteristic);
|
||||
|
||||
// Generate a string representation to provide uuid of this descriptor to
|
||||
// applications
|
||||
ReversedUuidToString(aDescriptorId.mUuid, mUuidStr);
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
// Generate bluetooth signal path and a string representation to provide uuid
|
||||
// of this descriptor to applications
|
||||
nsString path;
|
||||
GeneratePathFromGattId(mDescriptorId, path, mUuidStr);
|
||||
bs->RegisterBluetoothSignalHandler(path, this);
|
||||
}
|
||||
|
||||
BluetoothGattDescriptor::~BluetoothGattDescriptor()
|
||||
{
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
nsString path;
|
||||
GeneratePathFromGattId(mDescriptorId, path);
|
||||
bs->UnregisterBluetoothSignalHandler(path, this);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothGattDescriptor::HandleDescriptorValueUpdated(
|
||||
const BluetoothValue& aValue)
|
||||
{
|
||||
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfuint8_t);
|
||||
|
||||
mValue = aValue.get_ArrayOfuint8_t();
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothGattDescriptor::Notify(const BluetoothSignal& aData)
|
||||
{
|
||||
BT_LOGD("[D] %s", NS_ConvertUTF16toUTF8(aData.name()).get());
|
||||
|
||||
BluetoothValue v = aData.value();
|
||||
if (aData.name().EqualsLiteral("DescriptorValueUpdated")) {
|
||||
HandleDescriptorValueUpdated(v);
|
||||
} else {
|
||||
BT_WARNING("Not handling GATT Descriptor signal: %s",
|
||||
NS_ConvertUTF16toUTF8(aData.name()).get());
|
||||
}
|
||||
}
|
||||
|
||||
JSObject*
|
||||
@ -64,17 +100,106 @@ BluetoothGattDescriptor::GetValue(JSContext* cx,
|
||||
: ArrayBuffer::Create(cx, mValue.Length(), mValue.Elements()));
|
||||
}
|
||||
|
||||
class ReadValueTask final : public BluetoothReplyRunnable
|
||||
{
|
||||
public:
|
||||
ReadValueTask(BluetoothGattDescriptor* aDescriptor, Promise* aPromise)
|
||||
: BluetoothReplyRunnable(
|
||||
nullptr, aPromise,
|
||||
NS_LITERAL_STRING("GattClientReadDescriptorValue"))
|
||||
, mDescriptor(aDescriptor)
|
||||
{
|
||||
MOZ_ASSERT(aDescriptor);
|
||||
MOZ_ASSERT(aPromise);
|
||||
}
|
||||
|
||||
bool
|
||||
ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
|
||||
{
|
||||
aValue.setUndefined();
|
||||
|
||||
const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
|
||||
NS_ENSURE_TRUE(v.type() == BluetoothValue::TArrayOfuint8_t, false);
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
NS_ENSURE_TRUE(jsapi.Init(mDescriptor->GetParentObject()), false);
|
||||
|
||||
JSContext* cx = jsapi.cx();
|
||||
if (!ToJSValue(cx, v.get_ArrayOfuint8_t(), aValue)) {
|
||||
JS_ClearPendingException(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ReleaseMembers()
|
||||
{
|
||||
BluetoothReplyRunnable::ReleaseMembers();
|
||||
mDescriptor = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothGattDescriptor> mDescriptor;
|
||||
};
|
||||
|
||||
already_AddRefed<Promise>
|
||||
BluetoothGattDescriptor::ReadValue(ErrorResult& aRv)
|
||||
{
|
||||
// TODO: This will be implemented by later patch set in the same bug.
|
||||
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);
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
BT_ENSURE_TRUE_REJECT(bs, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsRefPtr<BluetoothReplyRunnable> result = new ReadValueTask(this, promise);
|
||||
bs->GattClientReadDescriptorValueInternal(
|
||||
mCharacteristic->Service()->GetAppUuid(),
|
||||
mCharacteristic->Service()->GetServiceId(),
|
||||
mCharacteristic->GetCharacteristicId(),
|
||||
mDescriptorId,
|
||||
result);
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
BluetoothGattDescriptor::WriteValue(
|
||||
const RootedTypedArray<ArrayBuffer>& aValue, ErrorResult& aRv)
|
||||
{
|
||||
// TODO: This will be implemented by later patch set in the same bug.
|
||||
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);
|
||||
|
||||
aValue.ComputeLengthAndData();
|
||||
|
||||
nsTArray<uint8_t> value;
|
||||
value.AppendElements(aValue.Data(), aValue.Length());
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
BT_ENSURE_TRUE_REJECT(bs, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsRefPtr<BluetoothReplyRunnable> result = new BluetoothVoidReplyRunnable(
|
||||
nullptr, promise, NS_LITERAL_STRING("GattClientWriteDescriptorValue"));
|
||||
bs->GattClientWriteDescriptorValueInternal(
|
||||
mCharacteristic->Service()->GetAppUuid(),
|
||||
mCharacteristic->Service()->GetServiceId(),
|
||||
mCharacteristic->GetCharacteristicId(),
|
||||
mDescriptorId,
|
||||
value,
|
||||
result);
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ class BluetoothValue;
|
||||
|
||||
class BluetoothGattDescriptor final : public nsISupports
|
||||
, public nsWrapperCache
|
||||
, public BluetoothSignalObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
@ -71,6 +72,13 @@ public:
|
||||
private:
|
||||
~BluetoothGattDescriptor();
|
||||
|
||||
/**
|
||||
* Update the value of this descriptor.
|
||||
*
|
||||
* @param aValue [in] BluetoothValue which contains an uint8_t array.
|
||||
*/
|
||||
void HandleDescriptorValueUpdated(const BluetoothValue& aValue);
|
||||
|
||||
/****************************************************************************
|
||||
* Variables
|
||||
***************************************************************************/
|
||||
|
@ -431,6 +431,31 @@ public:
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
/**
|
||||
* Read the value of a descriptor of a characteristic on a GATT client.
|
||||
* (platform specific implementation)
|
||||
*/
|
||||
virtual void
|
||||
GattClientReadDescriptorValueInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharacteristicId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
/**
|
||||
* Write the value of a descriptor of a characteristic on a GATT client.
|
||||
* (platform specific implementation)
|
||||
*/
|
||||
virtual void
|
||||
GattClientWriteDescriptorValueInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharacteristicId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
bool
|
||||
IsEnabled() const
|
||||
{
|
||||
|
@ -276,6 +276,12 @@ BluetoothParent::RecvPBluetoothRequestConstructor(
|
||||
case Request::TGattClientWriteCharacteristicValueRequest:
|
||||
return actor->DoRequest(
|
||||
aRequest.get_GattClientWriteCharacteristicValueRequest());
|
||||
case Request::TGattClientReadDescriptorValueRequest:
|
||||
return actor->DoRequest(
|
||||
aRequest.get_GattClientReadDescriptorValueRequest());
|
||||
case Request::TGattClientWriteDescriptorValueRequest:
|
||||
return actor->DoRequest(
|
||||
aRequest.get_GattClientWriteDescriptorValueRequest());
|
||||
default:
|
||||
MOZ_CRASH("Unknown type!");
|
||||
}
|
||||
@ -866,3 +872,38 @@ BluetoothRequestParent::DoRequest(
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothRequestParent::DoRequest(
|
||||
const GattClientReadDescriptorValueRequest& aRequest)
|
||||
{
|
||||
MOZ_ASSERT(mService);
|
||||
MOZ_ASSERT(mRequestType ==
|
||||
Request::TGattClientReadDescriptorValueRequest);
|
||||
|
||||
mService->GattClientReadDescriptorValueInternal(aRequest.appUuid(),
|
||||
aRequest.serviceId(),
|
||||
aRequest.charId(),
|
||||
aRequest.descId(),
|
||||
mReplyRunnable.get());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothRequestParent::DoRequest(
|
||||
const GattClientWriteDescriptorValueRequest& aRequest)
|
||||
{
|
||||
MOZ_ASSERT(mService);
|
||||
MOZ_ASSERT(mRequestType ==
|
||||
Request::TGattClientWriteDescriptorValueRequest);
|
||||
|
||||
mService->GattClientWriteDescriptorValueInternal(aRequest.appUuid(),
|
||||
aRequest.serviceId(),
|
||||
aRequest.charId(),
|
||||
aRequest.descId(),
|
||||
aRequest.value(),
|
||||
mReplyRunnable.get());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -249,6 +249,12 @@ protected:
|
||||
|
||||
bool
|
||||
DoRequest(const GattClientWriteCharacteristicValueRequest& aRequest);
|
||||
|
||||
bool
|
||||
DoRequest(const GattClientReadDescriptorValueRequest& aRequest);
|
||||
|
||||
bool
|
||||
DoRequest(const GattClientWriteDescriptorValueRequest& aRequest);
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
@ -492,6 +492,38 @@ BluetoothServiceChildProcess::GattClientWriteCharacteristicValueInternal(
|
||||
aValue));
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceChildProcess::GattClientReadDescriptorValueInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharacteristicId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
SendRequest(aRunnable,
|
||||
GattClientReadDescriptorValueRequest(nsString(aAppUuid),
|
||||
aServiceId,
|
||||
aCharacteristicId,
|
||||
aDescriptorId));
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceChildProcess::GattClientWriteDescriptorValueInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharacteristicId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
SendRequest(aRunnable,
|
||||
GattClientWriteDescriptorValueRequest(nsString(aAppUuid),
|
||||
aServiceId,
|
||||
aCharacteristicId,
|
||||
aDescriptorId,
|
||||
aValue));
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothServiceChildProcess::HandleStartup()
|
||||
{
|
||||
|
@ -257,6 +257,23 @@ public:
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
GattClientReadDescriptorValueInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharacteristicId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
virtual void
|
||||
GattClientWriteDescriptorValueInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharacteristicId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
protected:
|
||||
BluetoothServiceChildProcess();
|
||||
virtual ~BluetoothServiceChildProcess();
|
||||
|
@ -248,6 +248,23 @@ struct GattClientWriteCharacteristicValueRequest
|
||||
uint8_t[] value;
|
||||
};
|
||||
|
||||
struct GattClientReadDescriptorValueRequest
|
||||
{
|
||||
nsString appUuid;
|
||||
BluetoothGattServiceId serviceId;
|
||||
BluetoothGattId charId;
|
||||
BluetoothGattId descId;
|
||||
};
|
||||
|
||||
struct GattClientWriteDescriptorValueRequest
|
||||
{
|
||||
nsString appUuid;
|
||||
BluetoothGattServiceId serviceId;
|
||||
BluetoothGattId charId;
|
||||
BluetoothGattId descId;
|
||||
uint8_t[] value;
|
||||
};
|
||||
|
||||
union Request
|
||||
{
|
||||
GetAdaptersRequest;
|
||||
@ -291,6 +308,8 @@ union Request
|
||||
GattClientReadRemoteRssiRequest;
|
||||
GattClientReadCharacteristicValueRequest;
|
||||
GattClientWriteCharacteristicValueRequest;
|
||||
GattClientReadDescriptorValueRequest;
|
||||
GattClientWriteDescriptorValueRequest;
|
||||
};
|
||||
|
||||
protocol PBluetooth
|
||||
|
@ -4761,6 +4761,27 @@ BluetoothDBusService::GattClientWriteCharacteristicValueInternal(
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDBusService::GattClientReadDescriptorValueInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharacteristicId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDBusService::GattClientWriteDescriptorValueInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharacteristicId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
}
|
||||
#else
|
||||
// Missing in bluetooth1
|
||||
#endif
|
||||
|
@ -286,6 +286,23 @@ public:
|
||||
const BluetoothGattWriteType& aWriteType,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
GattClientReadDescriptorValueInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharacteristicId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
GattClientWriteDescriptorValueInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharacteristicId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
#else
|
||||
// Missing in bluetooth1
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user