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

Questions around supporting devices with USB serial emulation #71

Closed
noopkat opened this issue Oct 12, 2019 · 5 comments
Closed

Questions around supporting devices with USB serial emulation #71

noopkat opened this issue Oct 12, 2019 · 5 comments

Comments

@noopkat
Copy link
Contributor

noopkat commented Oct 12, 2019

The context of this issue is that I'm porting AVRGirl-Arduino to work with web serial.

There are some Arduino boards out there sporting an Atmel 32u4 chip that emulates the USB serial port. In order to software reset these boards into "bootloader mode" for uploading new firmware, you connect to them once at a baud rate of 1200 and then immediately disconnect. Once the chip reboots into bootloader mode, the serial emulation also comes back up. The device often presents itself as a different device in this mode by either differences in vendor / product id, or it shows up on a different COM port entirely which is a common occurrence on windows.

Let's walk through a user wanting to flash blink.hex to their 32u4 based Arduino in a browser interface with web serial for the very first time:

  1. User clicks an 'upload' button, which is the required user gesture to grant first time permission for pairing the device.
  2. They find their Arduino board in the filtered permission prompt, and grant access
  3. The webpage then runs code to open the port, with the correct baud rate specified when requesting the port
  4. Board resets, which also takes down the active emulated serial port connection
  5. Board finishes booting, USB serial emulation is back up, and the board presents itself as a slightly different device (product id change, or something similar)
  6. At this point I am a little lost - I theoretically believe at this point that I cannot reconnect to the Arduino board automatically despite having permission and having paired with the board in the previous steps.

My questions here are:

  1. Am I making assumptions about how the device is attached to the permission grant? Is this permission grant linked to all of the available metadata about the device at the time of requesting it?
  2. Can I still use the original serialPort instance I was given before the disconnection occurred? If a port hop has occurred since, I assume that detail change was not tracked and updated by the Web Serial internals?
  3. Do I need to write code such that I require another user gesture to occur after the device resets, in order to open another requestDevice prompt with a slightly different filter? 
  4. If (3) is required, we commonly have 8 seconds or so where bootloader mode waits for an initial instruction before it exits back to running the user program again. Getting a new permission grant from the user after attempting to get them to perform another gesture in order to do so seems like it'd be unreliable and a fragile flow.

My other question which is slightly related is - does navigator.serial.getPorts behave in the same way as the WebUSB spec's navigator.usb.getDevices?

If it's required to have the two separate permission grants for the same device, perhaps a good flow could be an initial one time only "setup" sequence where the user is asked to run through the two permission prompts, and then they're ready to use the main features of webpage itself for uploading new firmware, etc etc. Even with this solution the 8 second timing requirement could present accessibility difficulties for some users, so I'd prefer for there to be a slightly better flow for that reason.

Thanks for considering these questions and scenarios. The web serial spec is not quite fully fleshed out yet so I got a bit stuck on some of this while porting AVRGirl-Arduino to web serial and supporting some of the Arduino boards.

🙇‍♀

@reillyeon
Copy link
Collaborator

Thank you for outlining this scenario.

  1. Am I making assumptions about how the device is attached to the permission grant? Is this permission grant linked to all of the available metadata about the device at the time of requesting it?

In today's experimental implementation in the Blink engine a permission grant is attached to the device node path (COM1, /etc/ttyS0, etc.) and lasts until the user agent is quit. This is not the desired end state for a couple of reasons. I envision this will work similarly to WebUSB and be specified in terms of device properties such as USB vendor/product IDs, Bluetooth MAC addresses and physical bus paths. Ideally the user will also be in control of the duration of the permission grant.

Some of this can be specified (such as which identifiers are used) and some is up to the user agent implementation.

  1. Can I still use the original serialPort instance I was given before the disconnection occurred? If a port hop has occurred since, I assume that detail change was not tracked and updated by the Web Serial internals?

If from an operating system perspective a new device has connected with different hardware IDs then the original SerialPort instance is not valid for communicating with this new device. I have considered adding a reconfigure() method which would allow a site to change parameters such as baud rate without closing the port. This is required for some protocols but doesn't sound like it would work for this scenario.

  1. Do I need to write code such that I require another user gesture to occur after the device resets, in order to open another requestDevice prompt with a slightly different filter?

Yes.

  1. If (3) is required, we commonly have 8 seconds or so where bootloader mode waits for an initial instruction before it exits back to running the user program again. Getting a new permission grant from the user after attempting to get them to perform another gesture in order to do so seems like it'd be unreliable and a fragile flow.

This is a difficult scenario. With a chooser-based permission the user must select a particular device. A site can't ask for permission for a device that, from the user agent's perspective, doesn't exist. The danger here is that the user agent can't properly describe this hypothetical device in a way in which the user can make an informed choice.

My other question which is slightly related is - does navigator.serial.getPorts behave in the same way as the WebUSB spec's navigator.usb.getDevices?

That is the intention.

@noopkat
Copy link
Contributor Author

noopkat commented Oct 23, 2019

thanks for answering all of my questions so clearly ✨
I think going forward once it's possible, I'll lean towards the 'setup mode' for 32u4 boards where the user runs through both permission grants at once but the board is not flashed. Then, I can show them the regular UI and make use of the navigator.usb.getDevices to run through the reset and upload flows back-to-back now that the permission requirements are satisfied.

@conradopoole
Copy link

conradopoole commented Jun 17, 2021

Thank you for outlining this scenario.

  1. Am I making assumptions about how the device is attached to the permission grant? Is this permission grant linked to all of the available metadata about the device at the time of requesting it?

In today's experimental implementation in the Blink engine a permission grant is attached to the device node path (COM1, /etc/ttyS0, etc.) and lasts until the user agent is quit. This is not the desired end state for a couple of reasons. I envision this will work similarly to WebUSB and be specified in terms of device properties such as USB vendor/product IDs, Bluetooth MAC addresses and physical bus paths. Ideally the user will also be in control of the duration of the permission grant.

Some of this can be specified (such as which identifiers are used) and some is up to the user agent implementation.

  1. Can I still use the original serialPort instance I was given before the disconnection occurred? If a port hop has occurred since, I assume that detail change was not tracked and updated by the Web Serial internals?

If from an operating system perspective a new device has connected with different hardware IDs then the original SerialPort instance is not valid for communicating with this new device. I have considered adding a reconfigure() method which would allow a site to change parameters such as baud rate without closing the port. This is required for some protocols but doesn't sound like it would work for this scenario.

  1. Do I need to write code such that I require another user gesture to occur after the device resets, in order to open another requestDevice prompt with a slightly different filter?

Yes.

  1. If (3) is required, we commonly have 8 seconds or so where bootloader mode waits for an initial instruction before it exits back to running the user program again. Getting a new permission grant from the user after attempting to get them to perform another gesture in order to do so seems like it'd be unreliable and a fragile flow.

This is a difficult scenario. With a chooser-based permission the user must select a particular device. A site can't ask for permission for a device that, from the user agent's perspective, doesn't exist. The danger here is that the user agent can't properly describe this hypothetical device in a way in which the user can make an informed choice.

My other question which is slightly related is - does navigator.serial.getPorts behave in the same way as the WebUSB spec's navigator.usb.getDevices?

That is the intention.

@reillyeon Would it be possible to reconsider this reconfigure() method? Most microcontrollers boot up and start listening on a Serial port at an specific baud rate but allow for clients to change the baud rate via commands. For instance in this project https://github.com/esphome/esp-web-tools for Flashing ESP devices over serial, most of the USBtoUART chips on those boards support speeds well above 115200, but once the port is open via Web Serial, and after issuing the command to change the baud rate, there is no way on the client side to also make that change.

@reillyeon
Copy link
Collaborator

I've broken the request for a reconfigure() method out into a new issue. @noopkat, if you don't mind I think I can close this issue since your questions were answered.

@noopkat
Copy link
Contributor Author

noopkat commented Jun 25, 2021

thanks @reillyeon 👍

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

3 participants