Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. Isolate different keyboard input in Widget

Isolate different keyboard input in Widget

Scheduled Pinned Locked Moved Unsolved Mobile and Embedded
9 Posts 4 Posters 2.7k Views
  • 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.
  • N Offline
    N Offline
    nicktlloyd
    wrote on last edited by
    #1

    I am developing an app for the raspberry pi and EGLFS. I have a keyboard connected, as well as a magnetic card reader which reads as keyboard input. Both show up in /dev as hidraw items with random proceeding numbers. I need to isolate the input from both of them so that they get parsed differently because I don't want a card to be able to be read in a QLineEdit, and the input from a card should be read and parsed before anything shows up on the screen. Is there an easy way to isolate these two keyboard inputs and deal with them seperately? Thanks in advance for any help!

    A 1 Reply Last reply
    0
    • N nicktlloyd

      I am developing an app for the raspberry pi and EGLFS. I have a keyboard connected, as well as a magnetic card reader which reads as keyboard input. Both show up in /dev as hidraw items with random proceeding numbers. I need to isolate the input from both of them so that they get parsed differently because I don't want a card to be able to be read in a QLineEdit, and the input from a card should be read and parsed before anything shows up on the screen. Is there an easy way to isolate these two keyboard inputs and deal with them seperately? Thanks in advance for any help!

      A Offline
      A Offline
      ambershark
      wrote on last edited by
      #2

      @nicktlloyd You're probably going to have to go to a raw linux level for that.

      I don't think Qt has anything that allows you to differentiate between devices. I could be wrong, but I just don't recall seeing a feature like that.

      This article will help you handle the device raw though:
      http://www.thelinuxdaily.com/2010/05/grab-raw-keyboard-input-from-event-device-node-devinputevent/

      You could easily use that information and write the code that will deliver that input only to a specific widget that registered for those events.

      Maybe someone else will come along with a better idea or know of a method that Qt has to do this. :)

      My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

      1 Reply Last reply
      1
      • N Offline
        N Offline
        nicktlloyd
        wrote on last edited by
        #3

        I was worried this would be my only option... My question then becomes: how do I intercept the input and then give it to Qt as separate types of events? Thanks for your help ambershark!

        A kshegunovK 2 Replies Last reply
        0
        • N nicktlloyd

          I was worried this would be my only option... My question then becomes: how do I intercept the input and then give it to Qt as separate types of events? Thanks for your help ambershark!

          A Offline
          A Offline
          ambershark
          wrote on last edited by
          #4

          @nicktlloyd So you would use the idea from that example I linked. You would put that in it's own thread as it has a while loop. When the data comes in on that loop you would signal an event from your class, we'll call it MyDeviceHandler and anyone registered for that signal would then be able to handle it.

          So something like:

          class MyDeviceHandler : public QObject
          {
             Q_OBJECT
          public:
             void readDevice()
             {
                while (readDevice(...))
                {
                   emit keyPressed(key);
                }
             }
          
          signals:
             void keyPressed(int key);
          };
          

          The above is pseudo code, you'll need to actually make it work with the proper logic.

          Also don't forget you need to add that class and specifically the readDevice function to it's own thread or you won't get events and your main thread will lock up.

          My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

          1 Reply Last reply
          1
          • N nicktlloyd

            I was worried this would be my only option... My question then becomes: how do I intercept the input and then give it to Qt as separate types of events? Thanks for your help ambershark!

            kshegunovK Offline
            kshegunovK Offline
            kshegunov
            Moderators
            wrote on last edited by kshegunov
            #5

            You could try to intercept the native events by installing a native event filter. For example take a peek at QCoreApplication::installNativeEventFilter and the QAbstractNativeEventFilter class.

            Read and abide by the Qt Code of Conduct

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

              Hi,

              What about adding an udev rule that would maybe create a symbolic link to whatever device is created when you connect your card reader ?

              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
              • N Offline
                N Offline
                nicktlloyd
                wrote on last edited by
                #7

                Thanks to everyone for your help! I ended up going with ambershark's suggestions. I wrote several threads that constantly watch for input. I had to translate the input from input events, which wasn't particularly fun, but it worked. Again, thank you to everyone!

                1 Reply Last reply
                0
                • N Offline
                  N Offline
                  nicktlloyd
                  wrote on last edited by
                  #8

                  In case anyone is interested, I'll post some code below for the QThread I made.

                  namespace KeyboardConstants {
                      static const QString keys[] = {"","","1","2","3","4","5","6","7","8","9","0",
                                                     "-","=","","","q","w","e","r","t","y","u",
                                                    "i","o","p","[","]","","","a","s","d","f",
                                                    "g","h","j","k","l",";","'","`","","\\","z",
                                                    "x","c","v","B","n","m",",",".","/","","","",
                                                    " ","",""};
                      static const QString shiftKeys[] = {"","","!","@","#","$","%","^","&","*","(",")",
                                                         "_","+","","","Q","W","E","R","T","Y","U",
                                                         "I","O","P","{","}","","","A","S","D","F",
                                                         "G","H","J","K","L",":","\"","~","","|","Z",
                                                         "X","C","V","B","N","M","<",">","?","","",""};
                  }
                  
                  void ccWatcher::run()
                  {
                      struct input_event ev[1];
                      int fevdev = -1;
                      int size = sizeof(struct input_event);
                      int rd;
                      char name[256] = "Unknown";
                      bool shift = false;
                      QString device = "/dev/input/by-id/XXXXX";
                  
                  
                      fevdev = open(device.toStdString().c_str(), O_RDONLY);
                  
                      if (fevdev >= 0) {
                          ioctl(fevdev, EVIOCGNAME(sizeof(name)), name);
                          ioctl(fevdev, EVIOCGRAB, 1);
                          while (1)
                          {
                              if ((rd = read(fevdev, ev, size)) < size) {
                                  break;
                              }
                              // ensure it's a keypress input event
                              if (ev[0].type == 1 && ev[0].value == 1) {
                                  // 28 and 96 are enter codes
                                  if (ev[0].code != 28 && ev[0].code != 96) {
                                      // If it's a shift key, enter shift mode
                                      if (ev[0].code == 42 || ev[0].code == 54) {
                                          shift = true;
                                      } else { // otherwise use the code as an index to an array of String characters
                                          if (shift) {
                                              input.append(KeyboardConstants::shiftKeys[ev[0].code]);
                                              shift = false;
                                          } else input.append(KeyboardConstants::keys[ev[0].code]);
                                      }
                                  } else { // Emit a signal out of the thread to by sent as a QEvent to the QWindow in focus
                                      emit ccReadin(input);
                                      input = "";
                                  }
                              }
                          }
                      }
                  }
                  
                  A 1 Reply Last reply
                  1
                  • N nicktlloyd

                    In case anyone is interested, I'll post some code below for the QThread I made.

                    namespace KeyboardConstants {
                        static const QString keys[] = {"","","1","2","3","4","5","6","7","8","9","0",
                                                       "-","=","","","q","w","e","r","t","y","u",
                                                      "i","o","p","[","]","","","a","s","d","f",
                                                      "g","h","j","k","l",";","'","`","","\\","z",
                                                      "x","c","v","B","n","m",",",".","/","","","",
                                                      " ","",""};
                        static const QString shiftKeys[] = {"","","!","@","#","$","%","^","&","*","(",")",
                                                           "_","+","","","Q","W","E","R","T","Y","U",
                                                           "I","O","P","{","}","","","A","S","D","F",
                                                           "G","H","J","K","L",":","\"","~","","|","Z",
                                                           "X","C","V","B","N","M","<",">","?","","",""};
                    }
                    
                    void ccWatcher::run()
                    {
                        struct input_event ev[1];
                        int fevdev = -1;
                        int size = sizeof(struct input_event);
                        int rd;
                        char name[256] = "Unknown";
                        bool shift = false;
                        QString device = "/dev/input/by-id/XXXXX";
                    
                    
                        fevdev = open(device.toStdString().c_str(), O_RDONLY);
                    
                        if (fevdev >= 0) {
                            ioctl(fevdev, EVIOCGNAME(sizeof(name)), name);
                            ioctl(fevdev, EVIOCGRAB, 1);
                            while (1)
                            {
                                if ((rd = read(fevdev, ev, size)) < size) {
                                    break;
                                }
                                // ensure it's a keypress input event
                                if (ev[0].type == 1 && ev[0].value == 1) {
                                    // 28 and 96 are enter codes
                                    if (ev[0].code != 28 && ev[0].code != 96) {
                                        // If it's a shift key, enter shift mode
                                        if (ev[0].code == 42 || ev[0].code == 54) {
                                            shift = true;
                                        } else { // otherwise use the code as an index to an array of String characters
                                            if (shift) {
                                                input.append(KeyboardConstants::shiftKeys[ev[0].code]);
                                                shift = false;
                                            } else input.append(KeyboardConstants::keys[ev[0].code]);
                                        }
                                    } else { // Emit a signal out of the thread to by sent as a QEvent to the QWindow in focus
                                        emit ccReadin(input);
                                        input = "";
                                    }
                                }
                            }
                        }
                    }
                    
                    A Offline
                    A Offline
                    ambershark
                    wrote on last edited by ambershark
                    #9

                    @nicktlloyd Looks good. You'll probably want to add a way to signal your thread to get out of that loop and exit. Otherwise you will have issues quitting your application and end up having to kill the thread with terminate. Which seems to cause crashes more often than not.

                    Is it working out for you though? Did it fix the original issue? EDIT: Nevermind just read your above post and saw that it worked. Great news! :)

                    My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

                    1 Reply Last reply
                    1

                    • Login

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