Coder Social home page Coder Social logo

webhid's Introduction

WebHID API

HID API for the web platform.

Explainer

Details about the API including example usage code snippets and its motivation, privacy, and security considerations are described in the Explainer.

Code of conduct

We are committed to providing a friendly, safe and welcoming environment for all. Please read and respect the W3C Code of Ethics and Professional Conduct.

Implementation status

This API is implemented in Blink. It is available in browsers based on Chromium 89 and later, such as Google Chrome and Microsoft Edge. Individual Chromium-based browsers may choose to enable or disable this API. Chromium-based Android browsers do not support this API because Android itself does not provide a direct API for accessing HID devices (Chromium issue 964441). For the same reason this API is not available in Android WebView (Chromium issue 1164125).

webhid's People

Contributors

autokagami avatar beaufortfrancois avatar chengweih001 avatar jyasskin avatar luser avatar marcoscaceres avatar nondebug avatar onlykey avatar pehandersen-jabra avatar reillyeon avatar scheib avatar tomayac avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

webhid's Issues

No input reports on Mac

For some reason, I don't get any input report events on Mac. If I try

let device = await navigator.hid.getDevices();
device[0].addEventListener('inputreport', async (event) => {
  console.log("Got input report");
});

in Chrome 83.0.4103.61, it works on Windows but not on macOS 10.15.4 with the same device. Should there be feature parity between the different OS versions with regard to WebHID implementations?

Question about enumerating requestDevice

Lacking access to a serial number, privacy hashed serial number, DevicePath, etc., what is a good approach to finding out if requestDevice has returned a new device or one already in getDevices? And if it is in getDevices, what is a good way to determine which device it is?

I'd like to make a table of paired devices (with a View button, and then a Pair New button using requestDevice), and while I can do this, if I pair new devices, lacking a way to compare them, I will have to reload and requery all of the devices, so I can't cache any information about it even locally. What's the best way to accomplish this?

Add a stable device identifier

The current spec does not provide an adequate way for script to distinguish multiple devices of the same model. Typically this is done by comparing USB serial numbers or Bluetooth MAC addresses which are set by the manufacturer and are expected to be unique.

Add blocklist to specification

crbug.com/1180703: "FIDO2/WebAuthN devices invisible to navigator.hid.requestDevice in WebHID" shows web developers confused expecting FIDO devices to work.

WebHID specification and web developer documentation should clearly reference the blocklist.

HIDDevice class - problem using "this" as named parameter in method declarations

This is a TypeScript project bootstrapped with create-react-app, here are my imports:

├── @material-ui/[email protected]
├── @material-ui/[email protected]
├── @testing-library/[email protected]
├── @testing-library/[email protected]
├── @testing-library/[email protected]
├── @types/[email protected]
├── @types/[email protected]
├── @types/[email protected]
├── @types/[email protected]
├── @types/[email protected]
├── @types/[email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]

Here is my tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": [
    "src"
  ],
  "files": [
    "src/typings/index.d.ts"
  ]
}

The issue appears to be the declaration of the oninputreport function on the HIDDevice class as such:

/*~ https://wicg.github.io/webhid/#hiddevice-interface */
declare class HIDDevice extends EventTarget {
    oninputreport: ((this: this, ev: HIDInputReportEvent) => any) | null;
    // etc
}

Using this here seems to constrain the function to force it to be implemented either on HIDDevice or else if implemented on another class it forces it to use this as the parameter name, which causes other problems...here's an example of what I mean:

Screen Shot 2021-09-07 at 10 03 45 AM

Note above the TS compiler is complaining that my implementation of that function is not assignable b/c the parameter name is not matching. I attempted to underscore it, but it still does not like it:

Screen Shot 2021-09-07 at 10 04 03 AM

So, I tried to override it using a typings file, but that still isn't working. The only hack workaround at this point is to cast it to unknown and then cast it back which is realistically a very poor hack.

Screen Shot 2021-09-07 at 10 09 24 AM

Of course, if I name the parameter this in my function implementation, well this causes me other issues:

Screen Shot 2021-09-07 at 10 18 03 AM

I can no longer use this as intended on my own class.

The fix here seems fairly simple. In the spec / implementation of the typings, you could re-do the declaration like so:

/*~ https://wicg.github.io/webhid/#hiddevice-interface */
declare class HIDDevice extends EventTarget {
    oninputreport: ((dev: HIDDevice, ev: HIDInputReportEvent) => any) | null;
    // etc
}

I see several other areas of the typings spec where this is used quite a bit. I would advise against this if possible.

Consider USB devices with multiple interfaces

A USB device may have multiple interfaces, each of which may support the HID protocol. Physically it is one device, but logically it may be represented by multiple HIDDevice objects.

The spec should describe how to present the device to the user as well as how to return the device to script. Users should not be required to understand how the USB device is implemented. To make it easier for users to identify the correct device, devices with multiple interfaces should be represented by a single item when shown in a chooser. When the user grants permission to access that device, the Promise returned by requestDevice should resolve to a sequence containing all of the device's interfaces.

Add possibility to query the initial state

I just started looking into WebHID. Everything works fine so far, except for one issue I've come across:
After requesting and opening a HID device, I did not find a way to get/query the device's current state. I have to wait forl an inputreport event to know the device's state.

Did I just miss something, or is this really not possible?

Unable to receive data right after sending report to the device.

Immediately after sending data, the USB device sends a response but 'inputreport' event handler is unable to catch the response. Is this a bug or is this expected?

The event handler catches input from the device if it is not immediately after sending a report.

Function to send data:

async function sendData(reportData) {
	recData = [];
	const device = await getOpenedDevice();
	device.sendReport(reportId, reportData).then(() => {
		console.log('Report Sent')
    });
}

Function to connect to device :

connectButton.addEventListener('click', async () => {
  let device;

  try {
    const devices = await navigator.hid.requestDevice({ filters: deviceFilters });
    device = devices[0];
    device.open().then(() => {
        console.log('Opened HID device');
        device.addEventListener('inputreport', handleInputReport);
    });
  } catch (error) {
    console.warn('No device access granted', error);
    return;
  }
});

Function to check open devices:

async function getOpenedDevice() {
  const devices = await navigator.hid.getDevices();
  let device = devices.find(d => d.vendorId === vendorId && d.productId === productId);

  if (!device) {
    device = await navigator.hid.requestDevice({
      filters: [{ vendorId, productId }],
    });
  }

  if (!device.opened) {
    await device.open();
  }

  return device;
}

Input report handler function:

function handleInputReport(e) {

	console.log("Input Received");
    // Fetch the value of the first button in the report.
    if (e.reportId < 0xF0 || e.reportId > 0xFE) {
    	return;
    }
    
    var uint8View = new Uint8Array(e.data.buffer);
    
	recData.push(uint8View[1]);
	
	showRecData();
}

handleInputReport not working for CP2110 HID USB-to-UART Bridge

This was working at one point. Not sure if anything changed on the WebHID end.
The problem is that although it recognizes the device, the handleInputReport event never fires:

document.getElementById('connectButton').addEventListener('click', handleConnectClick);
document.getElementById('sendButton').addEventListener('click', handleDisconnectClick);
let inputReportDisplay = document.getElementById('inputReportBox')

async function handleConnectClick() {
    var device = await openDevice();
}

async function handleDisconnectClick() {
    await device.close();
}

function handleInputReport(e) {
    console.log(e.device.productName + ": got input report " + e.reportId);
    inputReportDisplay.innerHTML = e.device.productName + ": got input report " + e.reportId;
    console.log(new Uint8Array(e.data.buffer));
    inputReportDisplay.innerHTML = new Uint8Array(e.data.buffer);
}

async function openDevice() {
    const vendorId = 0x10C4;
    const productId = 0xEA80; 

    const device_list = await navigator.hid.getDevices();
    console.log(device_list)

    let device = device_list.find(d => d.vendorId === vendorId && d.productId === productId);

    if (!device) {
        // this returns an array now
        let devices = await navigator.hid.requestDevice({
            filters: [{ vendorId, productId }],
        });
        console.log("devices:", devices);
        inputReportDisplay.innerHTML = "devices: " + devices;
        device = devices[0];
        if (!device) return null;
    }

    if (!device.opened) {
        await device.open();
        device.addEventListener("inputreport", handleInputReport);
    }
    console.log("device opened:", device);
    inputReportDisplay.innerHTML = "device opened: " + device.productName;
    return device;
}

Wondering if maybe the CP2110 is not supported?

Origin Trial 0.5% question

How does the 0.5% usage restriction apply to an origin? For letting people beta test a feature, ought I keep it on my main domain (www.) instead of a subdomain (say, beta.) so that under 0.5% of pages requested are likely to use the origin trial? Or is it 0.5% across the whole web instead of my origin?

Device available on Windows, but not on Mac

I'm having the exact same problem with the same device as described here: node-hid/node-hid#197

At the end of that issue it mentions that it may be resolved with the latest release of that project. There was only 1 related PR for it, linked to this issue: node-hid/node-hid#348

Specifically they note "The hidapi updates that allow Macs to see devices with multiple usages as unique items has been added to node-hid as of version v1.1.0."

The specific commit that seems to fix the issue is here: libusb/hidapi@083223e...ca1a2d6#diff-5cbb2d1918d13a205b0b45fa24166f42

I'm wondering if the same issue could be what is affecting WebHID?

navigator.hid not available

Hi there,

I was looking for a web equivalent of Chrome.hid and I came across the WebHID API.
But when I'm trying to communicate with a custom hid device using navigator.hid, it returns undefined.

Is there something I need to do to access navigator.hid?

Ted

Usage Page should not be per HIDCollectionInfo but per HIDReportItem

Current WebHID spec expects Usage Page appears once per HIDCollectionInfo, but there is no such restriction in the USB HID spec AFAIK. Usage Page is just a Global Item like other global ones such as Logical Minimum, etc. These field appear per HIDReportItem, and Usage Page should be so too.

HID1_11.pdf, Device Class Definition for Human Interface Devices (HID) Firmware Specification Version 1.11, P.25 shows an example report that contains the case.

Single headset button press fires event multiple times

Hello,

Currently, I am integrating our softphone app with webHID API. It works great but I just noticed that a single headset button press (dial, hangup, etc.) fires same event twice. I've tried testing using Jabra and Plantronics brands, and they both exhibit same behavior with Jabra having an interval of <= 2500 ms and Plantronics with <= 50 ms. I am not sure if this is an expected behavior. If so, is there a way to prevent webHID from firing it multiple times? I just tested two brands and I am worried that same behavior might occur for other brands as well.

Also there are times that when a mute button is pressed for Plantronics headsets, multiple events are fired with different report ids which result to an inconsistent behavior. Any comments are highly appreciated.

Thanks.

Is it possible for the Chrome team to supply TypeScript definitions

Like title says -- would it be possible get TypeScript definitions for HIDDevice and all the interfaces, etc?

I'm embarking on writing a driver for a USB/HID device after I worked through a PoC to ensure it would work. Seems like I can read/write feature reports, and receive input reports fine with it after experimentation, and now want to build a real driver in TypeScript, but the missing type definitions are problematic. Since this is currently, mostly a Chrome only feature...I doubt Microsoft will include them in official DOM typings.

HID Headsets send two reports in a sequence if push 'Mute' button

Looks like this is not related to device, since tried on different with the same result: Sennheiser, Jabra, Poly.
If you connect one of listed USB headset and add inputReport listener, you will find that on pressing mute button you receive 2 reports in a sequence first with value 1 and second with value 0. The sequence is always the same: 1 then 0.

Failed to write the report.

I am working with a Mettler Toledo PS60 scale. I am able to open the device, but am having trouble consistently sending reports to the device. If I restart the scale, I can write the report and I get data back that I can use. I continuously get data sent back for roughly 10 to 60 seconds before I stop getting the reports. When I attempt to send the report to the device again, it says "Failed to write the report" and continues to do so until I reset the device.

I am assuming this is a device issue and I have sent them a request. Has anyone else experienced intermittent connectivity like my example using this API? I do not have another device with which to test at the moment.

If there is a better place to discuss these issues, please let me know. I have not found a lot of documentation on this yet.

no such device variable in the spec example

navigator.hid.addEventListener('connect', async () => {
  console.log('HID connected: ${device.productName}');
});

navigator.hid.addEventListener('disconnect', async () => {
  console.log('HID disconnected: ${device.productName}');
});

🤔

was it supposed to be async e => ... e.device.productName ?

hid read/write

Hi,
I have built a custom hid device using Lufa library. I am using python to blink led using following code:
import hid
ocr=hid.device()
ocr.open(0x3eb, 0x204f)
ocr.write([0, 1, 0, 0, 0, 0, 0]) // 1 > to turn led on

but, i wanted to blink led using chrome. saw this library webhid. Hence, how should i proceed??
steps done till now:

  1. enabled experimental web platform feature on chrome

  2. let device = await navigator.hid.requestDevice({filters:[]});
    await device.open();
    if (device.opened)
    console.log("Device is open.");

  3. now how should i write?? in order to blink led..

Buffer Timing Issue?

I'm working with a CP2110 USB-to-UART right now.

I can connect to the device, but the input report seems a bit off.
When the device is turned on, it automatically starts spitting out data, but there should always be a 5-byte "Preamble" at the start of the input report, but sometimes the input report is off (shifted).

It works flawlessly in my Winform Desktop App, but for some reason, here it doesn't.

I've tried adding a slight delay in between reads (200ms, 500ms, 1500ms, etc.) but it doesn't seem to help.

I might be using this incorrectly, or I don't know if there are other parameters you can set to adjust the input report?

Properties missing from HIDReportItem

In the USB spec report items (Input, Output and Feature) include several bit flags in the item value that are missing from HIDReportItem.

  • Bit 0: Data|Constant - Missing.
  • Bit 1: Array|Variable - Included.
  • Bit 2: Absolute|Relative - Included.
  • Bit 3: No Wrap|Wrap - Missing.
  • Bit 4: Linear|Nonlinear - Missing.
  • Bit 5: Preferred State|No Preferred - Missing.
  • Bit 6: No Null|Null State - Included.
  • Bit 7: Non-volatile|Volatile - Missing.
  • Bit 8: Bit Field|Buffered Bytes - Missing.
  • Bit 9-31: Reserved.

I think the first bit is crucial if you want to make anything generic, or you wont be able to detect PAD data in the report (your best bet would be missing usage?).

I'm also a bit confused what isRange refer to, the WebHID spec doesn't say anything about it.

Specify the algorithms for each method/getter

It looks like this specification has a bunch of IDL, but no discussion of what actually happens when the given methods/getters are invoked. So there's no spec in existence for what navigator.hid.requestDevice() or navigator.hid.getDevices() should actually do.

Similarly, if you somehow magically got a HIDDevice instance, there's no specification for what calling device.open() or device.sendReport() does.

Cannot open device returned from requestDevice

I am trying to connect to a USB scale (Mettler Toledo). The USB scale registers itself as an HID device. I am able to select it in the drop down after I execute the requestDevice function. However, when I go to open the device, I get a 'Not supported' error. Here is my code:

async Connect() {
        if (this.Vendor === 'Mettler Toledo') {
            this.VENDOR_ID = 0x0EB8;
        }
        try {
            this.device = await navigator.hid.requestDevice({
                filters: [{
                    vendorId: this.VENDOR_ID
                }]
            });
            await this.device.open();
            if (this.device.opened)
                console.log('Device is open.');
            let initReport = new Uint8Array(1);
            initReport[0] = 42;
            this.device.oninputreport = e => {
                console.log(e);
            };
            this.device.sendReport(0x01, initReport).then(() => {
                console.log('Sent initialization packet');
            });
            return true;
        } catch (err) {
            console.log(err.message);
        }
    }

It appears that the requestDevice function is returning an empty object:

HIDDevice {collections: Array(0), opened: false, productId: 0, productName: "", vendorId: 0, …}
     collections: []
     oninputreport: null
     opened: false
     productId: 0
     productName: ""
     vendorId: 0
     __proto__: HIDDevice

I am using the Chrome beta branch. Version 77.0.3865.75. I have the flag Experimental Web Platform features enabled.

Collection & main item ordering

I think there might be a fundamental flaw in separating collection children from main items (inputReports, outputReports, featureReports). The nesting and their ordering become important when figuring out the data offsets.

Consider the following two report descriptors:

Collection
  Input A
  Collection
    Input B
Collection
  Collection
    Input B
  Input A

With the current API they will be identical, while in reality the ordering of the inputs are reversed. This makes it impossible to calculate correct data offsets.

Add helpers for reading/writing report fields by usage

The Windows HID API has a number of helper functions for reading and writing report buffers, it would be handy if WebHID offered something similar so that applications can read or write reports without needing to first parse the HIDDevice.collections member.

Initialization
HidP_InitializeReportForID

Get field by usage
HidP_GetUsages
HidP_GetUsagesEx
HidP_GetUsageValue
HidP_GetScaledUsageValue
HidP_GetUsageValueArray

Get field by data index
HidP_GetData

Set field by usage
HidP_SetUsages
HidP_UnsetUsages
HidP_SetUsageValue
HidP_SetScaledUsageValue
HidP_SetUsageValueArray

Set field by data index
HidP_SetData

Collection Dissapear upon disconnect/reconnect

Hi all,

Recently I see my collections getting smaller after disconnecting mydevice and then later reconnecting it.

I made a small test looking like below;

navigator.hid.addEventListener('disconnect', ({device}) => {
        console.log(device.collections.length);          //This output 3 on first disconnect, 2 on subsequent
});
navigator.hid.addEventListener('connect', ({device}) => {
        console.log(device.collections.length);          //This always output 2 
});

The missing collection is the telephony page 0x0B, my device is a headset.
I am running on Windows. After restart of Canary I am back to 3 collections until first disconnect....

open API always return permission denied on Chrome OS

Hi,
I use WebHID API to develop a tool , this tool can communicate with bluetooth HID device on Windows 10.
I run this tool on Chrome OS, but it always returns "permission denied" when I use "open()" API to open device.

I catch the device log and system log as below:

device log:

HIDEvent[09:16:08] Permission broker failed to open '/dev/hidraw3': org.freedesktop.DBus.Error.Failed: permission_broker/permission_denied:Permission to open '/dev/hidraw3' denied

HIDUser[09:16:01] HID device detected: vendorId=14648, productId=4662, name='BT5.1 Mouse', serial='d4:8d:cf:c0:06:ac', deviceIds=[/sys/devices/virtual/misc/uhid/0005:3938:1236.0005/hidraw/hidraw3']

system log:

2021-01-20T07:57:43.811441Z INFO kernel: [ 42.922193] input: BT5.1 Mouse Mouse as /devices/virtual/misc/uhid/0005:3938:1236.0005/input/input13
2021-01-20T07:57:43.811552Z INFO kernel: [ 42.922616] input: BT5.1 Mouse as /devices/virtual/misc/uhid/0005:3938:1236.0005/input/input14
2021-01-20T07:57:43.812417Z INFO kernel: [ 42.922926] hid-generic 0005:3938:1236.0005: input,hidraw3: BLUETOOTH HID v0.02 Mouse [BT5.1 Mouse] on 30:c9:ab:d9:42:86
2021-01-20T07:57:54.512424Z DEBUG kernel: [ 53.617684] gpio gpiochip0: Persistence not supported for GPIO 150
2021-01-20T07:57:54.512478Z DEBUG kernel: [ 53.617693] gpio gpiochip0: registered chardev handle for line 150
2021-01-20T07:57:54.512485Z DEBUG kernel: [ 53.617701] gpio gpiochip0: registered chardev handle for 1 lines
2021-01-20T07:58:03.314881Z INFO kernel: [ 62.415193] PDLOG 2021/01/20 07:56:56.925 P0 Disconnected
2021-01-20T07:58:10.224641Z NOTICE temp_logger[7243]: 00:36C 01:34C 02:33C 03:34C 04:36C 05:34C 06:35C 07:31C 08:27C 09:28C
2021-01-20T07:58:12.717531Z INFO kernel: [ 71.813082] binder_alloc: 5439: binder_alloc_buf size 1056768 failed, no address space
2021-01-20T07:58:12.717664Z INFO kernel: [ 71.813100] binder_alloc: allocated: 3104 (num: 13 largest: 2320), free: 1037280 (num: 3 largest: 1037232)
2021-01-20T07:58:12.717677Z INFO kernel: [ 71.813109] binder: 5644:7250 transaction failed 29201/-28, size 1056768-0 line 3152
2021-01-20T07:58:18.357481Z INFO chrome[1607]: 2021-01-20T07:58:18.356424Z INFO chrome[1607:1639]: [rlz_lib.cc(463)] Attempting to send RLZ ping brand=UBRP
2021-01-20T07:58:18.576613Z INFO chrome[1607]: 2021-01-20T07:58:18.576155Z INFO chrome[1607:1639]: [rlz_lib.cc(488)] Succeeded in sending RLZ ping
2021-01-20T07:59:06.361192Z INFO permission_broker[1855]: ProcessPath(/dev/hidraw3)
2021-01-20T07:59:06.753967Z INFO permission_broker[1855]: AllowUsbDeviceRule: IGNORE
2021-01-20T07:59:06.754260Z INFO permission_broker[1855]: AllowTtyDeviceRule: IGNORE
2021-01-20T07:59:06.754402Z INFO permission_broker[1855]: DenyClaimedUsbDeviceRule: IGNORE
2021-01-20T07:59:06.754500Z INFO permission_broker[1855]: DenyUninitializedDeviceRule: IGNORE
2021-01-20T07:59:06.754606Z INFO permission_broker[1855]: DenyUsbDeviceClassRule: IGNORE
2021-01-20T07:59:06.754710Z INFO permission_broker[1855]: DenyUsbVendorIdRule: IGNORE
2021-01-20T07:59:06.754813Z INFO permission_broker[1855]: AllowHidrawDeviceRule: ALLOW
2021-01-20T07:59:06.754939Z INFO permission_broker[1855]: AllowGroupTtyDeviceRule: IGNORE
2021-01-20T07:59:06.755057Z INFO permission_broker[1855]: DenyGroupTtyDeviceRule: IGNORE
2021-01-20T07:59:06.755251Z INFO permission_broker[1855]: message repeated 2 times: [ DenyGroupTtyDeviceRule: IGNORE]
2021-01-20T07:59:07.074555Z INFO permission_broker[1855]: DenyClaimedHidrawDeviceRule: DENY
2021-01-20T07:59:07.074995Z INFO permission_broker[1855]: Verdict for /dev/hidraw3: DENY
2021-01-20T07:59:07.075263Z ERR permission_broker[1855]: OpenPathImpl(...): Domain=permission_broker, Code=permission_denied, Message=Permission to open '/dev/hidraw3' denied

The "BT5.1 Mouse Mouse" is BT mouse and it can work on Chrome OS.
"BT5.1 Mouse" has customized HID report, I want to communicate with it.
"BT5.1 Mouse Mouse" and "BT5.1 Mouse" are in the same physical device.

It looks like my device was denied by permission broker?
How can I solve this problem?

Thanks.

Lifecycle of event handlers

I managed to experiment with WebHID a few month back in Chrome. I found an issue and reported (but got no feedback, cf. https://bugs.chromium.org/p/chromium/issues/detail?id=890096#c51) about the garbage collection of the event handlers. It is very similar to an issue that plagued the (now deprecated) audio processor API as I mentioned in the issue. I ended implementing this to solve the problem:
https://github.com/asutherland/ni-controllers-lib/blob/f698d54bb1f33c0a8b7b55a92c13da8ceff3ce31/lib/usb/web.ts#L44-L51

I understand this is the issue tracker for the spec. My point is there is nothing about the lifecycle/reference type held to the handler so I wonder if it should be explicitly put in the spec to avoid interpretation?

navigator.hid.addEventListener('connect', async ({device})) called to early

Lately the timing in when the "connect" event is called has changed and I found that the device.collections is not yet fully populated. The array is typically only of length 1, while if you log the device to console, you will see the right length, which in my case is 3...

It did not use to be like this, but I see it now in 91.0.4472.77 and even in latest canary build...

Serial number

Would you please make it so, after the page has access to the device, it can query the serial number? I would like to store user customizations based on serial number, and there is presently no way to do this.

Right now I am using WebUSB (where serial number is available), but WebHID would allow me to support our legacy products as well, so I would like to support it.

Use of dictionaries instead of interfaces

As raised in a blink-dev discussion, it would be better to prefer dictionaries over interfaces for easier logging purposes.

I could see the interfaces below replaced by dictionaries, as they don't have methods on them:

  • HIDCollectionInfo
  • HIDReportInfo
  • HIDReportItem

For info, this is what web developers get today:

JSON.stringify(myHidDevice.collections);
>> "[{}]"

Rename requestDevice to requestDevices

As the result of navigator.hid.requestDevice() is a sequence of HID devices, it would be better for expectation purposes to rename the navigator.hid method to requestDevices().

Note that we have getDevices(), not getDevice().

const devices = await navigator.hid.requestDevices({ filters: [] });
devices.forEach((device) => { /* ... */ });

Unpair device method

Hello,

This isn't strictly necessary, but it would be a nice symmetry, if one is offering their users a Pair option, to also offer them an Unpair option. Certainly, when some sort of unique identifier is added, one could store a 'don't use' based on that, but out of respect to my users I'd really like to offer them the ability to genuinely unpair the device. :)

Other than the lack of unique identifiers, WebHID is working pretty well for me right now! (porting Evolv's ECigStats to the web)

Thank you!

James

What is the longer term goal?

The stated impetus for this API as documented on https://web.dev/hid/:

There is a long tail of human interface devices (HIDs), such as alternative keyboards or exotic gamepads, that are too new, too old, or too uncommon to be accessible by systems' device drivers. The WebHID API solves this by providing a way to implement device-specific logic in JavaScript.

This will certainly improve the accessibility for writing code against HID devices, forgoing the need to learn, develop, build, and distribute native device drivers.

However, I suspect countless web developers implementing HID 'drivers' in javascript is just going to cause a new problem: inconsistent, buggy, and out-of-date behavior with very limited device support and sparse QA/Testing.

Is the expectation that individual devices drivers will be built and packaged as npm packages? Or driver libraries emerge with embedded collections of drivers that are community supported? Certainly Chrome devs don't expect independent developers to build drivers themselves for countless, (as indicated) inconsistently built devices.

I see a bleak future with a hodgepodge of inconsistently implemented and unpredictably supported hardware much worse than the stated problem. Am I missing something?

Exclusion

Hello,

I'm the creator of the HIDSharp library for C# USB HID communications. I use this library in a product I'm contracted to create, Evolv's EScribe Suite.

Since Windows does not provide any form of exclusion for USB HID devices, I do it manually using global mutexes, with handoffs, etc. This allows different aspects of the (multiprocess) product to coordinate and not conflict as far as USB HID communications go. (This also works on Mac and Linux.) Of course, this problem does not exist with WebUSB, since USB access is not shared.

Is there any equivalent for Chrome? I could easily extend my HIDSharp library to support however Chrome may implement this (Windows mutexes, or whatnot), and update our desktop applications. Our ECigStats software downloads statistics upon connect, and my web implementation does the same, so if both are present, it does not work too well. We have other pieces of software that also need exclusion.

Does Chrome provide anything of this sort, named mutexes or whatnot (prefixed by the origin or something would be fine)? It need not be specific to WebHID, I just haven't found anything at all of this kind.

Thank you!

James

Question on HID over Bluetooth

I know HID over Bluetooth is possible, but how would it work with the WICG APIs?

I have a BTLE device that does not advertise itself to the OS (e.g. scanning with Mac OS Bluetooth dialog it is not discoverable), but if I use WebBluetooth APIs I can find it and connect to it. Once I do that, it shows up in OS list as connected.

What I'd like to know is if I can then turn around and use the WebHID APIs using Bluetooth LE as the transport? How would that work, even? If I use the WebHID API to requestDevice with the appropriate filter and it were not attached via USB but it was connected via Bluetooth, would it even show up? If it did, this would seemingly require two pop-up dialogs to make the user affirm connecting to the device (one for WebBT, and one for WebHID), which would be an awkward experience.

Thanks in advance!

A new filter option to exclude already-authorized devices

I want to add a new filter option to exclude already-authorized devices for the requestDevice method.

dictionary HIDDeviceFilter {
    unsigned long vendorId;
    unsigned short productId;
    unsigned short usagePage;
    unsigned short usage;
    boolean excludeAuthorisedDevices;  // <- New filter option
};

Currently, there is no such option. Therefore, users see all connected devices including devices which was already authorized on the dialog opened by calling the requestDevice method.

In the other hand, we can get all authorized devices by calling the getDevices method. Generally, most apps should call the getDevices method at launching for the purpose of displaying a device list, I guess. Also, most apps should keep and manage the list of authorized devices.

If a user selects already-authorized devices from the dialog opened by calling the requestDevice method, we need to check whether the selected device is included in the list of the result retrieved from calling getDevices method or not. However, if there is an option to exclude already-authorized devices from the device list on the dialog opened by calling the requestDevice method, it is unnecessary.

Max. Buffer size in output reports

Hi,

I tried to send a HID report to a device from my Linux machine (Ubuntu 18.04), and any buffer bigger than 16B will leads to:
"Output report buffer too long" error in chrome://device-log/.

Then I tried to send a report to the same device using a Windows 10 machine, and I can send buffers up to 1KB.

There is a way to change the max. value? from browser settings? or OS settings?

Thanks

sendReport() fails with DOMException

It says DOMException: Failed to write the report.
However, I am connected to the device (it keeps sending ordered numbers every 300ms).

The exception also has a name: "NotAllowedError".
What am I supposed to do with that?? I am the administrator, I enabled webhid and I'm running Chrome Dev. What else am I supposed to do?

USB Product Version

I noticed USB Product Version is not available in WebHID after pairing.

We use USB Product Version to distinguish device revisions that present identically to the user but have incompatible firmware update needs. Without this, we are not able to safely provide firmware updates over WebHID, at least for devices which have more than one revision.

Please consider adding this part of the USB spec. Thank you!

Blocklist implementation conflicts with Chrome

@agl of the chrome team [directs developers who want to communicate with U2F (FIDO/WebAuthN device) to use WebHID.(https://bugs.chromium.org/p/chromium/issues/detail?id=1179077)

subject: Issue 1179077: Disallow tunneling of unrelated protocols over U2F interfaces
Chromium allows websites relatively direct communication with security keys. This is permitted because:

a) we understand the security and privacy implications of the CTAP protocols, and
b) we formulate the protocol messages ourselves and are reasonably sure that websites won't be able to exploit bugs in security keys because the variable fields are subject only to simple processing by the security key.

Both of these factors are nullified if other protocols are tunneled with the security key protocols, which some devices have done. This is presumably attractive because the U2F API does not have a UI and, while that will be going away and WebAuthn does have a UI, some devices simply put up with flashing the WebAuthn UI repeatedly.

Websites that wish to communicate with USB devices can use the WebUSB and WebHID APIs to do so without such shenanigans.

SoloKeys supports seeding their security keys via a CTAP protocol (the one explicitly permitted -- no tunneling) an so we (me/DiceKeys) have built a web app to do that using WebHID.

By introducing a block list that removes all access to any device that supports FIDO, with no ability for vendors to opt out, it would seem that Google's @nodebug has made it impossible to do what Google's @agl is telling developers they should do ("Websites that wish to communicate with USB devices can use the WebUSB and WebHID APIs to do so").

Having written an app that assumes I'll be able to do what @agl directs developers to do, I would hope that the spec can either remove FIDO from the block list, or to supplement the block list with an allow list that allows vendors to override it.

Multiple applications, same device

Is there any or will there be any way to know how many WebHID apps have a device open? Apps are not very good at cooperating. With a microphone device, there is an issue that we have experienced in our product. The mic is opened and "sync'd" to our conferencing application for mute/unmute. The user mutes the device but goes to another app, say a softphone like Skype, and that app unmutes it (unbeknownst to the user this also unmutes our app). User talks on phone: "I'm in the middle of this stupid conference". Bad. Not sure anything can be done to fully solve this type of issue except tell the user to be careful but perhaps there is a way for use to tell whether another app has also opened this device? Thanks for any thoughts.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.