diff --git a/index.bs b/index.bs
index 8e15a42..864ea96 100644
--- a/index.bs
+++ b/index.bs
@@ -4102,6 +4102,30 @@ slots described in the following table:
has been removed or otherwise invalidated.
+
@@ -4146,18 +4170,40 @@ readValue() method, when invoked, MUST run the following steps:
"{{InvalidStateError}}" {{DOMException}}.
1. Return a |gatt|-[=connection-checking wrapper=] around [=a new promise=]
|promise| and run the following steps [=in parallel=]:
- 1. If the UA is currently using the Bluetooth system, it MAY [=queue a
- global task=] on the [=Bluetooth task source=] given |global| to
- [=reject=] |promise| with a "{{NetworkError}}" {{DOMException}} and
- abort these steps.
+ 1. If |global|'s [=Window/navigable=]'s
+ [=navigable/top-level traversable=]'s
simulated Bluetooth adapter
+ is not empty, run the following steps:
+ 1. If [=this=].{{[[automatedDescriptorReadResponse]]}} is not `"not-expected"`,
+ [=queue a global task=] on the [=Bluetooth task source=] given |global| to
+ [=reject=] |promise| with a "{{InvalidStateError}}" {{DOMException}} and abort
+ these steps.
+ 1. [=Trigger a simulated descriptor event=] given |global|'s
+ [=Window/navigable=], [=this=].{{BluetoothRemoteGATTServer/device}},
+ |descriptor|, and `read`.
+ 1. Set [=this=].{{[[automatedDescriptorReadResponse]]}} to `"expected"`,
+ and wait for it to change.
+ 1. Let |response| be [=this=].{{[[automatedDescriptorReadResponse]]}}.
+ 1. Set [=this=].{{[[automatedDescriptorReadResponse]]}} to `"not-expected"`.
+ 1. If |response| is not `0`, do the following sub-steps:
+ 1. [=Queue a global task=] on the [=Bluetooth task source=] given
+ |global| to [=reject=] |promise| with a "{{NetworkError}}"
+ {{DOMException}} and abort these steps.
+ 1. Otherwise, let |buffer| be a [=new=] {{ArrayBuffer}} containing
+ [=this=].{{[[automatedDescriptorReadResponseData]]}}.
+ 1. Otherwise, run the following steps:
+ 1. If the UA is currently using the Bluetooth system, it MAY [=queue a
+ global task=] on the [=Bluetooth task source=] given |global| to
+ [=reject=] |promise| with a "{{NetworkError}}" {{DOMException}} and
+ abort these steps.
- Issue(188): Implementations may be able to avoid this {{NetworkError}},
- but for now sites need to serialize their use of this API
- and/or give the user a way to retry failed operations.
- 1. Use either the [=Read Characteristic Descriptors=] or the [=Read Long
- Characteristic Descriptors=] sub-procedure to retrieve the value of
- |descriptor|. Handle errors as described in
-
.
+ Issue(188): Implementations may be able to avoid this {{NetworkError}},
+ but for now sites need to serialize their use of this API
+ and/or give the user a way to retry failed operations.
+ 1. Use either the [=Read Characteristic Descriptors=] or the [=Read Long
+ Characteristic Descriptors=] sub-procedure to retrieve the value of
+ |descriptor| and let |buffer| be a [=new=] {{ArrayBuffer}} holding the
+ retrieved value. Handle errors as described in
+
.
1. [=Queue a global task=] on the [=Bluetooth task source=] given |global|
to perform the following steps:
1. If |promise| is not in |gatt|.{{[[activeAlgorithms]]}}, [=reject=]
@@ -4165,8 +4211,7 @@ readValue() method, when invoked, MUST run the following steps:
these steps.
1. If the sub-procedure above returned an error, [=reject=] |promise|
with that error and abort these steps.
- 1. Let |buffer| be a [=new=] {{ArrayBuffer}} holding the retrieved
- value, and assign a [=new=] {{DataView}} created with |buffer| to
+ 1. Assign a [=new=] {{DataView}} created with |buffer| to
[=this=].{{BluetoothRemoteGATTDescriptor/value}}.
1. [=Resolve=] |promise| with
[=this=].{{BluetoothRemoteGATTDescriptor/value}}.
@@ -4194,18 +4239,37 @@ following steps:
"{{InvalidStateError}}" {{DOMException}}.
1. Return a |gatt|-[=connection-checking wrapper=] around [=a new promise=]
|promise| and run the following steps [=in parallel=].
- 1. If the UA is currently using the Bluetooth system, it MAY [=queue a
- global task=] on the [=Bluetooth task source=] given |global| to
- [=reject=] |promise| with a "{{NetworkError}}" {{DOMException}} and
- abort these steps.
+ 1. If |global|'s [=Window/navigable=]'s
+ [=navigable/top-level traversable=]'s
simulated Bluetooth adapter
+ is not empty, run the following steps:
+ 1. If [=this=].{{[[automatedDescriptorWriteResponse]]}} is not `"not-expected"`,
+ [=queue a global task=] on the [=Bluetooth task source=] given |global| to
+ [=reject=] |promise| with a "{{InvalidStateError}}" {{DOMException}} and abort
+ these steps.
+ 1. [=Trigger a simulated descriptor event=] given |global|'s
+ [=Window/navigable=], [=this=].{{BluetoothRemoteGATTServer/device}},
+ |descriptor|, `write`, and |bytes|.
+ 1. Set [=this=].{{[[automatedDescriptorWriteResponse]]}} to `"expected"`,
+ and wait for it to change.
+ 1. Let |response| be [=this=].{{[[automatedDescriptorWriteResponse]]}}.
+ 1. Set [=this=].{{[[automatedDescriptorWriteResponse]]}} to `"not-expected"`.
+ 1. If |response| is not `0`, do the following sub-steps:
+ 1. [=Queue a global task=] on the [=Bluetooth task source=] given
+ |global| to [=reject=] |promise| with a "{{NetworkError}}"
+ {{DOMException}} and abort these steps.
+ 1. Otherwise, run the following steps:
+ 1. If the UA is currently using the Bluetooth system, it MAY [=queue a
+ global task=] on the [=Bluetooth task source=] given |global| to
+ [=reject=] |promise| with a "{{NetworkError}}" {{DOMException}} and
+ abort these steps.
- Issue(188): Implementations may be able to avoid this {{NetworkError}},
- but for now sites need to serialize their use of this API
- and/or give the user a way to retry failed operations.
- 1. Use either the [=Write Characteristic Descriptors=] or the [=Write Long
- Characteristic Descriptors=] sub-procedure to write |bytes| to
- |descriptor|. Handle errors as described in
-
.
+ Issue(188): Implementations may be able to avoid this {{NetworkError}},
+ but for now sites need to serialize their use of this API
+ and/or give the user a way to retry failed operations.
+ 1. Use either the [=Write Characteristic Descriptors=] or the [=Write Long
+ Characteristic Descriptors=] sub-procedure to write |bytes| to
+ |descriptor|. Handle errors as described in
+
.
1. [=Queue a global task=] on the [=Bluetooth task source=] given |global|
to perform the following steps:
1. If |promise| is not in |gatt|.{{[[activeAlgorithms]]}}, [=reject=]
@@ -5139,11 +5203,15 @@ is an
ordered map of Bluetooth
UUID strings to
simulated GATT c
A simulated GATT characteristic is a software defined [=Characteristic=] that belongs to a
simulated GATT service, has a property of
UUID, a property of
Characteristic Properties,
-and is known-present in the
Bluetooth cache.
+is known-present in the
Bluetooth cache, and has a
simulated GATT descriptor mapping, which
+is an
ordered map of Bluetooth
UUID strings to
simulated GATT descriptors.
Simulated GATT characteristic properties are software defined [=Characteristic Properties=] that belong to a
simulated GATT characteristic and are known-present in the
Bluetooth cache.
+A
simulated GATT descriptor is a software defined [=Descriptor=] that belongs to a
+
simulated GATT characteristic, has a property of
UUID, and is known-present in the
Bluetooth cache.
+
Issue: CDDL snippetes use the "text" type instead of
"browsingContext.BrowsingContext" to allow indepedent programmatic
processing of CDDL snippets. Currently, other modules cannot be
@@ -5757,7 +5825,7 @@ The [=remote end steps=] with command parameters |params| are:
and add a mapping from |simulatedGattService| to the resulting {{Promise}} in
|simulatedDeviceInstance|.{{[[context]]}}.{{Bluetooth/[[attributeInstanceMap]]}}.
1. Return [=success=] with data `null`.
-1. Else if |params|[`"type"`] is `"remove"`:
+1. If |params|[`"type"`] is `"remove"`:
1. If |serviceMapping|[|uuid|] [=map/exists=], let |simulatedGattService| be |serviceMapping|[|uuid|].
1. Otherwise, return [=error=] with [=error code=] [=invalid element state=].
1. Remove |simulatedGattService| from |simulatedDeviceInstance|.{{[[context]]}}.{{Bluetooth/[[attributeInstanceMap]]}}.
@@ -5867,7 +5935,7 @@ The [=remote end steps=] with command parameters |params| are:
and add a mapping from |simulatedGattCharacteristic| to the resulting {{Promise}} in
|simulatedDeviceInstance|.{{[[context]]}}.{{Bluetooth/[[attributeInstanceMap]]}}.
1. Return [=success=] with data `null`.
-1. Else if |params|[`"type"`] is `"remove"`:
+1. If |params|[`"type"`] is `"remove"`:
1. If |params|[`"characteristicProperties"`] [=map/exists=], return [=error=] with [=error code=] [=invalid argument=].
1. If |characteristicMapping|[|characteristicUuid|] [=map/exists=], let |simulatedGattCharacteristic|
be |characteristicMapping|[|characteristicUuid|].
@@ -6025,7 +6093,46 @@ bluetooth.SimulateDescriptorParameters = {
-Issue: TODO: Finish the algorithm of bluetooth.simulateDescriptor.
+1. Let |contextId| be |params|[`"context"`].
+1. Let |navigable| be the result of [=trying=] to [=get a navigable=] with |contextId|.
+1. Let |deviceAddress| be |params|[`"address"`].
+1. Let |simulatedBluetoothAdapter| be |navigable|'s
simulated Bluetooth adapter.
+1. If |simulatedBluetoothAdapter| is empty, return [=error=] with [=error code=] [=invalid argument=].
+1. Let |deviceMapping| be |simulatedBluetoothAdapter|'s
simulated Bluetooth device mapping.
+1. If |deviceMapping|[|deviceAddress|] [=map/exists=], let |simulatedDevice| be |deviceMapping|[|deviceAddress|].
+1. Otherwise, return [=error=] with [=error code=] [=invalid argument=].
+1. Let |simulatedDeviceInstance| be the result of
get the BluetoothDevice representing
+ |simulatedDevice| inside |navigable|'s
active window's
associated Navigator's
+ [=associated Bluetooth=].
+1. Let |serviceMapping| be |simulatedDevice|'s
simulated GATT service mapping.
+1. Let |serviceUuid| be |params|[`"serviceUuid"`].
+1. If |serviceMapping|[|serviceUuid|] [=map/exists=], let |simulatedService| be |serviceMapping|[|serviceUuid|].
+1. Otherwise, return [=error=] with [=error code=] [=invalid argument=].
+1. Let |characteristicMapping| be |simulatedService|'s
simulated GATT characteristic mapping.
+1. Let |characteristicUuid| be |params|[`"characteristicUuid"`].
+1. If |characteristicMapping|[|characteristicUuid|] [=map/exists=], let |simulatedCharacteristic| be
+ |characteristicMapping|[|characteristicUuid|].
+1. Otherwise, return [=error=] with [=error code=] [=invalid argument=].
+1. Let |descriptorMapping| be |simulatedCharacteristic|'s
simulated GATT descriptor mapping.
+1. Let |descriptorUuid| be |params|[`"descriptorUuid"`].
+1. If |params|[`"type"`] is `"add"`:
+ 1. If |descriptorMapping|[|descriptorUuid|] [=map/exists=], return [=error=] with
+ [=error code=] [=invalid element state=].
+ 1. Let |simulatedGattDescriptor| be a new
simulated GATT descriptor.
+ 1. Set |simulatedGattDescriptor|'s
UUID to |descriptorUuid|.
+ 1. Set |descriptorMapping|[|descriptorUuid|] to |simulatedGattDescriptor|.
+ 1.
Create a BluetoothRemoteGATTDescriptor representing |simulatedGattDescriptor|
+ and add a mapping from |simulatedGattDescriptor| to the resulting {{Promise}} in
+ |simulatedDeviceInstance|.{{[[context]]}}.{{Bluetooth/[[attributeInstanceMap]]}}.
+ 1. Return [=success=] with data `null`.
+1. If |params|[`"type"`] is `"remove"`:
+ 1. If |descriptorMapping|[|descriptorUuid|] [=map/exists=], let |simulatedGattDescriptor|
+ be |descriptorMapping|[|descriptorUuid|].
+ 1. Otherwise, return [=error=] with [=error code=] [=invalid element state=].
+ 1. Remove |simulatedGattDescriptor| from |simulatedDeviceInstance|.{{[[context]]}}.{{Bluetooth/[[attributeInstanceMap]]}}.
+ 1. Remove |descriptorUuid| from |descriptorMapping|.
+ 1. Return [=success=] with data `null`.
+1. Return [=error=] with [=error code=] [=invalid argument=].
@@ -6087,7 +6194,44 @@ bluetooth.SimulateDescriptorResponseParameters = {
-Issue: TODO: Finish the algorithm of bluetooth.simulateDescriptorResponse.
+1. Let |contextId| be |params|[`"context"`].
+1. Let |navigable| be the result of [=trying=] to [=get a navigable=] with |contextId|.
+1. Let |deviceAddress| be |params|[`"address"`].
+1. Let |simulatedBluetoothAdapter| be |navigable|'s
simulated Bluetooth adapter.
+1. If |simulatedBluetoothAdapter| is empty, return [=error=] with [=error code=] [=invalid argument=].
+1. Let |deviceMapping| be |simulatedBluetoothAdapter|'s
simulated Bluetooth device mapping.
+1. If |deviceMapping|[|deviceAddress|] [=map/exists=], let |simulatedDevice| be |deviceMapping|[|deviceAddress|].
+ Otherwise, return [=error=] with [=error code=] [=invalid argument=].
+1. Let |serviceMapping| be |simulatedDevice|'s
simulated GATT service mapping.
+1. Let |serviceUuid| be |params|[`"serviceUuid"`].
+1. If |serviceMapping|[|serviceUuid|] [=map/exists=], let |simulatedService| be |serviceMapping|[|serviceUuid|].
+1. Otherwise, return [=error=] with [=error code=] [=invalid argument=].
+1. Let |characteristicMapping| be |simulatedService|'s
simulated GATT characteristic mapping.
+1. Let |characteristicUuid| be |params|[`"characteristicUuid"`].
+1. If |characteristicMapping|[|characteristicUuid|] [=map/exists=], let |simulatedCharacteristic|
+ be |characteristicMapping|[|characteristicUuid|].
+1. Otherwise, return [=error=] with [=error code=] [=invalid element state=].
+1. Let |descriptorMapping| be |simulatedCharacteristic|'s
simulated GATT descriptor mapping.
+1. Let |descriptorUuid| be |params|[`"descriptorUuid"`].
+1. If |descriptorMapping|[|descriptorUuid|] [=map/exists=], let |simulatedDescriptor|
+ be |descriptorMapping|[|descriptorUuid|].
+1. Otherwise, return [=error=] with [=error code=] [=invalid element state=].
+1. Let |simulatedDeviceInstance| be the result of
get the BluetoothDevice representing
+ |simulatedDevice| inside |navigable|'s
active window's
associated Navigator's
+ [=associated Bluetooth=].
+1. Let |promise| be |simulatedDeviceInstance|.{{[[context]]}}.{{Bluetooth/[[attributeInstanceMap]]}}[|simulatedDescriptor|].
+1.
Upon fulfillment of |promise| with |descriptor|, run the following steps:
+ 1. If |params|[`"type"`] is `read`, run the following steps:
+ 1. If |descriptor|.{{[[automatedDescriptorReadResponse]]}} is `expected`,
+ set |descriptor|.{{[[automatedDescriptorReadResponse]]}} to |params|[`"code"`] and
+ |descriptor|.{{[[automatedDescriptorReadResponseData]]}} to [=a copy of the bytes held=]
+ by |params|[`"data"`].
+ 1. Otherwise, return [=error=] with [=error code=] [=invalid element state=].
+ 1. If |params|[`"type"`] is `write`, run the following steps:
+ 1. If |characteristic|.{{[[automatedDescriptorWriteResponse]]}} is `expected`,
+ set |characteristic|.{{[[automatedDescriptorWriteResponse]]}} to |params|[`"code"`].
+ 1. Otherwise, return [=error=] with [=error code=] [=invalid element state=].
+ 1. Otherwise, return [=error=] with [=error code=] [=invalid argument=].
@@ -6212,7 +6356,11 @@ To
trigger a simulated characteristic event given a [=navigable=] |n
1. Set |params|[`"serviceUuid"`] to |service|'s
UUID.
1. Set |params|[`"characteristicUuid"`] to |characteristic|'s
UUID.
1. Set |params|[`"type"`] to |type|.
- 1. If |type| is `write`, set |params|[`"data"`] to a [=new=] {{Uint8Array}} wrapping a [=new=] {{ArrayBuffer}} containing |bytes|.
+ 1. If |type| is `write`, run the following steps:
+ 1. Let |data| be an empty list.
+ 1. For each |byte| in |bytes|:
+ 1. Append |byte|'s [=byte/value=] to |data|.
+ 1. Set |params|[`"data"`] to |data|.
1. Let |body| be a [=map=] matching the
bluetooth.CharacteristicEventGenerated production, with the
params field set to |params|.
1. Let |relatedNavigables| be a [=/set=] containing |navigable|.
@@ -6243,7 +6391,31 @@ bluetooth.DescriptorEventGeneratedParameters = {
-Issue: TODO: Finish the algorithm of bluetooth.descriptorEventGenerated.
+To
trigger a simulated descriptor event given a [=navigable=] |navigable|, a {{BluetoothDevice}} |device|, a
+
simulated GATT descriptor |descriptor|,
string |type|, and an optional
byte sequence |bytes|:
+
+1. Let |navigableId| be |navigable|'s [=navigable id=].
+1. Let |params| be a [=map=] matching the
bluetooth.DescriptorEventGeneratedParameters production and run
+ the following steps:
+ 1. Set |params|[`"context"`] to |navigableId|.
+ 1. Set |params|[`"address"`] to |device|.{{[[representedDevice]]}}'s address.
+ 1. Let |characteristic| be the
simulated GATT characteristic containing |descriptor|.
+ 1. Let |service| be the
simulated GATT service containing |characteristic|.
+ 1. Set |params|[`"serviceUuid"`] to |service|'s
UUID.
+ 1. Set |params|[`"characteristicUuid"`] to |characteristic|'s
UUID.
+ 1. Set |params|[`"descriptorUuid"`] to |descriptor|'s
UUID.
+ 1. Set |params|[`"type"`] to |type|.
+ 1. If |type| is `write`, run the following steps:
+ 1. Let |data| be an empty list.
+ 1. For each |byte| in |bytes|:
+ 1. Append |byte|'s [=byte/value=] to |data|.
+ 1. Set |params|[`"data"`] to |data|.
+1. Let |body| be a [=map=] matching the
bluetooth.DescriptorEventGenerated production, with the
+
params field set to |params|.
+1. Let |relatedNavigables| be a [=/set=] containing |navigable|.
+1. For each |session| in the [=set of sessions for which an event is enabled=] given
+ "
bluetooth.descriptorEventGenerated" and |relatedNavigables|:
+ 1. [=Emit an event=] with |session| and |body|.