Skip to content

Commit

Permalink
Fixes for beaufortfrancois and wbamberg review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisdavidmills committed Nov 29, 2024
1 parent e16dd34 commit 85c9bb8
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 12 deletions.
2 changes: 1 addition & 1 deletion files/en-us/web/api/serial/getports/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ A {{jsxref("Promise")}} that resolves with an array of {{domxref("SerialPort")}}
### Exceptions

- `SecurityError` {{domxref("DOMException")}}
- : The returned `Promise` rejects with this error if:
- : The returned `Promise` rejects with this error in either of the following situations:
- A {{httpheader('Permissions-Policy/serial','serial')}} [Permissions Policy](/en-US/docs/Web/HTTP/Permissions_Policy) blocks the use of this feature.
- A user permission prompt was denied.

Expand Down
35 changes: 32 additions & 3 deletions files/en-us/web/api/serial/requestport/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ requestPort(options)
- `filters` {{optional_inline}}
- : A list of objects containing vendor, product, or Bluetooth service class IDs used to filter the specific device types made available for the user to request a connection to. If no filters are specified, the user is presented with a list of every available device to choose from. Filters can contain the following values:
- `bluetoothServiceClassId` {{optional_inline}}
- : An unsigned long integer or string representing a Bluetooth service class ID. This can be a 16- or 32-bit UUID aliase, any valid UUID, or a valid name from a GATT assigned services key.
- : An unsigned long integer or string representing a Bluetooth service class ID. This can be a 16- or 32-bit UUID alias, any valid UUID, or a valid name from a [GATT assigned services key](https://github.com/WebBluetoothCG/registries/blob/master/gatt_assigned_services.txt).
- `usbVendorId` {{optional_inline}}
- : An unsigned short integer that identifies a USB device vendor. The [USB Implementors Forum](https://www.usb.org/) assigns IDs to specific vendors.
- `usbProductId` {{optional_inline}}
- : An unsigned short integer that identifies a USB device. Each vendor assigns IDs to its products.
- `allowedBluetoothServiceClassIds` {{optional_inline}}
- : A list of unsigned long integers and/or strings representing Bluetooth service class IDs. Bluetooth ports with custom service class IDs are excluded from the list of ports presented to the user unless the service class ID is included in this list.
- : A list of unsigned long integers and/or strings representing Bluetooth service class IDs. Bluetooth ports with custom service class IDs are excluded from the list of ports presented to the user unless the service class ID is included in this list. This is true whether you filter the list or not.

### Return value

Expand All @@ -49,7 +49,7 @@ A {{jsxref("Promise")}} that resolves with an instance of {{domxref("SerialPort"
### Exceptions

- `SecurityError` {{domxref("DOMException")}}
- : The returned `Promise` rejects with this error if:
- : The returned `Promise` rejects with this error in either of the following situations:
- A {{httpheader('Permissions-Policy/serial','serial')}} [Permissions Policy](/en-US/docs/Web/HTTP/Permissions_Policy) blocks the use of this feature.
- A user permission prompt was denied.
- `NotFoundError` {{domxref("DOMException")}}
Expand Down Expand Up @@ -93,6 +93,35 @@ connectBtn.addEventListener("click", () => {
});
```

### Allow the user to select custom RFCOMM-based services

Although most devices expose SPP-based communication through the standardized Bluetooth Classic Serial Port Profile, some use custom RFCOMM-based services. These devices have a Service Class ID that is not in the standard Bluetooth UUID range.

You need to pass the `allowedBluetoothServiceClassIds` list to `requestPort()` to access these custom RFCOMM-based services:

```js
const myBluetoothServiceUuid = "01234567-89ab-cdef-0123-456789abcdef";

// Prompt user to select any serial port
// Access to the custom Bluetooth RFCOMM service above will be allowed
const port = await navigator.serial.requestPort({
allowedBluetoothServiceClassIds: [myBluetoothServiceUuid],
});
```

You can also use the `bluetoothServiceClassIdfilter` key when calling `requestPort()` to prompt the user with a list of filtered Bluetooth serial ports identified by Service Class IDs:

```js
const myBluetoothServiceUuid = "01234567-89ab-cdef-0123-456789abcdef";

// Prompt the user to select Bluetooth serial ports with
// the custom Bluetooth RFCOMM service above.
const port = await navigator.serial.requestPort({
allowedBluetoothServiceClassIds: [myBluetoothServiceUuid],
filters: [{ bluetoothServiceClassId: myBluetoothServiceUuid }],
});
```

## Specifications

{{Specifications}}
Expand Down
48 changes: 47 additions & 1 deletion files/en-us/web/api/serialport/close/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,53 @@ The **`SerialPort.close()`** method of the {{domxref("SerialPort")}} interface r

## Description

`close()` closes the serial port if previously-locked {{domxref("SerialPort.readable")}} and {{domxref("SerialPort.writable")}} members are unlocked, meaning the `releaseLock()` methods have been called for their respective reader and writer. However, in some cases it is not that simple, for example when continuously reading data from a serial device using a loop. See [Close a serial port](https://developer.chrome.com/docs/capabilities/serial#close-port) for more guidance.
`close()` closes the serial port if previously-locked {{domxref("SerialPort.readable")}} and {{domxref("SerialPort.writable")}} members are unlocked, meaning the `releaseLock()` methods have been called for their respective reader and writer.

However, when continuously reading data from a serial device using a loop, the associated [readable stream](/en-US/docs/Web/API/ReadableStream) will always be locked until the [reader](/en-US/docs/Web/API/ReadableStreamDefaultReader) encounters an error. In this case, calling [`reader.cancel()`](/en-US/docs/Web/API/ReadableStreamDefaultReader/cancel) will force [`reader.read()`](/en-US/docs/Web/API/ReadableStreamDefaultReader/read) to resolve immediately with `{ value: undefined, done: true }` allowing the loop to call [`reader.releaseLock()`](/en-US/docs/Web/API/ReadableStreamDefaultReader/releaseLock).

```js
// Without transform streams.

let keepReading = true;
let reader;

async function readUntilClosed() {
while (port.readable && keepReading) {
reader = port.readable.getReader();
try {
while (true) {
const { value, done } = await reader.read();
if (done) {
// reader.cancel() has been called.
break;
}
// value is a Uint8Array.
console.log(value);
}
} catch (error) {
// Handle error...
} finally {
// Allow the serial port to be closed later.
reader.releaseLock();
}
}

await port.close();
}

const closedPromise = readUntilClosed();

document.querySelector("button").addEventListener("click", async () => {
// User clicked a button to close the serial port.
keepReading = false;
// Force reader.read() to resolve immediately and subsequently
// call reader.releaseLock() in the loop example above.
reader.cancel();
await closedPromise;
});
```

Closing a serial port is more complicated when using [transform streams](/en-US/docs/Web/API/TransformStream). See [Close a serial port](https://developer.chrome.com/docs/capabilities/serial#close-port) for guidance.

## Syntax

Expand Down
7 changes: 1 addition & 6 deletions files/en-us/web/api/serialport/forget/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,7 @@ The **`SerialPort.forget()`** method of the {{domxref("SerialPort")}} interface

## Description

A website can clean up permissions to access a serial port it is no longer interested in retaining by calling `SerialPort.forget()`. In real terms, calling this closes the connection, forgets the device, and resets the permission.

```js
// Voluntarily revoke access to this serial port
await port.forget();
```
A website can clean up permissions to access a serial port it is no longer interested in retaining by calling `SerialPort.forget()`. Calling this "forgets" the device, resetting any previously-set permissions so the calling site can no longer communicate with the port.

For example, for an educational web application used on a shared computer with many devices, a large number of accumulated user-generated permissions creates a poor user experience.

Expand Down
2 changes: 1 addition & 1 deletion files/en-us/web/api/serialport/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Instances of this interface may be obtained by calling methods of the {{domxref(
## Instance methods

- {{domxref("SerialPort.forget()")}} {{Experimental_Inline}}
- : Returns a {{jsxref("Promise")}} that resolves when access to the serial port is revoked. In real terms, calling this closes the connection, forgets the device, and resets the permission.
- : Returns a {{jsxref("Promise")}} that resolves when access to the serial port is revoked. Calling this "forgets" the device, resetting any previously-set permissions so the calling site can no longer communicate with the port.
- {{domxref("SerialPort.getInfo()")}} {{Experimental_Inline}}
- : Returns an object containing identifying information for the device available via the port.
- {{domxref("SerialPort.open()")}} {{Experimental_Inline}}
Expand Down

0 comments on commit 85c9bb8

Please sign in to comment.