flipperdevices / qFlipper

qFlipper — desktop application for updating Flipper Zero firmware via PC
https://update.flipperzero.one
GNU General Public License v3.0
1.06k stars 142 forks source link

Unable to connect on Fedora Linux #154

Open VoidField101 opened 1 year ago

VoidField101 commented 1 year ago

Describe the bug qFlipper is unable to connect to the Flipper Zero on Linux (Fedora 36) showing a "Permission Denied" error even though all the perimissions/udev rules are set correctly.

To Reproduce Steps to reproduce the behavior:

  1. Download qFlipper version 1.2.2
  2. Install the udev rules ./qFlipper-x86_64-1.2.2.AppImage rules install as described in the UI
  3. Start qFlipper (gui mode)
  4. Connect the Flipper and wait

Expected behavior Flipper should connect without issues

Actual behavior "Permission Denied" occurs

Additional troubleshooting

  1. I tried updating the Firmware via Bluetooth but the latest Firmware ("Release") didn't fix the issue.
  2. I tried restarting the Flipper zero multiple times and it didn't work
  3. Omitting all Hubs (connecting directly to the PC) didn't work
  4. Testing with picocom picocom /dev/ttyACM0 showed the Flipper Zero serial cli. Therefor a permission error is unlikely otherwise picocom should also fail.
  5. Giving my user the dialout role and logging in again.
  6. I checked the issue tracker and found that this issue is usually related to missing udev rules, so I made sure they are installed and even ran the sudo udevadm control --reload-rules && sudo udevadm trigger manually again to make sure they are loaded.
  7. I disabled Bluetooth on the Flipper Zero (Point 1. in the "How to fix")

The report must also include at least one of the following: image

LOG:

488 [APP] qFlipper version 1.2.2 commit ba67025d 2022-12-08T13:31:11
488 [APP] OS info: Fedora Linux 36 (KDE Plasma) 36 6.0.12-200.fc36.x86_64 Qt 5.15.2
502 [REG] Detected new device: VID_0x483:PID_0x5740
615 [DBG] Trying serial port  at /dev/ttyACM0
615 [DBG] Trying serial port  at /dev/ttyS0
615 [UPD] Fetched update information from https://update.flipperzero.one/firmware/directory.json
616 [UPD] Fetched update information from https://update.flipperzero.one/qFlipper/directory.json
648 [DBG] Trying serial port  at /dev/ttyACM0
648 [DBG] Trying serial port  at /dev/ttyS0
<Omitted because the same 2 lines ("Trying serial port") are repeated 99 times in the log>
3964 [DBG] Trying serial port  at /dev/ttyACM0
3964 [DBG] Trying serial port  at /dev/ttyS0
3981 [REG] Device initialization failed: Failed to find a suitable serial port
gsurkov commented 1 year ago

Judging by the log, it's still some sort of a weird permission issue (the port /dev/ttyACM0 has an empty serial number).

Please try running the development version and post the log here again.

The development version has an improved permission checking and error reporting, so it might help narrow down the problem.

VoidField101 commented 1 year ago

I'm getting the same error

463 [APP] qFlipper version 1.2.2 commit 84566a50 2023-01-01T18:59:28
464 [APP] OS info: Fedora Linux 36 (KDE Plasma) 36 6.0.12-200.fc36.x86_64 Qt 5.15.2
477 [REG] Detected new device: VID_0x483:PID_0x5740
606 [DBG] Trying serial port  at /dev/ttyACM0
606 [DBG] Trying serial port  at /dev/ttyS0
607 [UPD] Fetched update information from https://update.flipperzero.one/qFlipper/directory.json
607 [UPD] Fetched update information from https://update.flipperzero.one/firmware/directory.json
640 [DBG] Trying serial port  at /dev/ttyACM0
640 [DBG] Trying serial port  at /dev/ttyS0
...
3875 [DBG] Trying serial port  at /dev/ttyACM0
3875 [DBG] Trying serial port  at /dev/ttyS0
3892 [REG] Device initialization failed: Failed to find a suitable serial port

PS: Putting the Device into DFU / Recovery mode does actually work and let's me connect. Normal mode doesn't.

Also checked the permissions on the /dev/ttyACM0 devicefile. Owned by root, Group: dialout with a ACL set to allow read & write from any logged in user, just like the udev file is configured.

gsurkov commented 1 year ago

Was worth a try. It does also look weird to me that it tries to open /dev/ttyS0, but that might be nothing. Just for the completeness' sake, please give me the output of lsusb -d483:5740 -v (run it as a normal user while Flipper is connected and is NOT in dfu mode). Especially please pay attention to any errors.

I'll set up a test environment to see if it will be possible to reproduce this problem.

VoidField101 commented 1 year ago

Here is the full lsusb output:

lsusb -d483:5740 -v

Bus 007 Device 006: ID 0483:5740 STMicroelectronics Virtual COM Port
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass          239 Miscellaneous Device
  bDeviceSubClass         2 
  bDeviceProtocol         1 Interface Association
  bMaxPacketSize0         8
  idVendor           0x0483 STMicroelectronics
  idProduct          0x5740 Virtual COM Port
  bcdDevice            1.00
  iManufacturer           1 Flipper Devices Inc.
  iProduct                2 Flipper Atiw
  iSerial                 3 flip_Atiw
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x004b
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xc0
      Self Powered
    MaxPower              100mA
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         0
      bInterfaceCount         2
      bFunctionClass          2 Communications
      bFunctionSubClass       2 Abstract (modem)
      bFunctionProtocol       0 
      iFunction               0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol      0 
      iInterface              0 
      CDC Header:
        bcdCDC               1.10
      CDC Call Management:
        bmCapabilities       0x00
        bDataInterface          1
      CDC ACM:
        bmCapabilities       0x00
      CDC Union:
        bMasterInterface        0
        bSlaveInterface         1 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval             255
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
Device Status:     0x0000
  (Bus Powered)

I also did a bit more debugging. The QSerialPortInfo doesn't seem to carry the serialNumber() as you mentioned (just an empty string) but it does carry some vendorIdentifier() and productIdentifier() (VID: 0x1022, PID: 0x129C) which don't match the USB device.

However doing a manual check in the sys filesytem (without sudo):

$ cat $(readlink -f /sys/class/tty/ttyACM0/device)/../serial
flip_Atiw
$ cat $(readlink -f /sys/class/tty/ttyACM0/device)/../idProduct
5740
$ cat $(readlink -f /sys/class/tty/ttyACM0/device)/../idVendor
0483
$ cat $(readlink -f /sys/class/tty/ttyACM0/device)/../manufacturer
Flipper Devices Inc.

I'm not sure, looks like a QT bug as it don't read the correct serial information.

gsurkov commented 1 year ago

Thanks for providing the info, the lsusb output is looking perfectly healthy. I was also starting to think about Qt being the culprit here, but the only version I can think of is that its version supplied inside the AppImage is somehow incompatible with Fedora 36 kernel or other system software (no idea how, though).

but it does carry some vendorIdentifier() and productIdentifier() (VID: 0x1022, PID: 0x129C) which don't match the USB device

These might be the numbers for the /dev/ttyS0 port. qFlipper detects Flippers first using the libusb hotplug events (where it reads the device's serial number), then it uses Qt to get a list of ports and find the corresponding one using the serial number it had read earlier. During the second stage, all QSerialPortInfos are therefore checked for a match. The question is - why doesn't Qt load the serial number for the Flipper's port.

If you are able to compile qFlipper from sources (or install a pre-built version which links to the system libraries), you might try doing so and see if it works then. If it does, it certainly looks like a compatibility issue.

gsurkov commented 1 year ago

UPD: I ran a Fedora 36 KDE LiveCD (which should be close enough to your OS, based on the OS info from the log) and was not able to reproduce this issue. The port could be opened and found without problems, as well as its serial number. So it might not be a compatibility issue, after all.

VoidField101 commented 1 year ago

If you are able to compile qFlipper from sources (or install a pre-built version which links to the system libraries), you might try doing so and see if it works then. If it does, it certainly looks like a compatibility issue.

That's the way I found the issue with the serial port information being completely wrong. I ran the project in QT Creator and added a few extra debug lines in the SerialFinder to output all the SerialPortInfo for every port. Since ttyS0 is a internal serial port on the mainboard it has no vendor or product information attached (both read as 0)

By hardcoding the check that /dev/ttyACM0 is correct (checking for systemLocation rather than the serialNumber) I got it to connect but it's obviously not a good solution.

VoidField101 commented 1 year ago

I was able to pinpoint the issue to the systemd-udev-250.9-1.fc36.x86_64 package in Fedora. To be exact it provides a file /usr/lib/udev/rules.d/60-serial.rules which contains the following line (Line 6):

SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}"

So it seems to override the Vendor and Model ID when the pci subsystem is involved which it is because the USB controller is connected to PCI. Commenting this line out and reloading the udev rules fixed the issue, however this is only a temporary solution since this file is managed by the package and will be overwritten by an update. I'll try and figure something out using a separate udev rule.

gsurkov commented 1 year ago

Fantastic detective work! If I remember correctly, rule files from /etc/udev/rules.d take precedence over those situated in /usr/lib/udev/rules.d, so you may place the edited version of the file there.

VoidField101 commented 1 year ago

My current working fix includes a override for all the values in a file called 99-flipperzero.rules

TAG=="flipperzero", ENV{ID_VENDOR_ID}="$env{ID_USB_MODEL_ID}", ENV{ID_MODEL}="$env{ID_USB_MODEL}", ENV{ID_MODEL_ENC}="$env{ID_USB_MODEL_ENC}", ENV{ID_VENDOR_ID}="$env{ID_USB_VENDOR_ID}", ENV{ID_VENDOR}="$env{ID_USB_VENDOR}", ENV{ID_VENDOR_ENC}="$env{ID_USB_VENDOR_ENC}", ENV{ID_SERIAL}="$env{ID_USB_SERIAL}", ENV{ID_SERIAL_SHORT}="$env{ID_USB_SERIAL_SHORT}" 

and in the 42-flipperzero.rules I just added a TAG+="flipperzero". This seems to work and override all the PCI values with the USB values again.

justafren commented 1 year ago

I came across this same issue this evening and your current working fix worked a treat. Thank you for saving me hours of debugging @voidfield101. I appreciate you big dawg

gsurkov commented 1 year ago

@theshrewformallyknownasdrew is it an issue caused by a package update or was it always there?

justafren commented 1 year ago

@theshrewformallyknownasdrew is it an issue caused by a package update or was it always there?

First time install of qflipper. Fedora 36 and qflipper 1.2.2.

cofuente commented 10 months ago

I believe I have a similar problem but I'm running 64 bit Ubuntu 22.04.3 LTS. If creating a rules file is a solution, can we get more details on what exactly to put on the file?