Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QSocketNotifier and libgpiod on Raspberry Pi

QSocketNotifier and libgpiod on Raspberry Pi

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 2 Posters 284 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    DL5EU
    wrote last edited by
    #1

    Hi,

    I am using libgpiod and Qt 6.8.3 on my Raspberry Pi to access the GPIO pins and would like to use a QSocketNotifier to get informed whenever the signal an a given GPIO pin changes.

    In the constructor of my Sampler object I have got this code:

    m_gpioChip = gpiod_chip_open_by_name("gpiochip0");
    m_retrace = gpiod_chip_get_line(m_gpioChip, 26);
    gpiod_line_request_falling_edge_events(m_retrace, "display");
    m_fdRetrace = gpiod_line_event_get_fd(m_retrace);
    m_notifier = new QSocketNotifier(m_fdRetrace, QSocketNotifier::Read, this);
    connect(m_notifier, &QSocketNotifier::activated, this, &Sampler::onRetrace);
    

    The signature of onRetrace is

    void Sampler::onRetrace(QSocketDescriptor socket, QSocketNotifier::Type type)
    

    and corresponds to what I have found in the documentatin.

    However, on Retrace gets never called. I have also tried the QSocketNotifier::Exception type and different pins but this does not change anything.
    My question is: is this kind of use of QSocketNotifier possible at all or have I made a mistake in my code? The poll() function works, but would like to avoid using it because it blocks the worker thread.

    Thanks,

    Ralf

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote last edited by
      #2

      Hi,

      I haven't used that library yet but I am wondering: does it implement the events supported by QSocketNotifier ? From a brief look at their example I am not sure about that.
      Depending on your needs using a QThread and poll might be the easier route.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      D 1 Reply Last reply
      1
      • SGaistS SGaist

        Hi,

        I haven't used that library yet but I am wondering: does it implement the events supported by QSocketNotifier ? From a brief look at their example I am not sure about that.
        Depending on your needs using a QThread and poll might be the easier route.

        D Offline
        D Offline
        DL5EU
        wrote last edited by
        #3

        @SGaist

        Hi,

        I have tried that already. At least it works. If nobody comes up with a better idea I think I'll do that.

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote last edited by
          #4

          Would it be possible for you to provide a minimal compilable example using QSocketNotifier so other people may explore this issue ?

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          D 1 Reply Last reply
          0
          • D Offline
            D Offline
            DL5EU
            wrote last edited by DL5EU
            #5

            Before I do that I would like to check if with version 2 of libgpiod it still does not work. On my system I have currently installed version 1.6.3.

            1 Reply Last reply
            0
            • SGaistS SGaist

              Would it be possible for you to provide a minimal compilable example using QSocketNotifier so other people may explore this issue ?

              D Offline
              D Offline
              DL5EU
              wrote last edited by
              #6

              @SGaist

              Hi,

              I have set up a Raspberry Pi with the most recent OS (Trixie) that comes with libgpiod version 2.2.1. This version seems to work. I have created a test class "GpioWatcher". The signal "activated" is sent when an event at the pin occurs. I know that it is just a hack and not good code and there are certainly better ways to do it but it was just to test if QSocketNotifier works with this version of the library.

              class GpioWatcher : public QObject
              {
                  Q_OBJECT
              
              public:
                  enum class Edge {
                      Rising,
                      Falling,
                      Both
                  };
              
                  explicit GpioWatcher(const QString& chipPath, uint lineOffset, Edge edge, QObject* parent = nullptr);
                  ~GpioWatcher();
              
              private slots:
                  void handleGpioEvent();
              
              private:
                  void setupGpio(const QString& chipPath, uint lineOffset, Edge edge);
              
              private:
                  struct gpiod_chip*         m_chip;
                  struct gpiod_line_request* m_request;
                  gpiod_edge_event_buffer*   m_eventBuffer;
                  QSocketNotifier*           m_notifier;
              
              signals:
                  void activated();
              };
              
              
              GpioWatcher::GpioWatcher(const QString& chipPath, uint lineOffset, Edge edge, QObject* parent)
                  : QObject{parent}
                  , m_chip{nullptr}
                  , m_request{nullptr}
                  , m_eventBuffer{nullptr}
                  , m_notifier{nullptr}
              {
                  setupGpio(chipPath, lineOffset, edge);
              
                  m_eventBuffer = gpiod_edge_event_buffer_new(4);
                  if (!m_eventBuffer) {
                      throw std::runtime_error("Failed to create edge event buffer");
                  }
              
                  int fd = gpiod_line_request_get_fd(m_request);
                  m_notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
              
                  connect(m_notifier,
                          &QSocketNotifier::activated,
                          this,
                          &GpioWatcher::handleGpioEvent);
              }
              
              GpioWatcher::~GpioWatcher()
              {
                  if (m_notifier) {
                      m_notifier->setEnabled(false);
                  }
              
                  if (m_eventBuffer) {
                      gpiod_edge_event_buffer_free(m_eventBuffer);
                  }
              
                  if (m_request) {
                      gpiod_line_request_release(m_request);
                  }
              
                  if (m_chip) {
                      gpiod_chip_close(m_chip);
                  }
              }
              
              void GpioWatcher::setupGpio(const QString& chipPath,
                                          uint lineOffset,
                                          Edge edge)
              {
                  m_chip = gpiod_chip_open(chipPath.toUtf8().constData());
                  if (!m_chip) {
                      throw std::runtime_error("Failed to open GPIO chip");
                  }
              
                  gpiod_line_settings* lineSettings = gpiod_line_settings_new();
                  gpiod_line_config* lineConfig = gpiod_line_config_new();
                  gpiod_request_config* requestConfig = gpiod_request_config_new();
              
                  gpiod_request_config_set_consumer(requestConfig, "GpioWatcher");
              
                  gpiod_line_settings_set_direction(
                      lineSettings,
                      GPIOD_LINE_DIRECTION_INPUT
                      );
              
                  gpiod_line_edge edgeType;
                  switch (edge) {
                  case Edge::Rising:  edgeType = GPIOD_LINE_EDGE_RISING; break;
                  case Edge::Falling: edgeType = GPIOD_LINE_EDGE_FALLING; break;
                  case Edge::Both:
                  default:            edgeType = GPIOD_LINE_EDGE_BOTH; break;
                  }
              
                  gpiod_line_settings_set_edge_detection(lineSettings, edgeType);
              
                  gpiod_line_config_add_line_settings(
                      lineConfig,
                      &lineOffset,
                      1,
                      lineSettings
                      );
              
                  m_request = gpiod_chip_request_lines(
                      m_chip,
                      requestConfig,
                      lineConfig
                      );
              
                  gpiod_line_settings_free(lineSettings);
                  gpiod_line_config_free(lineConfig);
                  gpiod_request_config_free(requestConfig);
              
                  if (!m_request) {
                      throw std::runtime_error("Failed to request GPIO line");
                  }
              }
              
              void GpioWatcher::handleGpioEvent()
              {
                  const int count = gpiod_line_request_read_edge_events(
                      m_request,
                      m_eventBuffer,
                      gpiod_edge_event_buffer_get_capacity(m_eventBuffer)
                      );
              
                  if (count < 0) {
                      return;
                  }
              
                  for (int i = 0; i < count; ++i) {
                      const gpiod_edge_event* event =
                          gpiod_edge_event_buffer_get_event(m_eventBuffer, i);
                      Q_UNUSED(event);
                      emit activated();
                  }
              }
              
              1 Reply Last reply
              1
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote last edited by
                #7

                Excellent ! Thanks for the feedback !

                Since you have it working now, please mark the thread as solved using the "Topic Tools" button or the three dotted menu beside the answer you deem correct so other forum users may know a solution has been found :-)

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply
                1
                • D DL5EU has marked this topic as solved

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved