Cannot open /dev/ttyS4

I have a node.js snap trying to access the ttyS4 (GPS) data. However I get this error:

(node:5643) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Error: Permission denied, cannot open /dev/ttyS4

I’ve seen samples where people are using the serial-port interface, but there are no interfaces called serial-port installed on the device, so I tried connecting kernel-module-control and hardware-observe. There is an interface called caracalla:ttys4, so I tried connecting that on too.

According to the documentation: “Note that the slot (serial-port) is meant to be implemented by a gadget snap (this is not provided by the core snap)”. I don’t know what that means, but serial-port is not in the list of interfaces…

Here is the snapcraft.yaml:

...
apps:
  microservicebus-node:
    command: bin/startsnap
    plugs:
    - kernel-module-control
    - hardware-observe
    - ubx
parts:
  node:
    source: https://github.com/qbranch-code/microservicebus-node.git
    source-branch: master
    plugin: nodejs
    node-engine: 7.10.0
    stage-packages: [python2.7, build-essential]
    node-packages: [serialport]

After i have created the snap and installed it, I ran:

snap connect microservicebus-node:kernel-module-control core:kernel-module-control
snap connect microservicebus-node:hardware-observe core:hardware-observe
snap connect microservicebus-node:ubc caracalla:ttys4

Checking the interface connections using snap interfaces microservicebus-node:

Slot                    Plug
caracalla:ttys4         locationd:ubx,microservicebus-node:ubx
:hardware-observe       caracalla,ccm-wda,dcc,dcm,microservicebus-node,udisks2
:kernel-module-control  caracalla,dcc,dcm,microservicebus-node

All looks good, but running the application gives me:

(node:5643) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Error: Permission denied, cannot open /dev/ttyS4

Thank you!

the gadget of your device needs to provide a serial interface (check with snap interfaces) that your microservicebus-node should then connect to via a plug …

oh, sorry, i missed the “caracalla:ttys4” bit … so there is a serial interface you can use … but you need to define it in the plugs section of your app …

Thank you for your reply!

I thought that was the same thing as:

snap connect microservicebus-node:ubc caracalla:ttys4

But fair enough. How do i add it to the plugs section:

apps:
  microservicebus-node:
    command: bin/startsnap
    plugs:
    - kernel-module-control
    - hardware-observe
    - caracalla:ttys4

Using the config above results in:

INFO snap "microservicebus-node" has bad plugs or slots: caracalla:ttys4 (unknown interface)

Thank you!

You can add just serial-port plug and instruct the user to plug it into ttys4. You cannot refer to product names or specific plugs like that.

Thanks. I updated my app plugs to user serial-port:

apps:
  microservicebus-node:
    command: bin/startsnap
    plugs:
    - kernel-module-control
    - hardware-observe
    - serial-port

And continued connecting the plugs:

sudo snap connect microservicebus-node:kernel-module-control core:kernel-module-control
sudo snap connect microservicebus-node:hardware-observe core:hardware-observe
sudo snap connect microservicebus-node:serial-port caracalla:ttys4

Checked interfaces…

snap interfaces microservicebus-node
Slot                    Plug
caracalla:ttys4         locationd:ubx,microservicebus-node:serial-port
:hardware-observe       caracalla,ccm-wda,dcc,dcm,microservicebus-node,udisks2
:kernel-module-control  caracalla,dcc,dcm,microservicebus-node
:network                ccm-wda,dcc,dcm,docker,microservicebus-node,snapweb,tpm2,uefi-fw-tools,wifi-ap,wpa-supplicant
:network-bind           ccm-wda,dcc,dcm,docker,microservicebus-node,snapweb,tpm2,udisks2,wifi-ap
-                       microservicebus-node:home
-                       microservicebus-node:ttys4

Still… Permission denied, cannot open /dev/ttyS4

:disappointed:

The output of snap interfaces there is confusing (we will soon introduce a new command that shows connections) so you may not have noticed that nothing is connected to your ttys4 plug.

One note of clarification:

In your application you should not hardcode things like /dev/ttyS4 or “ttys4” plug names. You should accept a serial-port plug. Once connected a connect hook can tell your application where the actual serial port is and that it is now connected (or disconnected).

Still, to get going just connect your plug to the desired slot.

Yes I noticed that, but it’s a “global” plug I forgot to remove…:

plugs:
  ttys4:
    interface: serial-port
    path: /dev/ttyS4

I don’t think it should have any affect, but i’ll rebuild and get back

This is wrong still, the plug side cannot designate a path. Path comes from the slot you connect to. It’s not static. Just declare a plug called serial-port (not ttys4) and then at runtime connect it to the serial port corresponding to ttyS4

I know (now)… just wanted to show what added that plug…

Anyway…updated the yaml and here are the interfaces now:

Slot                    Plug
caracalla:ttys4         locationd:ubx,microservicebus-node:serial-port
:hardware-observe       caracalla,ccm-wda,dcc,dcm,microservicebus-node,udisks2
:kernel-module-control  caracalla,dcc,dcm,microservicebus-node
:network                ccm-wda,dcc,dcm,docker,microservicebus-node,snapweb,tpm2,uefi-fw-tools,wifi-ap,wpa-supplicant
:network-bind           ccm-wda,dcc,dcm,docker,microservicebus-node,snapweb,tpm2,udisks2,wifi-ap
-                       microservicebus-node:home

Issue is the same:
Permission denied, cannot open /dev/ttyS4

Can you look at dmesg | grep DENIED please?

[   28.257505] audit: type=1400 audit(1502299283.079:120): apparmor="DENIED" operation="capable" profile="snap.network-manager.networkmanager" pid=1867 comm="NetworkManager" capability=1  capname="dac_override"
[   28.299545] audit: type=1107 audit(1502299283.123:121): pid=1513 uid=100 auid=4294967295 ses=4294967295 msg='apparmor="DENIED" operation="dbus_method_call"  bus="system" path="/org/freedesktop/login1" interface="org.freedesktop.login1.Manager" member="Inhibit" mask="send" name=":1.1" pid=1831 label="snap.modem-manager.modemmanager" peer_pid=1530 peer_label="unconfined"
[   29.106317] audit: type=1400 audit(1502299283.927:125): apparmor="DENIED" operation="open" profile="snap.uefi-fw-tools.fwupd" name="/sys/bus/usb/devices/" pid=1605 comm="fwupd" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
[   29.107096] audit: type=1400 audit(1502299283.927:126): apparmor="DENIED" operation="open" profile="snap.uefi-fw-tools.fwupd" name="/sys/bus/usb/devices/" pid=1605 comm="fwupd" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
[   29.107754] audit: type=1400 audit(1502299283.927:127): apparmor="DENIED" operation="open" profile="snap.uefi-fw-tools.fwupd" name="/sys/bus/usb/devices/" pid=1605 comm="fwupd" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
[   29.123505] audit: type=1400 audit(1502299283.943:128): apparmor="DENIED" operation="open" profile="snap.uefi-fw-tools.fwupd" name="/sys/bus/usb/devices/" pid=1605 comm="fwupd" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
[   88.385880] audit: type=1107 audit(1502299343.834:305): pid=1513 uid=100 auid=4294967295 ses=4294967295 msg='apparmor="DENIED" operation="dbus_signal"  bus="system" path="/org/freedesktop/login1" interface="org.freedesktop.login1.Manager" member="SessionNew" name=":1.1" mask="receive" pid=1831 label="snap.modem-manager.modemmanager" peer_pid=1530 peer_label="unconfined"
[  140.529275] audit: type=1107 audit(1502299395.925:306): pid=1513 uid=100 auid=4294967295 ses=4294967295 msg='apparmor="DENIED" operation="dbus_signal"  bus="system" path="/org/freedesktop/login1" interface="org.freedesktop.login1.Manager" member="SessionNew" name=":1.1" mask="receive" pid=1831 label="snap.modem-manager.modemmanager" peer_pid=1530 peer_label="unconfined"

Looks alright doesn’t it?

This indicates the interface is connected. Your grep for DENIED indicates there are no denials for /dev/ttyS4. How are you trying to access the device? As root? As non-root? If it works as root but not non-root, check the permissions on the device with ls -l /dev/ttyS4 and/or getfacl /dev/ttyS4.

I suspect either you need to be root or your user needs to be added to the ‘dialout’ group. Note that allowing non-root users to use devices is being discussed in: Multiple users and groups in snaps

1 Like

That did the trick! Thanks!