Bug 1140952 - Implement read/write value of a descriptor for GATT client API (ipc part). f=jocelyn, r=btian

This commit is contained in:
Bruce Sun 2015-04-16 16:45:20 +08:00
parent ea2fb4850a
commit 056f82d8c9
17 changed files with 714 additions and 29 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -249,6 +249,12 @@ protected:
bool
DoRequest(const GattClientWriteCharacteristicValueRequest& aRequest);
bool
DoRequest(const GattClientReadDescriptorValueRequest& aRequest);
bool
DoRequest(const GattClientWriteDescriptorValueRequest& aRequest);
};
END_BLUETOOTH_NAMESPACE

View File

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

View File

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

View File

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

View File

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

View File

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