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

Need to identify previously used port #128

Open
radio-miskovice opened this issue Mar 10, 2021 · 15 comments
Open

Need to identify previously used port #128

radio-miskovice opened this issue Mar 10, 2021 · 15 comments

Comments

@radio-miskovice
Copy link

radio-miskovice commented Mar 10, 2021

Hello, I have this kind of use case:

A web app accesses at least two functionally different devices on serial ports. For reference, it is a serial interface to transceiver control (CAT) and Arduino keyer - but this is not essential. The serial ports are actually USB devices of various manufacturers - e.g. CP2102, CH340, PL2303 etc. Raspberry Pi PICO (and, in principle any embedded device implementing serial port CDC) is also not excluded, although not in use, yet.

The web application maintains some kind of persistence to serve as a kind of ham radio logger and radio/keyer control panel. Therefore it is supposed to restore its previous state after reload - retrieve the log and configuration from LocalStorage or IndexedDB (also not essential) - and (automatically) reconnect previously connected devices.

Problem:

  • after reloading the app, the operator has to reconnect both serial devices again, manually
  • in the current API there is no reference as to which serial device is which, just COMx port name (in Windows) - and that's not visible in API, only in the pop-up dialogue window.

Task to be solved:

  • once the user has manually approved access to the port (in the connect dialog it subsequently appears as "paired"), the app should be able to obtain and keep some persistent identification of the respective connected device (e.g. VID, PID and serial number). So that next time it is launched, it could requestPort() with some kind of ID or structure that would immediately choose the exact device (if it is connected).

For those with extreme security concerns, I would like to repeat and point out that we talk about devices previously authorized by the user to be connected and to serve the given purpose as application peripheral.

Early implementation would be highly appreciated, of course :-)

Thank you
Jindra
OK4RM

@radio-miskovice radio-miskovice changed the title Need to remember previously used port Mar 10, 2021
@reillyeon
Copy link
Collaborator

I wrote up some notes about this on #19 and the corresponding implementation issue is Chromium issue 1074383. The plan is to add a 'id' member to the dictionary returned by getInfo(). The value of this ID will be unique to a given port but different from the value returned to a different site for the same port. This mitigates fingerprinting concerns. This ID can be remembered by the site in order to distinguish between two ports and assign them the same roles in a later session.

@thegecko
Copy link

thegecko commented Apr 3, 2021

It's great to hear there is already a plan to implement a unique identifier with WebSerial. I can't see anything in the specification, is this still pending?

There are a few real-world use cases for this we have today:

  • It's very common to have multiple devices attached to the system with the same VID/PID (see Mbed devices which are all the same). This makes it impossible to work with multiple devices and keep track of them.

  • State management. Extra state for a device (e.g. serial port baudrate) could be stored separately. Without a unique reference to the device when plugged in, this can't be guaranteed to be applied to the correct device.

  • Most importantly is the need for a reference for a device to go across logical boundaries. We have a use case where we undertake heavy USB access (currently using WebUSB) from within a webworker, but the device needs to be selected in the main UI thread.
    Therefore we use serialNumber to reacquire access to the device in the webworker as you cannot pass the device between the contexts. The same is true for protocols such as the Debug Adapter Protocol. To model this in WebSerial, you'd save the unique identifier in the main thread, then use getPorts() in the other context and filter by the identifier.

A strong reason for the unique identifier to be serialNumber is to allow soft links between devices using Web-* connections (WebUSB, WebSerial, WebHID, etc.). For example, if a user has already selected a WebSerial device, the serialNumber from it could be used to filter a further selection for WebUSB access with navigator.usb.requestDevice().
If serialNumber is also exposed in SerialPortRequestOptions, the opposite would also be possible.

It would be good to see some consistency between the WebUSB, WebHID and WebSerial specifications to allow such soft-linking.

Please see WICG/webhid#34 (comment) for an identical issue raised for WebHID

@csarnataro
Copy link

Hi @reillyeon , do you have any updates about adding an id to getInfo(), as you're mentioning in your comment above?
I'm working to update the Arduino Web IDE, to move away from the deprecated Chrome App, and embrace the PWA approach using the Web Serial API.
I think it would be great, in terms of user experience, to have the possibility to skip the selection step, if the device has already been connected before, in a deterministic way. With the current implementation, if I'm not mistaken, users have to reconnect every time the page is reloaded, if we don't have a unique way to associate the port with the device.
And BTW, I think the option to get a unique id based on the site the user is visiting, is great in terms of privacy.

@reillyeon
Copy link
Collaborator

@csarnataro, ports have have been connected before are already returned by the navigator.serial.getPorts() method under many circumstances (see details below). What is missing and tracked by this issue is a way to differentiate between two ports which, for example, have the same USB vendor and product IDs since those are the only properties currently exposed by getInfo().

The details on how getPorts() works:

Chromium tries to remember devices that it has seen before so that when the user makes the decision to grant a site access to a device that decision is remembered for later so that they don't need to make that decision over and over again. Unfortunately there aren't always enough identifiable properties of the device for the browser to confidently remember it. For example, a USB device which doesn't have a serial number is indistinguishable from any other device of the same model. The exact heuristics vary a bit between platforms. On Windows ports are almost always remembered because COM port numbers are stable identifiers managed by the operating system and based on complex heuristics like the location of the device on the USB bus. On Linux a serial number is required because the first USB serial port is always /dev/ttyUSB0.

@Gamadril
Copy link

Any chance to solve the issue in the near future?

@reillyeon
Copy link
Collaborator

I can't guarantee a timeline but we've been talking about the class of issues around this as part of our project planning process.

@PropGit
Copy link

PropGit commented Jul 18, 2022

Thanks everyone for bringing this up and @reillyeon and team for working on a solution. I like your port+site_specific getInfo().id idea; that would work just fine for us.

We too need this functionality since our use cases include the possibility for more than one simultaneously-connected microcontroller (each of which our users may be developing separate code for) and also common cases where students need to connect/disconnect multiple times during their development phase. Without this unique identifier to an already_granted port, I believe there is no way for us to provide the same level of nice port logistics handling that we implemented in native apps long ago.

@jessekingf
Copy link

Any updates or a timeline for getting this addressed?

@reillyeon
Copy link
Collaborator

I know that it looks like this issue hasn't been making much progress but I assure you our team is aware of the need here and it is on our roadmap.

@jessekingf
Copy link

Hi @reillyeon, I am checking in to see if there has been any progress on this issue and if you could provide a general timeline for addressing it. Thanks!

@reillyeon
Copy link
Collaborator

Hi @reillyeon, I am checking in to see if there has been any progress on this issue and if you could provide a general timeline for addressing it. Thanks!

If there's one thing I've learned as a software engineer it's that I am terrible at estimating timelines. This is on our project roadmap. It's not the next thing we're working on but it's near the top.

@gbmhunter
Copy link

I'm developing an open-source serial port application called NinjaTerm (https://ninjaterm.mbedded.ninja/) and I also would love this feature! I recently migrated NinjaTerm from an Electron-based App to a PWA and being able to "exactly" identify previously allowed ports for automatic opening the next time the app loads would greatly improve the user experience.

@Azq2
Copy link

Azq2 commented Apr 22, 2024

I'm surprised that any reliable port identifiers still do not exist in the standard.

@PropGit
Copy link

PropGit commented Apr 23, 2024

Any chance this feature can be added before the final deadline of Chrome App support or ChromeOS, Jan 2025?

@reillyeon - Is it currently considered impossible to definitively identify every USB device across all platforms unless it has a serial number (along with other identifying info) when it is being connected/disconnected throughout a session?

If that's the case, how about the next best thing...

  • provide a unique identifier (per site, as you noted) to each connected USB device,
  • for those devices that have serial numbers, have the same identifier (per site) re-applied once reconnected after a recent disconnect,
  • and for those devices that don't have a serial number, give the unique identifier (per site) a recognizable feature indicating this identifier will not survive disconnect/reconnect events.

That should solve the problem as much as is possible and gives the app awareness of sticky and non-sticky identifiers that may lead to some kind of graceful mitigation for certain use cases.

@hebnern
Copy link

hebnern commented May 27, 2024

I am developing a web app to interact with a USB composite device which exposes two CDC interfaces. I need to be able to positively identify each of these ports, ideally using the iInterface string which is unique for each. Failing that we must rely on the user to select the correct port for each function which is a guessing game at best, and once the page is reloaded we have no way to even restore the selections that the user previously made.
As a workaround, I have moved to using WebUSB and a tweaked webserial-polyfill that let's me manually link up serial port objects to the appropriate interfaces/endpoints. However this comes with the limitation that users must manually detach the CDC/ACM driver that the system attaches to the device when it enumerates (https://issues.chromium.org/issues/40137537?pli=1).
Given these two issues, I haven't found a way to provide a seamless user experience. Adding another vote for this issue to be prioritized.

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