mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1181482 - Patch3: Implement |sendResponse| and BluetoothGattAttributeEvent for GATT server read/write requests. r=btian, r=bz
This commit is contained in:
parent
831adbfe19
commit
1832bcbeea
@ -684,6 +684,8 @@ GK_ATOM(onanimationstart, "onanimationstart")
|
||||
GK_ATOM(onantennaavailablechange, "onantennaavailablechange")
|
||||
GK_ATOM(onAppCommand, "onAppCommand")
|
||||
GK_ATOM(onattributechanged, "onattributechanged")
|
||||
GK_ATOM(onattributereadreq, "onattributereadreq")
|
||||
GK_ATOM(onattributewritereq, "onattributewritereq")
|
||||
GK_ATOM(onaudioprocess, "onaudioprocess")
|
||||
GK_ATOM(onbeforecopy, "onbeforecopy")
|
||||
GK_ATOM(onbeforecut, "onbeforecut")
|
||||
|
@ -166,6 +166,10 @@ DOMInterfaces = {
|
||||
'nativeType': 'mozilla::dom::bluetooth::BluetoothGatt',
|
||||
},
|
||||
|
||||
'BluetoothGattAttributeEvent': {
|
||||
'nativeType': 'mozilla::dom::bluetooth::BluetoothGattAttributeEvent',
|
||||
},
|
||||
|
||||
'BluetoothGattCharacteristic': {
|
||||
'nativeType': 'mozilla::dom::bluetooth::BluetoothGattCharacteristic',
|
||||
},
|
||||
|
@ -291,6 +291,7 @@ public:
|
||||
nsRefPtr<BluetoothReplyRunnable> mRemoveServiceRunnable;
|
||||
nsRefPtr<BluetoothReplyRunnable> mStartServiceRunnable;
|
||||
nsRefPtr<BluetoothReplyRunnable> mStopServiceRunnable;
|
||||
nsRefPtr<BluetoothReplyRunnable> mSendResponseRunnable;
|
||||
|
||||
// Map connection id from device address
|
||||
nsDataHashtable<nsStringHashKey, int> mConnectionMap;
|
||||
@ -341,6 +342,18 @@ public:
|
||||
{
|
||||
return aClient->mConnId == aConnId;
|
||||
}
|
||||
|
||||
bool Equals(const nsRefPtr<BluetoothGattServer>& aServer,
|
||||
int aConnId) const
|
||||
{
|
||||
for (
|
||||
auto iter = aServer->mConnectionMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
if (aConnId == iter.Data()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
BluetoothGattManager*
|
||||
@ -2210,6 +2223,81 @@ BluetoothGattManager::ServerStopService(
|
||||
new ServerStopServiceResultHandler(server));
|
||||
}
|
||||
|
||||
class BluetoothGattManager::ServerSendResponseResultHandler final
|
||||
: public BluetoothGattResultHandler
|
||||
{
|
||||
public:
|
||||
ServerSendResponseResultHandler(BluetoothGattServer* aServer)
|
||||
: mServer(aServer)
|
||||
{
|
||||
MOZ_ASSERT(mServer);
|
||||
}
|
||||
|
||||
void SendResponse() override
|
||||
{
|
||||
if (mServer->mSendResponseRunnable) {
|
||||
DispatchReplySuccess(mServer->mSendResponseRunnable);
|
||||
mServer->mSendResponseRunnable = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void OnError(BluetoothStatus aStatus) override
|
||||
{
|
||||
BT_WARNING("BluetoothGattServerInterface::SendResponse failed: %d",
|
||||
(int)aStatus);
|
||||
|
||||
// Reject the send response request
|
||||
if (mServer->mSendResponseRunnable) {
|
||||
DispatchReplyError(mServer->mSendResponseRunnable,
|
||||
NS_LITERAL_STRING("Send response failed"));
|
||||
mServer->mSendResponseRunnable = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothGattServer> mServer;
|
||||
};
|
||||
|
||||
void
|
||||
BluetoothGattManager::ServerSendResponse(const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
uint16_t aStatus,
|
||||
int aRequestId,
|
||||
const BluetoothGattResponse& aRsp,
|
||||
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) {
|
||||
DispatchReplyError(aRunnable, STATUS_NOT_READY);
|
||||
return;
|
||||
}
|
||||
nsRefPtr<BluetoothGattServer> server = sServers->ElementAt(index);
|
||||
|
||||
if (server->mSendResponseRunnable) {
|
||||
DispatchReplyError(aRunnable, STATUS_BUSY);
|
||||
return;
|
||||
}
|
||||
|
||||
int connId = 0;
|
||||
server->mConnectionMap.Get(aAddress, &connId);
|
||||
if (!connId) {
|
||||
DispatchReplyError(aRunnable, STATUS_NOT_READY);
|
||||
return;
|
||||
}
|
||||
|
||||
sBluetoothGattInterface->SendResponse(
|
||||
connId,
|
||||
aRequestId,
|
||||
aStatus,
|
||||
aRsp,
|
||||
new ServerSendResponseResultHandler(server));
|
||||
}
|
||||
|
||||
//
|
||||
// Notification Handlers
|
||||
//
|
||||
@ -3336,6 +3424,110 @@ BluetoothGattManager::ServiceDeletedNotification(
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothGattManager::RequestReadNotification(
|
||||
int aConnId,
|
||||
int aTransId,
|
||||
const nsAString& aBdAddr,
|
||||
const BluetoothAttributeHandle& aAttributeHandle,
|
||||
int aOffset,
|
||||
bool aIsLong)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
NS_ENSURE_TRUE_VOID(aConnId);
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
size_t index = sServers->IndexOf(aConnId, 0 /* Start */, ConnIdComparator());
|
||||
NS_ENSURE_TRUE_VOID(index != sServers->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattServer> server = (*sServers)[index];
|
||||
|
||||
// Send an error response for unsupported requests
|
||||
if (aIsLong || aOffset > 0) {
|
||||
BT_LOGR("Unsupported long attribute read requests");
|
||||
BluetoothGattResponse response;
|
||||
memset(&response, 0, sizeof(BluetoothGattResponse));
|
||||
sBluetoothGattInterface->SendResponse(
|
||||
aConnId,
|
||||
aTransId,
|
||||
GATT_STATUS_REQUEST_NOT_SUPPORTED,
|
||||
response,
|
||||
new ServerSendResponseResultHandler(server));
|
||||
return;
|
||||
}
|
||||
|
||||
// Distribute a signal to gattServer
|
||||
InfallibleTArray<BluetoothNamedValue> properties;
|
||||
|
||||
AppendNamedValue(properties, "TransId", aTransId);
|
||||
AppendNamedValue(properties, "AttrHandle", aAttributeHandle);
|
||||
AppendNamedValue(properties, "Address", nsString(aBdAddr));
|
||||
AppendNamedValue(properties, "NeedResponse", true);
|
||||
AppendNamedValue(properties, "Value", new nsTArray<uint8_t>());
|
||||
|
||||
bs->DistributeSignal(NS_LITERAL_STRING("ReadRequested"),
|
||||
server->mAppUuid,
|
||||
properties);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothGattManager::RequestWriteNotification(
|
||||
int aConnId,
|
||||
int aTransId,
|
||||
const nsAString& aBdAddr,
|
||||
const BluetoothAttributeHandle& aAttributeHandle,
|
||||
int aOffset,
|
||||
int aLength,
|
||||
const uint8_t* aValue,
|
||||
bool aNeedResponse,
|
||||
bool aIsPrepareWrite)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
NS_ENSURE_TRUE_VOID(aConnId);
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
size_t index = sServers->IndexOf(aConnId, 0 /* Start */, ConnIdComparator());
|
||||
NS_ENSURE_TRUE_VOID(index != sServers->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattServer> server = (*sServers)[index];
|
||||
|
||||
// Send an error response for unsupported requests
|
||||
if (aIsPrepareWrite || aOffset > 0) {
|
||||
BT_LOGR("Unsupported prepare write or long attribute write requests");
|
||||
if (aNeedResponse) {
|
||||
BluetoothGattResponse response;
|
||||
memset(&response, 0, sizeof(BluetoothGattResponse));
|
||||
sBluetoothGattInterface->SendResponse(
|
||||
aConnId,
|
||||
aTransId,
|
||||
GATT_STATUS_REQUEST_NOT_SUPPORTED,
|
||||
response,
|
||||
new ServerSendResponseResultHandler(server));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Distribute a signal to gattServer
|
||||
InfallibleTArray<BluetoothNamedValue> properties;
|
||||
|
||||
AppendNamedValue(properties, "TransId", aTransId);
|
||||
AppendNamedValue(properties, "AttrHandle", aAttributeHandle);
|
||||
AppendNamedValue(properties, "Address", nsString(aBdAddr));
|
||||
AppendNamedValue(properties, "NeedResponse", aNeedResponse);
|
||||
|
||||
nsTArray<uint8_t> value;
|
||||
value.AppendElements(aValue, aLength);
|
||||
AppendNamedValue(properties, "Value", value);
|
||||
|
||||
bs->DistributeSignal(NS_LITERAL_STRING("WrtieRequested"),
|
||||
server->mAppUuid,
|
||||
properties);
|
||||
}
|
||||
|
||||
BluetoothGattManager::BluetoothGattManager()
|
||||
{ }
|
||||
|
||||
|
@ -146,6 +146,14 @@ public:
|
||||
const BluetoothAttributeHandle& aServiceHandle,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
void ServerSendResponse(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
uint16_t aStatus,
|
||||
int32_t aRequestId,
|
||||
const BluetoothGattResponse& aRsp,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
private:
|
||||
~BluetoothGattManager();
|
||||
|
||||
@ -179,6 +187,7 @@ private:
|
||||
class ServerRemoveDescriptorResultHandler;
|
||||
class ServerStartServiceResultHandler;
|
||||
class ServerStopServiceResultHandler;
|
||||
class ServerSendResponseResultHandler;
|
||||
|
||||
BluetoothGattManager();
|
||||
|
||||
@ -325,6 +334,25 @@ private:
|
||||
int aServerIf,
|
||||
const BluetoothAttributeHandle& aServiceHandle) override;
|
||||
|
||||
void
|
||||
RequestReadNotification(int aConnId,
|
||||
int aTransId,
|
||||
const nsAString& aBdAddr,
|
||||
const BluetoothAttributeHandle& aAttributeHandle,
|
||||
int aOffset,
|
||||
bool aIsLong) override;
|
||||
|
||||
void
|
||||
RequestWriteNotification(int aConnId,
|
||||
int aTransId,
|
||||
const nsAString& aBdAddr,
|
||||
const BluetoothAttributeHandle& aAttributeHandle,
|
||||
int aOffset,
|
||||
int aLength,
|
||||
const uint8_t* aValue,
|
||||
bool aNeedResponse,
|
||||
bool aIsPrepareWrite) override;
|
||||
|
||||
static bool mInShutdown;
|
||||
};
|
||||
|
||||
|
@ -736,6 +736,26 @@ BluetoothServiceBluedroid::GattServerStopServiceInternal(
|
||||
gatt->ServerStopService(aAppUuid, aServiceHandle, aRunnable);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceBluedroid::GattServerSendResponseInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
uint16_t aStatus,
|
||||
int32_t aRequestId,
|
||||
const BluetoothGattResponse& aRsp,
|
||||
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->ServerSendResponse(
|
||||
aAppUuid, aAddress, aStatus, aRequestId, aRsp, aRunnable);
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothServiceBluedroid::GetAdaptersInternal(
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
|
@ -360,6 +360,15 @@ public:
|
||||
const BluetoothAttributeHandle& aServiceHandle,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
GattServerSendResponseInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
uint16_t aStatus,
|
||||
int32_t aRequestId,
|
||||
const BluetoothGattResponse& aRsp,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
//
|
||||
// Bluetooth notifications
|
||||
//
|
||||
|
@ -4502,3 +4502,14 @@ BluetoothDBusService::GattServerStopServiceInternal(
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDBusService::GattServerSendResponseInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
uint16_t aStatus,
|
||||
int32_t aRequestId,
|
||||
const BluetoothGattResponse& aRsp,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
}
|
||||
|
@ -371,6 +371,15 @@ public:
|
||||
const BluetoothAttributeHandle& aServiceHandle,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
GattServerSendResponseInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
uint16_t aStatus,
|
||||
int32_t aRequestId,
|
||||
const BluetoothGattResponse& aRsp,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
private:
|
||||
nsresult SendGetPropertyMessage(const nsAString& aPath,
|
||||
const char* aInterface,
|
||||
|
@ -274,6 +274,13 @@ extern bool gBluetoothDebugFlag;
|
||||
*/
|
||||
#define ATTRIBUTE_CHANGED_ID "attributechanged"
|
||||
|
||||
/**
|
||||
* When the local GATT server received attribute read/write requests, we'll
|
||||
* dispatch an event.
|
||||
*/
|
||||
#define ATTRIBUTE_READ_REQUEST "attributereadreq"
|
||||
#define ATTRIBUTE_WRITE_REQUEST "attributewritereq"
|
||||
|
||||
// Bluetooth address format: xx:xx:xx:xx:xx:xx (or xx_xx_xx_xx_xx_xx)
|
||||
#define BLUETOOTH_ADDRESS_LENGTH 17
|
||||
#define BLUETOOTH_ADDRESS_NONE "00:00:00:00:00:00"
|
||||
@ -695,7 +702,8 @@ enum BluetoothGattAuthReq {
|
||||
GATT_AUTH_REQ_NO_MITM,
|
||||
GATT_AUTH_REQ_MITM,
|
||||
GATT_AUTH_REQ_SIGNED_NO_MITM,
|
||||
GATT_AUTH_REQ_SIGNED_MITM
|
||||
GATT_AUTH_REQ_SIGNED_MITM,
|
||||
GATT_AUTH_REQ_END_GUARD
|
||||
};
|
||||
|
||||
enum BluetoothGattWriteType {
|
||||
@ -821,30 +829,6 @@ struct BluetoothGattTestParam {
|
||||
uint16_t mU5;
|
||||
};
|
||||
|
||||
struct BluetoothGattResponse {
|
||||
uint16_t mHandle;
|
||||
uint16_t mOffset;
|
||||
uint16_t mLength;
|
||||
BluetoothGattAuthReq mAuthReq;
|
||||
uint8_t mValue[BLUETOOTH_GATT_MAX_ATTR_LEN];
|
||||
};
|
||||
|
||||
/**
|
||||
* EIR Data Type, Advertising Data Type (AD Type) and OOB Data Type Definitions
|
||||
* Please refer to https://www.bluetooth.org/en-us/specification/\
|
||||
* assigned-numbers/generic-access-profile
|
||||
*/
|
||||
enum BluetoothGapDataType {
|
||||
GAP_INCOMPLETE_UUID16 = 0X02, // Incomplete List of 16-bit Service Class UUIDs
|
||||
GAP_COMPLETE_UUID16 = 0X03, // Complete List of 16-bit Service Class UUIDs
|
||||
GAP_INCOMPLETE_UUID32 = 0X04, // Incomplete List of 32-bit Service Class UUIDs
|
||||
GAP_COMPLETE_UUID32 = 0X05, // Complete List of 32-bit Service Class UUIDs»
|
||||
GAP_INCOMPLETE_UUID128 = 0X06, // Incomplete List of 128-bit Service Class UUIDs
|
||||
GAP_COMPLETE_UUID128 = 0X07, // Complete List of 128-bit Service Class UUIDs
|
||||
GAP_SHORTENED_NAME = 0X08, // Shortened Local Name
|
||||
GAP_COMPLETE_NAME = 0X09, // Complete Local Name
|
||||
};
|
||||
|
||||
struct BluetoothAttributeHandle {
|
||||
uint16_t mHandle;
|
||||
|
||||
@ -858,6 +842,39 @@ struct BluetoothAttributeHandle {
|
||||
}
|
||||
};
|
||||
|
||||
struct BluetoothGattResponse {
|
||||
BluetoothAttributeHandle mHandle;
|
||||
uint16_t mOffset;
|
||||
uint16_t mLength;
|
||||
BluetoothGattAuthReq mAuthReq;
|
||||
uint8_t mValue[BLUETOOTH_GATT_MAX_ATTR_LEN];
|
||||
|
||||
bool operator==(const BluetoothGattResponse& aOther) const
|
||||
{
|
||||
return mHandle == aOther.mHandle &&
|
||||
mOffset == aOther.mOffset &&
|
||||
mLength == aOther.mLength &&
|
||||
mAuthReq == aOther.mAuthReq &&
|
||||
!memcmp(mValue, aOther.mValue, mLength);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* EIR Data Type, Advertising Data Type (AD Type) and OOB Data Type Definitions
|
||||
* Please refer to https://www.bluetooth.org/en-us/specification/\
|
||||
* assigned-numbers/generic-access-profile
|
||||
*/
|
||||
enum BluetoothGapDataType {
|
||||
GAP_INCOMPLETE_UUID16 = 0X02, // Incomplete List of 16-bit Service Class UUIDs
|
||||
GAP_COMPLETE_UUID16 = 0X03, // Complete List of 16-bit Service Class UUIDs
|
||||
GAP_INCOMPLETE_UUID32 = 0X04, // Incomplete List of 32-bit Service Class UUIDs
|
||||
GAP_COMPLETE_UUID32 = 0X05, // Complete List of 32-bit Service Class UUIDs
|
||||
GAP_INCOMPLETE_UUID128 = 0X06, // Incomplete List of 128-bit Service Class UUIDs
|
||||
GAP_COMPLETE_UUID128 = 0X07, // Complete List of 128-bit Service Class UUIDs
|
||||
GAP_SHORTENED_NAME = 0X08, // Shortened Local Name
|
||||
GAP_COMPLETE_NAME = 0X09, // Complete Local Name
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_bluetooth_BluetoothCommon_h
|
||||
|
@ -558,6 +558,15 @@ public:
|
||||
const BluetoothAttributeHandle& aServiceHandle,
|
||||
BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
virtual void
|
||||
GattServerSendResponseInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
uint16_t aStatus,
|
||||
int32_t aRequestId,
|
||||
const BluetoothGattResponse& aRsp,
|
||||
BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
bool
|
||||
IsEnabled() const
|
||||
{
|
||||
|
181
dom/bluetooth/common/webapi/BluetoothGattAttributeEvent.cpp
Normal file
181
dom/bluetooth/common/webapi/BluetoothGattAttributeEvent.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 "mozilla/dom/bluetooth/BluetoothGattAttributeEvent.h"
|
||||
|
||||
#include "js/GCAPI.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "mozilla/dom/BluetoothGattAttributeEventBinding.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothGattCharacteristic.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothGattDescriptor.h"
|
||||
#include "mozilla/dom/EventBinding.h"
|
||||
#include "mozilla/dom/Nullable.h"
|
||||
#include "mozilla/dom/PrimitiveConversions.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothGattAttributeEvent)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(BluetoothGattAttributeEvent, Event)
|
||||
NS_IMPL_RELEASE_INHERITED(BluetoothGattAttributeEvent, Event)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothGattAttributeEvent,
|
||||
Event)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCharacteristic)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDescriptor)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(BluetoothGattAttributeEvent,
|
||||
Event)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mValue)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothGattAttributeEvent,
|
||||
Event)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCharacteristic)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDescriptor)
|
||||
tmp->mValue = nullptr;
|
||||
mozilla::DropJSObjects(this);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothGattAttributeEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(Event)
|
||||
|
||||
BluetoothGattAttributeEvent::BluetoothGattAttributeEvent(EventTarget* aOwner)
|
||||
: Event(aOwner, nullptr, nullptr)
|
||||
{
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
|
||||
BluetoothGattAttributeEvent::~BluetoothGattAttributeEvent()
|
||||
{
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
BluetoothGattAttributeEvent::WrapObjectInternal(
|
||||
JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return BluetoothGattAttributeEventBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
already_AddRefed<BluetoothGattAttributeEvent>
|
||||
BluetoothGattAttributeEvent::Constructor(
|
||||
EventTarget* aOwner,
|
||||
const nsAString& aType,
|
||||
const nsAString& aAddress,
|
||||
int32_t aRequestId,
|
||||
BluetoothGattCharacteristic* aCharacteristic,
|
||||
BluetoothGattDescriptor* aDescriptor,
|
||||
const nsTArray<uint8_t>* aValue,
|
||||
bool aNeedResponse,
|
||||
bool aBubbles,
|
||||
bool aCancelable)
|
||||
{
|
||||
nsRefPtr<BluetoothGattAttributeEvent> e =
|
||||
new BluetoothGattAttributeEvent(aOwner);
|
||||
bool trusted = e->Init(aOwner);
|
||||
|
||||
e->InitEvent(aType, aBubbles, aCancelable);
|
||||
e->mAddress = aAddress;
|
||||
e->mRequestId = aRequestId;
|
||||
e->mCharacteristic = aCharacteristic;
|
||||
e->mDescriptor = aDescriptor;
|
||||
e->mNeedResponse = aNeedResponse;
|
||||
|
||||
if (aValue) {
|
||||
e->mRawValue = *aValue;
|
||||
}
|
||||
|
||||
e->SetTrusted(trusted);
|
||||
|
||||
return e.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<BluetoothGattAttributeEvent>
|
||||
BluetoothGattAttributeEvent::Constructor(
|
||||
const GlobalObject& aGlobal,
|
||||
const nsAString& aType,
|
||||
const BluetoothGattAttributeEventInit& aEventInitDict,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<EventTarget> owner = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
|
||||
nsRefPtr<BluetoothGattAttributeEvent> e =
|
||||
Constructor(owner, aType, aEventInitDict.mAddress,
|
||||
aEventInitDict.mRequestId, aEventInitDict.mCharacteristic,
|
||||
aEventInitDict.mDescriptor, nullptr,
|
||||
aEventInitDict.mNeedResponse, aEventInitDict.mBubbles,
|
||||
aEventInitDict.mCancelable);
|
||||
|
||||
if (!aEventInitDict.mValue.IsNull()) {
|
||||
const auto& value = aEventInitDict.mValue.Value();
|
||||
value.ComputeLengthAndData();
|
||||
e->mValue = ArrayBuffer::Create(aGlobal.Context(),
|
||||
value.Length(),
|
||||
value.Data());
|
||||
|
||||
if (!e->mValue) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return e.forget();
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothGattAttributeEvent::GetAddress(nsString& aRetVal) const
|
||||
{
|
||||
aRetVal = mAddress;
|
||||
}
|
||||
|
||||
int32_t
|
||||
BluetoothGattAttributeEvent::RequestId() const
|
||||
{
|
||||
return mRequestId;
|
||||
}
|
||||
|
||||
BluetoothGattCharacteristic*
|
||||
BluetoothGattAttributeEvent::GetCharacteristic() const
|
||||
{
|
||||
return mCharacteristic;
|
||||
}
|
||||
|
||||
BluetoothGattDescriptor*
|
||||
BluetoothGattAttributeEvent::GetDescriptor() const
|
||||
{
|
||||
return mDescriptor;
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothGattAttributeEvent::GetValue(
|
||||
JSContext* cx, JS::MutableHandle<JSObject*> aValue, ErrorResult& aRv)
|
||||
{
|
||||
if (!mValue) {
|
||||
mValue = ArrayBuffer::Create(
|
||||
cx, this, mRawValue.Length(), mRawValue.Elements());
|
||||
|
||||
if (!mValue) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
mRawValue.Clear();
|
||||
}
|
||||
|
||||
JS::ExposeObjectToActiveJS(mValue);
|
||||
aValue.set(mValue);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothGattAttributeEvent::NeedResponse() const
|
||||
{
|
||||
return mNeedResponse;
|
||||
}
|
81
dom/bluetooth/common/webapi/BluetoothGattAttributeEvent.h
Normal file
81
dom/bluetooth/common/webapi/BluetoothGattAttributeEvent.h
Normal file
@ -0,0 +1,81 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_bluetooth_BluetoothGattAttributeEvent_h
|
||||
#define mozilla_dom_bluetooth_BluetoothGattAttributeEvent_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/BluetoothGattAttributeEventBinding.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
|
||||
struct JSContext;
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothGattAttributeEvent final : public Event
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
|
||||
BluetoothGattAttributeEvent, Event)
|
||||
protected:
|
||||
virtual ~BluetoothGattAttributeEvent();
|
||||
explicit BluetoothGattAttributeEvent(EventTarget* aOwner);
|
||||
|
||||
nsString mAddress;
|
||||
int32_t mRequestId;
|
||||
nsRefPtr<BluetoothGattCharacteristic> mCharacteristic;
|
||||
nsRefPtr<BluetoothGattDescriptor> mDescriptor;
|
||||
JS::Heap<JSObject*> mValue;
|
||||
bool mNeedResponse;
|
||||
|
||||
public:
|
||||
virtual
|
||||
JSObject* WrapObjectInternal(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
static already_AddRefed<BluetoothGattAttributeEvent>
|
||||
Constructor(EventTarget* aOwner,
|
||||
const nsAString& aType,
|
||||
const nsAString& aAddress,
|
||||
int32_t aRequestId,
|
||||
BluetoothGattCharacteristic* aCharacteristic,
|
||||
BluetoothGattDescriptor* aDescriptor,
|
||||
const nsTArray<uint8_t>* aValue,
|
||||
bool aNeedResponse,
|
||||
bool aBubbles,
|
||||
bool aCancelable);
|
||||
|
||||
static already_AddRefed<BluetoothGattAttributeEvent>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aType,
|
||||
const BluetoothGattAttributeEventInit& aEventInitDict,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void GetAddress(nsString& aRetVal) const;
|
||||
|
||||
int32_t RequestId() const;
|
||||
|
||||
BluetoothGattCharacteristic* GetCharacteristic() const;
|
||||
|
||||
BluetoothGattDescriptor* GetDescriptor() const;
|
||||
|
||||
void
|
||||
GetValue(JSContext* cx,
|
||||
JS::MutableHandle<JSObject*> aValue,
|
||||
ErrorResult& aRv);
|
||||
|
||||
bool NeedResponse() const;
|
||||
|
||||
private:
|
||||
nsTArray<uint8_t> mRawValue;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_BluetoothGattAttributeEvent_h
|
@ -32,6 +32,7 @@ class BluetoothGattCharacteristic final : public nsISupports
|
||||
, public nsWrapperCache
|
||||
, public BluetoothSignalObserver
|
||||
{
|
||||
friend class BluetoothGattServer;
|
||||
friend class BluetoothGattService;
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
@ -114,6 +115,11 @@ public:
|
||||
|
||||
uint16_t GetHandleCount() const;
|
||||
|
||||
const nsTArray<uint8_t>& GetValue() const
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
|
@ -32,6 +32,7 @@ class BluetoothGattDescriptor final : public nsISupports
|
||||
, public nsWrapperCache
|
||||
, public BluetoothSignalObserver
|
||||
{
|
||||
friend class BluetoothGattServer;
|
||||
friend class BluetoothGattCharacteristic;
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
@ -88,6 +89,11 @@ public:
|
||||
return sHandleCount;
|
||||
}
|
||||
|
||||
const nsTArray<uint8_t>& GetValue() const
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
@ -228,4 +234,25 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Explicit Specialization of Function Templates
|
||||
*
|
||||
* Allows customizing the template code for a given set of template arguments.
|
||||
* With this function template, nsTArray can handle comparison between
|
||||
* 'nsRefPtr<BluetoothGattDescriptor>' and 'BluetoothAttributeHandle'
|
||||
* properly, including IndexOf() and Contains();
|
||||
*/
|
||||
template <>
|
||||
class nsDefaultComparator <
|
||||
nsRefPtr<mozilla::dom::bluetooth::BluetoothGattDescriptor>,
|
||||
mozilla::dom::bluetooth::BluetoothAttributeHandle> {
|
||||
public:
|
||||
bool Equals(
|
||||
const nsRefPtr<mozilla::dom::bluetooth::BluetoothGattDescriptor>& aDesc,
|
||||
const mozilla::dom::bluetooth::BluetoothAttributeHandle& aHandle) const
|
||||
{
|
||||
return aDesc->GetDescriptorHandle() == aHandle;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // mozilla_dom_bluetooth_BluetoothGattDescriptor_h
|
||||
|
@ -10,6 +10,9 @@
|
||||
#include "BluetoothService.h"
|
||||
#include "BluetoothUtils.h"
|
||||
#include "mozilla/dom/BluetoothStatusChangedEvent.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothGattAttributeEvent.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothGattCharacteristic.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothGattService.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
|
||||
using namespace mozilla;
|
||||
@ -176,6 +179,69 @@ BluetoothGattServer::HandleDescriptorHandleUpdated(
|
||||
descriptorHandle);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothGattServer::HandleReadWriteRequest(const BluetoothValue& aValue,
|
||||
const nsAString& aEventName)
|
||||
{
|
||||
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
|
||||
const InfallibleTArray<BluetoothNamedValue>& arr =
|
||||
aValue.get_ArrayOfBluetoothNamedValue();
|
||||
|
||||
MOZ_ASSERT(arr.Length() == 5 &&
|
||||
arr[0].value().type() == BluetoothValue::Tint32_t &&
|
||||
arr[1].value().type() == BluetoothValue::TBluetoothAttributeHandle &&
|
||||
arr[2].value().type() == BluetoothValue::TnsString &&
|
||||
arr[3].value().type() == BluetoothValue::Tbool &&
|
||||
arr[4].value().type() == BluetoothValue::TArrayOfuint8_t);
|
||||
|
||||
int32_t requestId = arr[0].value().get_int32_t();
|
||||
BluetoothAttributeHandle handle =
|
||||
arr[1].value().get_BluetoothAttributeHandle();
|
||||
nsString address = arr[2].value().get_nsString();
|
||||
bool needResponse = arr[3].value().get_bool();
|
||||
nsTArray<uint8_t> value;
|
||||
value = arr[4].value().get_ArrayOfuint8_t();
|
||||
|
||||
// Find the target characteristic or descriptor from the given handle
|
||||
nsRefPtr<BluetoothGattCharacteristic> characteristic = nullptr;
|
||||
nsRefPtr<BluetoothGattDescriptor> descriptor = nullptr;
|
||||
for (uint32_t i = 0; i < mServices.Length(); i++) {
|
||||
for (uint32_t j = 0; j < mServices[i]->mCharacteristics.Length(); j++) {
|
||||
nsRefPtr<BluetoothGattCharacteristic> currentChar =
|
||||
mServices[i]->mCharacteristics[j];
|
||||
|
||||
if (handle == currentChar->GetCharacteristicHandle()) {
|
||||
characteristic = currentChar;
|
||||
break;
|
||||
}
|
||||
|
||||
size_t index = currentChar->mDescriptors.IndexOf(handle);
|
||||
if (index != currentChar->mDescriptors.NoIndex) {
|
||||
descriptor = currentChar->mDescriptors[index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(characteristic || descriptor)) {
|
||||
BT_WARNING("Wrong handle: no matched characteristic or descriptor");
|
||||
return;
|
||||
}
|
||||
|
||||
// Save the request information for sending the response later
|
||||
RequestData data(handle,
|
||||
characteristic,
|
||||
descriptor);
|
||||
mRequestMap.Put(requestId, &data);
|
||||
|
||||
nsRefPtr<BluetoothGattAttributeEvent> event =
|
||||
BluetoothGattAttributeEvent::Constructor(
|
||||
this, aEventName, address, requestId, characteristic, descriptor,
|
||||
&value, needResponse, false /* Bubble */, false /* Cancelable*/);
|
||||
|
||||
DispatchTrustedEvent(event);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothGattServer::Notify(const BluetoothSignal& aData)
|
||||
{
|
||||
@ -195,6 +261,10 @@ BluetoothGattServer::Notify(const BluetoothSignal& aData)
|
||||
HandleCharacteristicHandleUpdated(v);
|
||||
} else if (aData.name().EqualsLiteral("DescriptorHandleUpdated")) {
|
||||
HandleDescriptorHandleUpdated(v);
|
||||
} else if (aData.name().EqualsLiteral("ReadRequested")) {
|
||||
HandleReadWriteRequest(v, NS_LITERAL_STRING(ATTRIBUTE_READ_REQUEST));
|
||||
} else if (aData.name().EqualsLiteral("WriteRequested")) {
|
||||
HandleReadWriteRequest(v, NS_LITERAL_STRING(ATTRIBUTE_WRITE_REQUEST));
|
||||
} else {
|
||||
BT_WARNING("Not handling GATT signal: %s",
|
||||
NS_ConvertUTF16toUTF8(aData.name()).get());
|
||||
@ -219,8 +289,9 @@ void
|
||||
BluetoothGattServer::Invalidate()
|
||||
{
|
||||
mValid = false;
|
||||
mServices.Clear();
|
||||
mPendingService = nullptr;
|
||||
mServices.Clear();
|
||||
mRequestMap.Clear();
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
@ -708,3 +779,59 @@ BluetoothGattServer::RemoveService(BluetoothGattService& aService,
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
BluetoothGattServer::SendResponse(const nsAString& aAddress,
|
||||
uint16_t aStatus,
|
||||
int32_t aRequestId,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
|
||||
if (!global) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
|
||||
|
||||
BT_ENSURE_TRUE_REJECT(mValid, promise, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
RequestData* requestData;
|
||||
mRequestMap.Get(aRequestId, &requestData);
|
||||
BT_ENSURE_TRUE_REJECT(requestData, promise, NS_ERROR_UNEXPECTED);
|
||||
|
||||
BluetoothGattResponse response;
|
||||
memset(&response, 0, sizeof(response));
|
||||
response.mHandle = requestData->mHandle;
|
||||
|
||||
if (requestData->mCharacteristic) {
|
||||
const nsTArray<uint8_t>& value = requestData->mCharacteristic->GetValue();
|
||||
response.mLength = value.Length();
|
||||
memcpy(&response.mValue, value.Elements(), response.mLength);
|
||||
} else if (requestData->mDescriptor) {
|
||||
const nsTArray<uint8_t>& value = requestData->mDescriptor->GetValue();
|
||||
response.mLength = value.Length();
|
||||
memcpy(&response.mValue, value.Elements(), response.mLength);
|
||||
} else {
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"There should be at least one characteristic or descriptor in the "
|
||||
"request data.");
|
||||
|
||||
promise->MaybeReject(NS_ERROR_INVALID_ARG);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
BT_ENSURE_TRUE_REJECT(bs, promise, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
bs->GattServerSendResponseInternal(
|
||||
mAppUuid,
|
||||
aAddress,
|
||||
aStatus,
|
||||
aRequestId,
|
||||
response,
|
||||
new BluetoothVoidReplyRunnable(nullptr, promise));
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothGattService.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
@ -46,6 +47,8 @@ public:
|
||||
* Event Handlers
|
||||
***************************************************************************/
|
||||
IMPL_EVENT_HANDLER(connectionstatechanged);
|
||||
IMPL_EVENT_HANDLER(attributereadreq);
|
||||
IMPL_EVENT_HANDLER(attributewritereq);
|
||||
|
||||
/****************************************************************************
|
||||
* Methods (Web API Implementation)
|
||||
@ -59,6 +62,11 @@ public:
|
||||
already_AddRefed<Promise> RemoveService(BluetoothGattService& aService,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> SendResponse(const nsAString& aAddress,
|
||||
uint16_t aStatus,
|
||||
int32_t aRequestId,
|
||||
ErrorResult& aRv);
|
||||
|
||||
/****************************************************************************
|
||||
* Others
|
||||
***************************************************************************/
|
||||
@ -102,12 +110,29 @@ private:
|
||||
friend class AddServiceTask;
|
||||
friend class RemoveServiceTask;
|
||||
|
||||
struct RequestData
|
||||
{
|
||||
RequestData(const BluetoothAttributeHandle& aHandle,
|
||||
BluetoothGattCharacteristic* aCharacteristic,
|
||||
BluetoothGattDescriptor* aDescriptor)
|
||||
: mHandle(aHandle)
|
||||
, mCharacteristic(aCharacteristic)
|
||||
, mDescriptor(aDescriptor)
|
||||
{ }
|
||||
|
||||
BluetoothAttributeHandle mHandle;
|
||||
nsRefPtr<BluetoothGattCharacteristic> mCharacteristic;
|
||||
nsRefPtr<BluetoothGattDescriptor> mDescriptor;
|
||||
};
|
||||
|
||||
void HandleServerRegistered(const BluetoothValue& aValue);
|
||||
void HandleServerUnregistered(const BluetoothValue& aValue);
|
||||
void HandleConnectionStateChanged(const BluetoothValue& aValue);
|
||||
void HandleServiceHandleUpdated(const BluetoothValue& aValue);
|
||||
void HandleCharacteristicHandleUpdated(const BluetoothValue& aValue);
|
||||
void HandleDescriptorHandleUpdated(const BluetoothValue& aValue);
|
||||
void HandleReadWriteRequest(const BluetoothValue& aValue,
|
||||
const nsAString& aString);
|
||||
|
||||
/****************************************************************************
|
||||
* Variables
|
||||
@ -136,6 +161,11 @@ private:
|
||||
* The service that is being added to this server.
|
||||
*/
|
||||
nsRefPtr<BluetoothGattService> mPendingService;
|
||||
|
||||
/**
|
||||
* Map request information from the request ID.
|
||||
*/
|
||||
nsClassHashtable<nsUint32HashKey, RequestData> mRequestMap;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
@ -44,6 +44,14 @@ struct ParamTraits<mozilla::dom::bluetooth::BluetoothGattWriteType>
|
||||
mozilla::dom::bluetooth::GATT_WRITE_TYPE_END_GUARD>
|
||||
{ };
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::dom::bluetooth::BluetoothGattAuthReq>
|
||||
: public ContiguousEnumSerializer<
|
||||
mozilla::dom::bluetooth::BluetoothGattAuthReq,
|
||||
mozilla::dom::bluetooth::GATT_AUTH_REQ_NONE,
|
||||
mozilla::dom::bluetooth::GATT_AUTH_REQ_END_GUARD>
|
||||
{ };
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::dom::bluetooth::BluetoothUuid>
|
||||
{
|
||||
@ -156,6 +164,40 @@ struct ParamTraits<mozilla::dom::bluetooth::BluetoothAttributeHandle>
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::dom::bluetooth::BluetoothGattResponse>
|
||||
{
|
||||
typedef mozilla::dom::bluetooth::BluetoothGattResponse paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mHandle);
|
||||
WriteParam(aMsg, aParam.mOffset);
|
||||
WriteParam(aMsg, aParam.mLength);
|
||||
WriteParam(aMsg, aParam.mAuthReq);
|
||||
for (uint16_t i = 0; i < aParam.mLength; i++) {
|
||||
WriteParam(aMsg, aParam.mValue[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
if (!ReadParam(aMsg, aIter, &(aResult->mHandle)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mOffset)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mLength)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mAuthReq))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i < aResult->mLength; i++) {
|
||||
if (!ReadParam(aMsg, aIter, &(aResult->mValue[i]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace IPC
|
||||
|
||||
#endif // mozilla_dom_bluetooth_ipc_BluetoothMessageUtils_h
|
||||
|
@ -316,6 +316,8 @@ BluetoothParent::RecvPBluetoothRequestConstructor(
|
||||
return actor->DoRequest(aRequest.get_GattServerStartServiceRequest());
|
||||
case Request::TGattServerStopServiceRequest:
|
||||
return actor->DoRequest(aRequest.get_GattServerStopServiceRequest());
|
||||
case Request::TGattServerSendResponseRequest:
|
||||
return actor->DoRequest(aRequest.get_GattServerSendResponseRequest());
|
||||
default:
|
||||
MOZ_CRASH("Unknown type!");
|
||||
}
|
||||
@ -1157,3 +1159,22 @@ BluetoothRequestParent::DoRequest(
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothRequestParent::DoRequest(
|
||||
const GattServerSendResponseRequest& aRequest)
|
||||
{
|
||||
MOZ_ASSERT(mService);
|
||||
MOZ_ASSERT(mRequestType ==
|
||||
Request::TGattServerSendResponseRequest);
|
||||
|
||||
mService->GattServerSendResponseInternal(
|
||||
aRequest.appUuid(),
|
||||
aRequest.address(),
|
||||
aRequest.status(),
|
||||
aRequest.requestId(),
|
||||
aRequest.response(),
|
||||
mReplyRunnable.get());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -300,6 +300,9 @@ protected:
|
||||
|
||||
bool
|
||||
DoRequest(const GattServerStopServiceRequest& aRequest);
|
||||
|
||||
bool
|
||||
DoRequest(const GattServerSendResponseRequest& aRequest);
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
@ -715,6 +715,20 @@ BluetoothServiceChildProcess::GattServerStopServiceInternal(
|
||||
GattServerStopServiceRequest(nsString(aAppUuid), aServiceHandle));
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceChildProcess::GattServerSendResponseInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
uint16_t aStatus,
|
||||
int32_t aRequestId,
|
||||
const BluetoothGattResponse& aRsp,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
SendRequest(aRunnable,
|
||||
GattServerSendResponseRequest(
|
||||
nsString(aAppUuid), nsString(aAddress), aStatus, aRequestId, aRsp));
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothServiceChildProcess::HandleStartup()
|
||||
{
|
||||
|
@ -364,6 +364,15 @@ public:
|
||||
const BluetoothAttributeHandle& aServiceHandle,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
virtual void
|
||||
GattServerSendResponseInternal(
|
||||
const nsAString& aAppUuid,
|
||||
const nsAString& aAddress,
|
||||
uint16_t aStatus,
|
||||
int32_t aRequestId,
|
||||
const BluetoothGattResponse& aRsp,
|
||||
BluetoothReplyRunnable* aRunnable) override;
|
||||
|
||||
protected:
|
||||
BluetoothServiceChildProcess();
|
||||
virtual ~BluetoothServiceChildProcess();
|
||||
|
@ -14,6 +14,8 @@ using mozilla::dom::bluetooth::BluetoothGattCharProp
|
||||
from "mozilla/dom/bluetooth/BluetoothCommon.h";
|
||||
using mozilla::dom::bluetooth::BluetoothGattId
|
||||
from "mozilla/dom/bluetooth/BluetoothCommon.h";
|
||||
using mozilla::dom::bluetooth::BluetoothGattResponse
|
||||
from "mozilla/dom/bluetooth/BluetoothCommon.h";
|
||||
using mozilla::dom::bluetooth::BluetoothGattServiceId
|
||||
from "mozilla/dom/bluetooth/BluetoothCommon.h";
|
||||
using mozilla::dom::bluetooth::BluetoothGattWriteType
|
||||
|
@ -359,6 +359,15 @@ struct GattServerStopServiceRequest
|
||||
BluetoothAttributeHandle serviceHandle;
|
||||
};
|
||||
|
||||
struct GattServerSendResponseRequest
|
||||
{
|
||||
nsString appUuid;
|
||||
nsString address;
|
||||
uint16_t status;
|
||||
int32_t requestId;
|
||||
BluetoothGattResponse response;
|
||||
};
|
||||
|
||||
union Request
|
||||
{
|
||||
GetAdaptersRequest;
|
||||
@ -419,6 +428,7 @@ union Request
|
||||
GattServerRemoveServiceRequest;
|
||||
GattServerStartServiceRequest;
|
||||
GattServerStopServiceRequest;
|
||||
GattServerSendResponseRequest;
|
||||
};
|
||||
|
||||
protocol PBluetooth
|
||||
|
@ -29,6 +29,7 @@ if CONFIG['MOZ_B2G_BT']:
|
||||
'common/webapi/BluetoothDevice.cpp',
|
||||
'common/webapi/BluetoothDiscoveryHandle.cpp',
|
||||
'common/webapi/BluetoothGatt.cpp',
|
||||
'common/webapi/BluetoothGattAttributeEvent.cpp',
|
||||
'common/webapi/BluetoothGattCharacteristic.cpp',
|
||||
'common/webapi/BluetoothGattDescriptor.cpp',
|
||||
'common/webapi/BluetoothGattServer.cpp',
|
||||
@ -141,6 +142,7 @@ EXPORTS.mozilla.dom.bluetooth += [
|
||||
'common/webapi/BluetoothDevice.h',
|
||||
'common/webapi/BluetoothDiscoveryHandle.h',
|
||||
'common/webapi/BluetoothGatt.h',
|
||||
'common/webapi/BluetoothGattAttributeEvent.h',
|
||||
'common/webapi/BluetoothGattCharacteristic.h',
|
||||
'common/webapi/BluetoothGattDescriptor.h',
|
||||
'common/webapi/BluetoothGattServer.h',
|
||||
|
@ -64,6 +64,10 @@ const kEventConstructors = {
|
||||
return new BluetoothDeviceEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
BluetoothGattAttributeEvent: { create: function (aName, aProps) {
|
||||
return new BluetoothGattAttributeEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
BluetoothGattCharacteristicEvent: { create: function (aName, aProps) {
|
||||
return new BluetoothGattCharacteristicEvent(aName, aProps);
|
||||
},
|
||||
|
@ -200,6 +200,9 @@ var interfaceNamesInGlobalScope =
|
||||
{name: "BluetoothDiscoveryHandle", b2g: true, permission: ["bluetooth"]},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "BluetoothGatt", b2g: true, permission: ["bluetooth"]},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "BluetoothGattAttributeEvent", b2g: true,
|
||||
permission: ["bluetooth"]},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "BluetoothGattCharacteristic", b2g: true,
|
||||
permission: ["bluetooth"]},
|
||||
|
33
dom/webidl/BluetoothGattAttributeEvent.webidl
Normal file
33
dom/webidl/BluetoothGattAttributeEvent.webidl
Normal file
@ -0,0 +1,33 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
[Constructor(DOMString type,
|
||||
optional BluetoothGattAttributeEventInit eventInitDict),
|
||||
CheckAnyPermissions="bluetooth"]
|
||||
interface BluetoothGattAttributeEvent : Event
|
||||
{
|
||||
readonly attribute DOMString address;
|
||||
readonly attribute long requestId;
|
||||
readonly attribute BluetoothGattCharacteristic? characteristic;
|
||||
readonly attribute BluetoothGattDescriptor? descriptor;
|
||||
[Throws]
|
||||
readonly attribute ArrayBuffer? value;
|
||||
readonly attribute boolean needResponse;
|
||||
};
|
||||
|
||||
dictionary BluetoothGattAttributeEventInit : EventInit
|
||||
{
|
||||
DOMString address = "";
|
||||
long requestId = 0;
|
||||
BluetoothGattCharacteristic? characteristic = null;
|
||||
BluetoothGattDescriptor? descriptor = null;
|
||||
/**
|
||||
* Note that the passed-in value will be copied by the event constructor
|
||||
* here instead of storing the reference.
|
||||
*/
|
||||
ArrayBuffer? value = null;
|
||||
boolean needResponse = true;
|
||||
};
|
@ -13,6 +13,10 @@ interface BluetoothGattServer : EventTarget
|
||||
// Fired when a remote device has been connected/disconnected
|
||||
attribute EventHandler onconnectionstatechanged;
|
||||
|
||||
// Fired when a remote BLE client send a read/write request
|
||||
attribute EventHandler onattributereadreq;
|
||||
attribute EventHandler onattributewritereq;
|
||||
|
||||
/**
|
||||
* Connect/Disconnect to the remote BLE device with the target address.
|
||||
*
|
||||
@ -41,4 +45,11 @@ interface BluetoothGattServer : EventTarget
|
||||
*/
|
||||
[NewObject]
|
||||
Promise<void> removeService(BluetoothGattService service);
|
||||
|
||||
/**
|
||||
* Send a read/write response to a remote BLE client
|
||||
*/
|
||||
[NewObject]
|
||||
Promise<void> sendResponse(
|
||||
DOMString address, unsigned short status, long requestId);
|
||||
};
|
||||
|
@ -683,6 +683,7 @@ if CONFIG['MOZ_B2G_BT']:
|
||||
'BluetoothDevice.webidl',
|
||||
'BluetoothDiscoveryHandle.webidl',
|
||||
'BluetoothGatt.webidl',
|
||||
'BluetoothGattAttributeEvent.webidl',
|
||||
'BluetoothGattCharacteristic.webidl',
|
||||
'BluetoothGattDescriptor.webidl',
|
||||
'BluetoothGattServer.webidl',
|
||||
|
Loading…
Reference in New Issue
Block a user