diff --git a/index.bs b/index.bs index 0852b43f..1f9b5c80 100644 --- a/index.bs +++ b/index.bs @@ -79,6 +79,10 @@ spec: BLUETOOTH-ASSIGNED text: Shortened Local Name; url: https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile# spec: ECMAScript; urlPrefix: https://tc39.github.io/ecma262/# + type: abstract-op + text: CanonicalNumericIndexString; url: sec-canonicalnumericindexstring + text: CreateDataProperty; url: sec-createdataproperty + text: IsInteger; url: sec-isinteger type: dfn text: current realm; url: current-realm text: fulfilled; url: sec-promise-objects @@ -86,6 +90,7 @@ spec: ECMAScript; urlPrefix: https://tc39.github.io/ecma262/# text: realm; url: sec-code-realms type: method text: Array.prototype.map; url: sec-array.prototype.map + text: [[OwnPropertyKeys]]; for: Object; url: sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys type: interface text: Array; url: sec-array-objects text: ArrayBuffer; url: sec-arraybuffer-constructor @@ -529,16 +534,22 @@ spec: html
- dictionary BluetoothRequestDeviceFilter {
+ dictionary BluetoothDataFilterInit {
+ BufferSource dataPrefix;
+ BufferSource mask;
+ };
+ dictionary BluetoothLEScanFilterInit {
sequence<BluetoothServiceUUID> services;
DOMString name;
DOMString namePrefix;
- unsigned short manufacturerId;
- BluetoothServiceUUID serviceDataUUID;
+ // Maps unsigned shorts to BluetoothDataFilters.
+ object manufacturerData;
+ // Maps BluetoothServiceUUIDs to BluetoothDataFilters.
+ object serviceData;
};
dictionary RequestDeviceOptions {
- sequence<BluetoothRequestDeviceFilter> filters;
+ sequence<BluetoothLEScanFilterInit> filters;
sequence<BluetoothServiceUUID> optionalServices = [];
boolean acceptAllDevices = false;
};
@@ -584,31 +595,37 @@ spec: html
+ Both Manufacturer Specific Data and Service Data
+ map a key to an array of bytes.
+ {{BluetoothDataFilterInit}} filters these arrays.
+ An array matches if it has a |prefix| such that
+ |prefix| & {{mask}} is equal to {{dataPrefix}} & {{mask}}.
+
- Note that this means that + Note that if a device changes its behavior significantly when it connects, for example by not advertising its identifying manufacturer data anymore and instead having the client discover some identifying GATT services, @@ -628,7 +645,7 @@ spec: html
After the user selects a device to pair with this origin,
the origin is allowed to access any service whose UUID was listed
- in the {{BluetoothRequestDeviceFilter/services}} list
+ in the {{BluetoothLEScanFilterInit/services}} list
in any element of options.filters
or in options.optionalServices.
- [{manufacturerId: 17}]
+ [{manufacturerData: {17: {}}}]
- [{serviceDataUUID: A}]
+ [{serviceData: {"A": {}}}]
- [{manufacturerId: 17},
- {serviceDataUUID: A}]
+ [{manufacturerData: {17: {}}},
+ {serviceData: {"A": {}}}]
+ [{manufacturerData: {17: {}},
+ serviceData: {"A": {}}}]
+
+
+ [{manufacturerData: {
+ 17: {dataPrefix: new Uint8Array([1, 2, 3])},
+ }}]
+
+
+ [{manufacturerData: {
+ 17: {dataPrefix: new Uint8Array([1, 2, 3, 4])},
+ }}]
+
+
+ [{manufacturerData: {
+ 17: {dataPrefix: new Uint8Array([1])},
+ }}]
+
+
+ [{manufacturerData: {
+ 17: {dataPrefix: new Uint8Array([0x91, 0xAA]),
+ mask: new Uint8Array([0x0F, 0x57])},
+ }}]
+
+
+ [{manufacturerData: {
+ 17: {},
+ 18: {},
+ }}]
+
+
+ requestDevice({
+ filters:[{manufacturerData: {}}]
+ })
+
+
+ requestDevice({
+ filters:[{serviceData: {}}]
+ })
+
+ filter.name is present then,
+ If filter.{{name}} is present then,
if device's Bluetooth Device Name isn't complete
and equal to filter.name,
return `mismatch`.
filter.namePrefix is present then
+ If filter.{{namePrefix}} is present then
if device's Bluetooth Device Name isn't present
or doesn't start with filter.namePrefix,
return `mismatch`.
filter.services,
+ For each uuid in filter.{{services}},
if the UA has not received advertising data, an extended inquiry response,
or a service discovery response indicating that
the device supports a primary (vs included) service with UUID uuid,
return `mismatch`.
filter.manufacturerId is present then
+ If filter.{{manufacturerData}} is present then
+ for each |manufacturerId| in
+ |filter|.manufacturerData.{{Object/[[OwnPropertyKeys]]}}(),
if device hasn't advertised manufacturer specific data
- with a company identifier code equal to
- filter.manufacturerId,
+ with a company identifier code that stringifies in base 10 to |manufacturerId|
+ and with data that matches
+ |filter|.{{manufacturerData}}[|manufacturerId|]
return `mismatch`.
filter.serviceDataUUID is present then
+ If filter.{{serviceData}} is present then
+ for each |uuid| in
+ |filter|.{{serviceData}}.{{Object/[[OwnPropertyKeys]]}}(),
if device hasn't advertised service data
- with a UUID equal to filter.serviceDataUUID,
+ with a UUID whose 128-bit form is |uuid|
+ and with data that matches
+ |filter|.{{serviceData}}[|manufacturerId|],
return `mismatch`.
+ An array of bytes |data| + matches a {{BluetoothDataFilterInit}} |filter| + if the following steps return `match`. +
++ Note: This algorithm assumes that |filter| has already been + canonicalized. +
+|filter|.{{dataPrefix}}.
+ |filter|.{{mask}}.
+ The list of Service UUIDs that a device advertises might not include all the UUIDs the device supports. @@ -1080,7 +1223,7 @@ spec: html
To request Bluetooth devices, - given a sequence of {{BluetoothRequestDeviceFilter}}s, |filters|, + given a sequence of {{BluetoothLEScanFilterInit}}s, |filters|, which can be `null` to represent that all devices can match, and a sequence of {{BluetoothServiceUUID}}s, |optionalServices|, the UA MUST run the following steps: @@ -1121,114 +1264,16 @@ spec: html do the following steps:
filter.services is present, do the following sub-steps:
- filter.services.length === 0,
- throw a {{TypeError}}
- and abort these steps.
- {{Array.prototype.map}}.call(filter.services,
- {{BluetoothUUID/getService()|BluetoothUUID.getService}}).
- canonicalizedFilter.services to services.
- filter.name is present, do the following sub-steps.
- filter.name
- is more than 248 bytes long,
- throw a {{TypeError}}
- and abort these steps.
-
- - 248 is the maximum number of UTF-8 code units in - a Bluetooth Device Name. -
-canonicalizedFilter.name
- to filter.name.
- filter.namePrefix is present, do the following sub-steps.
- filter.namePrefix.length === 0
- or if the UTF-8 encoding
- of filter.namePrefix
- is more than 248 bytes long,
- throw a {{TypeError}}
- and abort these steps.
-
- - 248 is the maximum number of UTF-8 code units in - a Bluetooth Device Name. -
-canonicalizedFilter.namePrefix
- to filter.namePrefix.
- |filter|.manufacturerId is present,
- set |canonicalizedFilter|.manufacturerId
- to |filter|.manufacturerId.
+ Add the contents of |canonicalFilter|.services
+ to |requiredServiceUUIDs|.
|filter|.serviceDataUUID is present, do the following sub-steps.
- |filter|.serviceDataUUID).
- |canonicalizedFilter|.serviceDataUUID
- to |service|.
- + The result of canonicalizing + the {{BluetoothLEScanFilterInit}} |filter|, + is the {{BluetoothLEScanFilterInit}} returned from the following steps: +
+filter.{{BluetoothLEScanFilterInit/services}} is present,
+ do the following sub-steps:
+ filter.services.length === 0,
+ throw a {{TypeError}}
+ and abort these steps.
+ {{Array.prototype.map}}.call(filter.services,
+ {{BluetoothUUID/getService()|BluetoothUUID.getService}}).
+ canonicalizedFilter.services to services.
+ filter.{{BluetoothLEScanFilterInit/name}} is present,
+ do the following sub-steps.
+ filter.name
+ is more than 248 bytes long,
+ throw a {{TypeError}}
+ and abort these steps.
+
+ + 248 is the maximum number of UTF-8 code units in + a Bluetooth Device Name. +
+canonicalizedFilter.name
+ to filter.name.
+ filter.{{BluetoothLEScanFilterInit/namePrefix}} is present,
+ do the following sub-steps.
+ filter.namePrefix.length === 0
+ or if the UTF-8 encoding
+ of filter.namePrefix
+ is more than 248 bytes long,
+ throw a {{TypeError}}
+ and abort these steps.
+
+ + 248 is the maximum number of UTF-8 code units in + a Bluetooth Device Name. +
+canonicalizedFilter.namePrefix
+ to filter.namePrefix.
+ |canonicalizedFilter|.manufacturerData to `{}`.
+ |filter|.{{BluetoothLEScanFilterInit/manufacturerData}} is present,
+ do the following sub-steps for each |key| in
+ |filter|.manufacturerData.{{Object/[[OwnPropertyKeys]]}}().
+ If there are no such keys, throw a {{TypeError}} and abort these steps.
+ |filter|.manufacturerData[|manufacturerId|],
+ converted to an IDL value of type {{BluetoothDataFilterInit}}.
+ If this conversion throws an exception, propagate it and abort these steps.
+ |canonicalizedFilter|.serviceData to `{}`.
+ |filter|.{{BluetoothLEScanFilterInit/serviceData}} is present,
+ do the following sub-steps for each |key| in
+ |filter|.serviceData.{{Object/[[OwnPropertyKeys]]}}().
+ If there are no such keys, throw a {{TypeError}} and abort these steps.
+ {{BluetoothUUID/getService()|BluetoothUUID.getService}}(|serviceName|).
+ |filter|.serviceData[|service|],
+ converted to an IDL value of type {{BluetoothDataFilterInit}}.
+ If this conversion throws an exception, propagate it and abort these steps.
+ + The result of canonicalizing + the {{BluetoothDataFilterInit}} |filter|, + is the {{BluetoothDataFilterInit}} returned from the following steps: +
+|filter|.{{BluetoothDataFilterInit/dataPrefix}} is present,
+ let |dataPrefix| be a copy of the bytes held
+ by |filter|.dataPrefix.
+ Otherwise, let |dataPrefix| be an empty sequence of bytes.
+ |filter|.{{BluetoothDataFilterInit/mask}} is present,
+ let |mask| be a copy of the bytes held
+ by |filter|.mask.
+ Otherwise, let |mask| be a sequence of `0xFF` bytes the same length as |dataPrefix|.
+ To scan for devices with @@ -1514,7 +1765,7 @@ spec: html dictionary BluetoothPermissionDescriptor : PermissionDescriptor { DOMString deviceId; // These match RequestDeviceOptions. - sequence<BluetoothRequestDeviceFilter> filters; + sequence<BluetoothLEScanFilterInit> filters; sequence<BluetoothServiceUUID> optionalServices = []; boolean acceptAllDevices = false; }; diff --git a/scanning.bs b/scanning.bs index 8a803be3..a5298241 100644 --- a/scanning.bs +++ b/scanning.bs @@ -74,21 +74,38 @@ Markup Shorthands: css no, markdown yes spec: ECMAScript; urlPrefix: https://tc39.github.io/ecma262/# type: method text: Array.prototype.map; url: sec-array.prototype.map + text: [[OwnPropertyKeys]]; for: Object; url: sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys type: interface text: TypeError; url: sec-native-error-types-used-in-this-standard-typeerror + +spec: WebIDL; urlPrefix: https://heycam.github.io/webidl/# + type: dfn + text: a copy of the bytes held; url: dfn-get-buffer-source-copy + spec: web-bluetooth; urlPrefix: index.html# + type: dfn + text: canonicalizing + for: BluetoothDataFilterInit; url: bluetoothdatafilterinit-canonicalizing + for: BluetoothLEScanFilterInit; url: bluetoothlescanfilterinit-canonicalizing + for: BluetoothDataFilterInit; text: matches; url: bluetoothdatafilterinit-matches + type: dictionary; urlPrefix: dictdef- + text: BluetoothDataFilterInit + text: BluetoothLEScanFilterInit type: dict-member for: AllowedBluetoothDevice; text: mayUseGATT; url: dom-allowedbluetoothdevice-mayusegatt + for: BluetoothLEScanFilterInit; urlPrefix: dom-bluetoothlescanfilterinit- + text: manufacturerData + text: serviceData + text: services + for: BluetoothDataFilterInit; urlPrefix: dom-bluetoothdatafilterinit- + text: dataPrefix + text: mask
-spec: html
+spec:web-bluetooth
type: dfn
- text: in parallel
- text: queue a task
- text: relevant settings object
- text: responsible event loop
- text: triggered by user activation
-spec:web-bluetooth-1; type:enum-value; for:PermissionName; text:"bluetooth"
+ text: read only arraybuffer
+ type:enum-value; for:PermissionName; text:"bluetooth"