electrolama / llama-bsl

Python cross-platform script to upload firmware via the serial boot loader onto the CC13xx, CC2538 and CC26xx SoC.
BSD 3-Clause "New" or "Revised" License
10 stars 1 forks source link

Add adapter model USB discovery which can be used to automatically select compatible firmware images #9

Open Hedda opened 3 years ago

Hedda commented 3 years ago

Adapter model USB discovery could be used to automatically select compatible firmware images.

Wondering if llama-bsl could add a similar USB discovery feature to that which Home Assistant recently added for Zigbee adapters.

https://www.home-assistant.io/blog/2021/09/01/release-20219/#usb-discovery

https://www.home-assistant.io/integrations/zha/#discovery-via-usb-or-zeroconf

https://www.home-assistant.io/integrations/usb/

USB discovering whitelist is currently maintain in code and they use a combination of the description in "Product Description String” (a.k.a. device descriptor/descriptors) in combination with its “Vendor ID” (a.k.a. vid hex) and “Product ID” (a.k.a. pid hex), but in the future they could potentially also extent USB discovery to use other data like manufacturer, etc.. More info on that here:

https://community.home-assistant.io/t/community-help-wanted-to-whitelist-all-compatible-zigbee-and-z-wave-usb-adapters-for-automatic-discovery-in-home-assistant-os/344412

PS: Home Assistant also use the same USB discovery feature for detecting Z-Wave USB dongles:

https://www.home-assistant.io/integrations/zwave_js/#discovery-via-usb

omerk commented 3 years ago

This is a great idea @Hedda, although this would only work for USB based devices (using the VID+PID+Descriptor String) and not for boards that have the radios wired straight to UART (like zoe, zoe2, etc).

Adding this to the v1.0 milestone

Hedda commented 3 years ago

although this would only work for USB based devices (using the VID+PID+Descriptor String) and not for boards that have the radios wired straight to UART (like zoe, zoe2, etc).

I don't have any UART radios but would it be possible to use a serial scan, list, and open probe for plugged-in serial devices?

https://github.com/jleben/python-serial/blob/master/examples/scan.py

That is, basically try to open each and every serial port then do a probe and check for a response to find a TI bootloader?

https://stackoverflow.com/questions/22081560/python-testing-serial-ports-for-answer

https://stackoverflow.com/questions/24214643/python-to-automatically-select-serial-ports-for-arduino

https://stackoverflow.com/questions/24493379/pyserial-how-to-know-if-a-serial-port-is-free-before-open-it

Maybe by trying to connect to read and firmware? Alternatively just list all serial ports with something connected to them?

zigpy-znp look to have tests to check uart connection?

https://github.com/zigpy/zigpy-znp/blob/dev/tests/test_uart.py

https://github.com/zigpy/zigpy-znp/tree/dev/tests/application

zigpy-znp tools also look to have function for reading all possible NVRAM entries?

https://github.com/zigpy/zigpy-znp/blob/dev/TOOLS.md

Otherwise, since llama-bsl is yours and you make zoe and zoe2 another option is to hardcode probes specifically for those?

Regardless, if possible always first give users option to manually select or type in the serial port before doing scan and probe:

https://stackoverflow.com/questions/11750926/identifying-serial-usb-device-python

"No matter how you configure your device, at some point you're probably going to have to ask the user where the port is, or poll all serial devices for a known response. (Polling has it's pitfalls though, so read on!). Unlike USB devices, there is no vendor/device ID that is made known to the OS when you attach a plain-old serial device.

First you need to find the serial ports. Here's a question that might help: What is the cross-platform method of enumerating serial ports in Python (including virtual ports)?.

https://stackoverflow.com/questions/11303850/what-is-the-cross-platform-method-of-enumerating-serial-ports-in-python-includi

Once you have a list of serial ports, you could ask the user whether they know which one to use. If they do, problem solved!

If they don't, you could offer to poll ALL serial devices with some data that you know will yield a certain response from your device. Keep in mind though that if the user has other serial devices attached, your string of "hello" bytes might actually be the self-destruct sequence for some other device! Hence, you should warn the user that polling may interfere with other devices, and always prompt them before you do so.

Without knowing more about your code (eg. what comms framework, if any, you're using; are you doing this in the console or are you using a GUI toolkit, etc), it's impossible to say what the best way to code this might be. In the simplest case, you could just loop over all of your serial devices, send the greeting and check for a response. (You could also do this in parallel: loop once for the greeting, and loop again to check what's in the buffer. If you're going to get more fancy than that, use a proper library.)"

omerk commented 3 years ago

I am happy with the idea of probing serial devices, as long as it is opt-in. In other words, explicitly requested by the user with a command line argument (--probe?). As you've referenced above, sending a string down an unknown serial device is not a good idea. It's not likely that there would be mission critical serial devices plugged into a Pi/server running home automation stuff, but then again assumptions are dangerous things in engineering.

Hedda commented 2 years ago

I am happy with the idea of probing serial devices, as long as it is opt-in. In other words, explicitly requested by the user with a command line argument (--probe?). As you've referenced above, sending a string down an unknown serial device is not a good idea. It's not likely that there would be mission critical serial devices plugged into a Pi/server running home automation stuff, but then again assumptions are dangerous things in engineering.

BootTerm (bt) logic methods for automatic port detection seems like logical processes to take inspiration from:

https://github.com/wtarreau/bootterm

The program is written in C so can not reuse code but their readme describes their two different optional processes available:

https://github.com/wtarreau/bootterm/blob/master/README.md

https://github.com/wtarreau/bootterm/blob/master/README.md#using-bootterm-to-detect-ports

https://github.com/wtarreau/bootterm/blob/master/README.md#waiting-for-a-new-serial-port

https://github.com/wtarreau/bootterm/blob/master/README.md#waiting-for-any-port

By default, it will try connecting to the last registered serial port, as that will usually be the most recently connected USB adapter.