Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

navigator.hid not available #1

Closed
TedNIVAN opened this issue Apr 3, 2019 · 27 comments
Closed

navigator.hid not available #1

TedNIVAN opened this issue Apr 3, 2019 · 27 comments

Comments

@TedNIVAN
Copy link

TedNIVAN commented Apr 3, 2019

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

@nondebug
Copy link
Collaborator

nondebug commented Apr 3, 2019

Hi Ted,

The WebHID implementation is incomplete, currently there's no way to experiment with it.

@TedNIVAN
Copy link
Author

TedNIVAN commented Apr 3, 2019

Thanks for replying.
Is this still an active project?

@nondebug
Copy link
Collaborator

nondebug commented Apr 3, 2019

Yes, still active, I expect we'll have a working implementation in Chrome Dev in a month or so.

@TedNIVAN
Copy link
Author

TedNIVAN commented Apr 3, 2019

Great!
Could we expect to have it embedded in future Chrome versions?
Is there a roadmap for the WebHID support?

@nondebug
Copy link
Collaborator

nondebug commented Apr 3, 2019

The current roadmap is to have it in Stable by Chrome 78, although that is probably optimistic.

@TedNIVAN
Copy link
Author

TedNIVAN commented Apr 4, 2019

Alright good to know!
One last question: Will it be possible to use it in PWAs?

@TedNIVAN
Copy link
Author

No clue about PWAs?

@nondebug
Copy link
Collaborator

Not sure yet. That said, it would surprise me if we couldn't expose this feature to PWAs given the nature of the feature and how we expect it to be used. Do you have a specific use case in mind?

@TedNIVAN
Copy link
Author

The power of Chrome.hid is that we can communicate to custom hid device on Windows, Mac, and Linux with the same code. However, we can't use it on Mobile devices... If the WebHID API get approved for PWAs, we'll be able to do so on Android (not sure about iOS).

@jammerxd
Copy link

Is this still active?

@TedNIVAN
Copy link
Author

TedNIVAN commented Aug 30, 2019

Hi there,

I got 2 questions:

1 - Could we still expect a release for Chrome version 78?

2 - Could this work on Chrome for Android devices?

Regards,

@nondebug
Copy link
Collaborator

Partial WebHID functionality is available in Chrome 78 behind a flag on desktop OSes. You will need to enable the "Experimental Web Platform Features" flag (chrome://flags/#enable-experimental-web-platform-features) and restart Chrome.

Android support is planned but there's no estimate yet for when it will be available.

To show the WebHID device chooser, call navigator.hid.requestDevice. A promise is returned that resolves to the selected device:

// Show device chooser dialog and wait for a selection.
let device = await navigator.hid.requestDevice({filters:[]});

Filters can be used to narrow the list of devices shown to the user:

// Only show devices with vendor ID 0x1234.
navigator.hid.requestDevice({filters:[{ vendorId: 0x1234 }]});

// Only show devices with a top-level collection with the Joystick usage (usage page 1, usage 4).
navigator.hid.requestDevice({filters:[{ usagePage: 1, usage: 4 }]});

The device must be opened before sending or receiving reports:

await device.open();
if (device.opened)
  console.log("Device is open.");

To register an input report event listener:

device.oninputreport = e => {
  console.log("Got input report from " + e.device.productName + " with ID " + e.reportId);
  handleInputReport(e.reportId, e.data);
}

To send an output report:

// Send a 5-byte output report with report ID 0x01.
device.sendReport(0x01, new Uint8Array([0x23, 0x45, 0x67, 0x89]));

There are a few known issues that we plan to address before default-enabling WebHID.

On Windows, each top-level HID collection is enumerated as a separate device. When a device exposes several top-level collections, it can be difficult to guide the user to select the correct one. In some cases you can use usage filters so that only the correct device is shown.

Persistent permissions are not yet implemented, so the user will need to grant permissions each time the device is connected or the page is loaded. With persistent permissions, Chrome will remember the devices that each origin is allowed to access. Devices that an origin has already been granted permission to access are included in navigator.hid.getDevices().

@TedNIVAN
Copy link
Author

TedNIVAN commented Aug 30, 2019

Thanks for this awesome reply!

How can I be notified when webhid is available for Android?

Is there a website?

@nondebug
Copy link
Collaborator

Here's the bug for WebHID on Android:

https://crbug.com/964441

No website yet... (unless you count this repo)

@TedNIVAN
Copy link
Author

I've checked it out and it says:
"WebHID will initially only be available on desktop versions of Chrome (Windows, Linux, Mac, Chrome OS) because the HID backend is not implemented on other platforms".

Maybe I've misinterpreted something but I think there is a HID backend for Android since it is based on a Linux kernel.

Moreover, there is a JAVA API available to access HID devices via an Android app.

@nondebug
Copy link
Collaborator

nondebug commented Sep 3, 2019

It's specifically the Chrome HID backend that isn't implemented on Android. Chrome has had support for HID devices for a while through the chrome.hid API, but it was never enabled on Android.

@TedNIVAN
Copy link
Author

TedNIVAN commented Sep 4, 2019

I hope this feature will come soon on Android. Thanks for the information.

@TedNIVAN
Copy link
Author

This might interest you

Learn the essentials of HID device development: https://usbhid.io/

@TedNIVAN
Copy link
Author

Partial WebHID functionality is available in Chrome 78 behind a flag on desktop OSes. You will need to enable the "Experimental Web Platform Features" flag (chrome://flags/#enable-experimental-web-platform-features) and restart Chrome.

Android support is planned but there's no estimate yet for when it will be available.

To show the WebHID device chooser, call navigator.hid.requestDevice. A promise is returned that resolves to the selected device:

// Show device chooser dialog and wait for a selection.
let device = await navigator.hid.requestDevice({filters:[]});

Filters can be used to narrow the list of devices shown to the user:

// Only show devices with vendor ID 0x1234.
navigator.hid.requestDevice({filters:[{ vendorId: 0x1234 }]});

// Only show devices with a top-level collection with the Joystick usage (usage page 1, usage 4).
navigator.hid.requestDevice({filters:[{ usagePage: 1, usage: 4 }]});

The device must be opened before sending or receiving reports:

await device.open();
if (device.opened)
  console.log("Device is open.");

To register an input report event listener:

device.oninputreport = e => {
  console.log("Got input report from " + e.device.productName + " with ID " + e.reportId);
  handleInputReport(e.reportId, e.data);
}

To send an output report:

// Send a 5-byte output report with report ID 0x01.
device.sendReport(0x01, new Uint8Array([0x23, 0x45, 0x67, 0x89]));

There are a few known issues that we plan to address before default-enabling WebHID.

On Windows, each top-level HID collection is enumerated as a separate device. When a device exposes several top-level collections, it can be difficult to guide the user to select the correct one. In some cases you can use usage filters so that only the correct device is shown.

Persistent permissions are not yet implemented, so the user will need to grant permissions each time the device is connected or the page is loaded. With persistent permissions, Chrome will remember the devices that each origin is allowed to access. Devices that an origin has already been granted permission to access are included in navigator.hid.getDevices().

Sending output reports works perfectly! However, it seems to have some issues on the API for receiving input reports.

I get an empty object while: console.log("data: ", e.data)
------------> data: DataView(1) {}

@mame82
Copy link

mame82 commented Dec 4, 2019

Hey guys,

used WebHID to demo a vulnerability in Logitech Wireless Receivers (https://twitter.com/mame82/status/1202224133217624065).

I noticed that navigator.hid is available on Android version of Chrome 78 and 79 Beta.

Anyways, there's no user dialog to grant permissions for USB device access (see Twitter stream for reference).

Will WebHID arrive on Chrome for Android?

implemented demo for reference

Demo page: https://mame82.github.io/munifying-web/

Source: https://github.com/mame82/munifying-web

@TedNIVAN
Copy link
Author

TedNIVAN commented Dec 4, 2019

Hi @mame82

As far as I know the WebHID backend is still not implemented for Android..

However you can give it a try using Chrome Canary on the Play Store. I think it might implement features of future version 80 at the time I'm writing this.

@mame82
Copy link

mame82 commented Dec 4, 2019

Hi @TedNIVAN,

seems you're right tried Chrome Canary and Dev in addition. No dice, doesn't even trigger a permission request, as other apps with USB access do.

Anyways, the code checks for navigator.hid === undefined to show an error, but it passes in all tested Chrome versions, once Experimental Web Platform features are enabled

@nondebug
Copy link
Collaborator

nondebug commented Dec 4, 2019

Ah, that's not right... thanks for the heads up. I've filed https://crbug.com/1030829 to track this in the Chromium bug repo.

@nondebug
Copy link
Collaborator

nondebug commented Dec 4, 2019

Will WebHID arrive on Chrome for Android?

We haven't committed to a timeline for this yet. In the short term we want to make WebHID available on desktop as a migration path for Chrome Apps that use the chrome.hid API. Probably the Android implementation will follow the stable launch of the API on desktop platforms.

Watch this bug for activity related to the Android implementation: https://crbug.com/964441

@nondebug
Copy link
Collaborator

nondebug commented Dec 4, 2019

Sending output reports works perfectly! However, it seems to have some issues on the API for receiving input reports.
I get an empty object while: console.log("data: ", e.data)
------------> data: DataView(1) {}

I think this is working as intended. DataView can't log its contents because it doesn't have an inherent element width. You can log the input report bytes by wrapping the underlying ArrayBuffer in a TypedArray like Uint8Array:

> let device = await navigator.hid.requestDevice({filters:[]});
> await device.open();
> device.oninputreport = (e) => { console.log(e.reportId, new Uint8Array(e.data.buffer)); };
1   <--- report ID
Uint8Array(63) [122, 131, 126, 128, 8, 0, 144, 0, 0, 12, 114, 253, 121,
0, 165, 254, 172, 255, 167, 1, 66, 30, 109, 5, 0, 0, 0, 0, 0, 23, 0, 0,
1, 111, 130, 55, 132, 31, 128, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 0, 0,
0, 128, 0, 0, 0, 128, 0, 0, 0, 0, 128, 0]   <--- report bytes

@dominiceden
Copy link

Great work on this guys, I've been having some fun integrating a simple React app with a USB foot pedal for controlling audio playback. It works very nicely on Mac OS X Catalina 10.15.4 and Chrome 83 with experimental web features turned on. Your hard work is much appreciated!

However, I've had no such luck with Windows 10 Pro and Chrome 83, even with experimental web features turned on. navigator.hid is undefined in the console so no connection attempts can even be made in Chrome. Is there definitely Windows 10 support here?

@reillyeon
Copy link
Contributor

This API is enabled by default in recent Chrome stable versions and is supported on Windows so I think this issue can be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants