Using a serial USB port on raspberry pi

Hi, I’m building a snap that runs a daemon app that uses a serial port (/dev/ttyUSB). This snap has to run on ubuntu core arm64 raspberry pi 4.

From reading other posts, I see a few options:

  1. Expand the raspberry pi gadget with a serial interface.
    • This requires me to build an image though, while: error: snap "ubuntu-image" is not available on beta for this architecture (arm64) but exists on other architectures (amd64, i386).
  2. Use classic confinement.
    • Not really nice, and I’m not sure I can install that on ubuntu core.
  3. Use hotplug.
    • Experimental feature, and I don’t see how to use this for auto connect.

What would be the best way to continue here?

You can cross build images from an amd64 device to target an arm64 device easily, just run the same ubuntu-image command on amd64 instead of your target device.

This would be used with auto-connect via greedy plugs, see for example the arduino snap which had this approved recently.

You can cross build images from an amd64 device to target an arm64 device easily, just run the same ubuntu-image command on amd64 instead of your target device.

Oh, the docs mention: " The ubuntu-image command needs to be run on the same architecture as the target image and needs only the filename of the model assertion to build an image."

This would be used with auto-connect via greedy plugs, see for example the arduino snap which had this approved recently.

So if my device shows up as - snapd:cp2102cp2109uartbrid (allows accessing a specific serial port), then in my snapcraftyaml, I need:

apps:
  my-app:
    plugs:
      - cp2102cp2109uartbrid

plugs:
  serial-port:
    allow-auto-connection:
      slots-per-plug: 1

Is that about right?

no all you need to do is have:

apps:
  my-app:
    plugs:
      - serial-port

and then the snap declaration will be issued by the store team which will automatically connect your serial-port plug to the snapd:cp2102cp2109uartbrid plug when installed. I would recommend trying this out first before building a purpose built gadget as that is more maintenance than using greedy hot plugs, which were designed for this exact problem.

this doc is incorrect, thanks for letting us know we will make sure that is updated

CC @degville when back, that sentence should not say it needs to be run on the same architecture as the target image. The architecture is encoded into the model assertion.

Alright will try that, thanks :slight_smile: Yeah, I was also not a big fan of maintaining a gadget for this purpose.

Nice to know it works though, then I can also make images with preinstalled snaps :slight_smile:

One more question: what path would the program connect to? Does it have to be something like /dev/serial/by-id/...?

I’ve fixed this - thanks for letting me know. Should be published soon.

So this is a bit nebulous, as it depends. We don’t currently expose any of the serial port slot attributes like the path or the vendor ID/product ID, etc. so there isn’t a way for your snap to know directly what path the newly provided serial port shows up as, i.e. /dev/ttyAMA0 or /dev/ttyUSB0, etc. What you could try to do is have a post-connect-serial-port hook which just tries to read every serial port path you expect and if it is able to read/connect to one, then save that by appending to a list saved with snapctl set serial-ports=[/dev/ttyAMA0,/dev/ttyUSB0] and then your main app could read that list of serial-ports.

This is an admitted shortcoming of hotplug that we hope to address sometime soon, see “Current limitations” section on https://snapcraft.io/docs/hotplug-support