Results 1 to 18 of 18

Thread: Reading from /dev/hidrawX

  1. #1
    Join Date
    Oct 2011
    Posts
    51
    Thanks
    5
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Reading from /dev/hidrawX

    Hi!

    I want to communicate with SixAxis PS3 controller on linux OS, and I really don't know how...
    The output from hidraw-dump looks like

    Qt Code:
    1. 01 00 00 00 00 00 81 80 80 80 00 00 00 00 00 00
    2. 00 00 00 00 00 00 00 00 00 00 00 00 00 03 EF 16
    3. 00 00 00 00 33 FD 77 01 C0 FA 01 DB 01 92 01 EC
    4. 01 00
    5.  
    6. 01 00 00 00 00 00 81 80 80 80 00 00 00 00 00 00
    7. 00 00 00 00 00 00 00 00 00 00 00 00 00 03 EF 16
    8. 00 00 00 00 33 FD 77 01 C0 FA 01 DB 01 92 01 ED
    9. 01 00
    10.  
    11. 01 00 00 00 00 00 81 80 80 80 00 00 00 00 00 00
    12. 00 00 00 00 00 00 00 00 00 00 00 00 00 03 EF 16
    13. 00 00 00 00 33 FD 77 01 C0 FA 01 DB 01 92 01 ED
    14. 01 00
    15.  
    16. 01 00 00 00 00 00 81 80 80 80 00 00 00 00 00 00
    17. 00 00 00 00 00 00 00 00 00 00 00 00 00 03 EF 16
    18. 00 00 00 00 33 FD 77 01 C0 FA 01 DB 01 92 01 ED
    19. 01 00
    To copy to clipboard, switch view to plain text mode 

    Blocks are sent one every Xms, I have to capture them and send (only couple values) by TCP socket.
    The question is, should I use a QProcess to capture those blocks, or a QIODevice and stdin, QFile or some other class?

    What I want to achieve in this application is a signal every end of block (not every bit of data).

    What is the best ( good ) way to do that

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Reading from /dev/hidrawX

    I would probably use QSocketNotifier and QFile.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Oct 2011
    Posts
    51
    Thanks
    5
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Reading from /dev/hidrawX

    I try to use QSocketNotifier with no success.
    The direct output from /dev/hidraw2 looks in terminal like
    Qt Code:
    1. $ cat /dev/hidraw2
    2. �{~~��w������{~~��w������{~~��w������{~~��w������{~~��w������
    To copy to clipboard, switch view to plain text mode 

    I made a simple app that reads data from /dev/hidraw and print it.

    Qt Code:
    1. QFile *in;
    2.  
    3. MainWindow::MainWindow(QWidget *parent) :
    4. QMainWindow(parent),
    5. ui(new Ui::MainWindow)
    6. {
    7. ui->setupUi(this);
    8.  
    9. in = new QFile ("/dev/hidraw2");
    10.  
    11. if(in->open(QFile::ReadOnly)) {
    12. sn = new QSocketNotifier (in->handle(),QSocketNotifier::Read);
    13. sn->setEnabled(true);
    14. connect(sn, SIGNAL(activated(int)), this, SLOT(readyRead()));
    15. }
    16. }
    17.  
    18. void MainWindow::readyRead(){
    19. qDebug() << in->read(50); // frame if 50 bits long
    20. }
    To copy to clipboard, switch view to plain text mode 


    But the app performance is terrible! And the output is not the same either (it looks likt QT is reading only one of ... ~100 frames)

    Whats wrong with my code?

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Reading from /dev/hidrawX

    Quote Originally Posted by cszawisza View Post
    I try to use QSocketNotifier with no success.
    The direct output from /dev/hidraw2 looks in terminal like
    Qt Code:
    1. $ cat /dev/hidraw2
    2. �{~~��w������{~~��w������{~~��w������{~~��w������{~~��w������
    To copy to clipboard, switch view to plain text mode 
    Is it the output you expected?

    Qt Code:
    1. qDebug() << in->read(50); // frame if 50 bits long
    To copy to clipboard, switch view to plain text mode 
    You are reading 50 bytes, not 50 bits.

    But the app performance is terrible! And the output is not the same either (it looks likt QT is reading only one of ... ~100 frames)
    I don't know why you are expecting to always receive just one frame. An arbitrary number of frames can arrive between subsequent calls to readyRead(). The signal from the notifier means there is something to be read from the descriptor, not that there is 50 bits to be read.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  5. #5
    Join Date
    Oct 2011
    Posts
    51
    Thanks
    5
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Reading from /dev/hidrawX

    qDebug() << in->read(50); // frame if 50 BYTES long
    My terrible mistake! Of course bytes, not bits!

    Is it the output you expected?
    Yes. The raw output looks like this, and the output parsed by hidraw-dupm is like in my first post.
    hidraw-dump is very simple https://github.com/aaronp24/QtSixA/b.../hidraw-dump.c I want to do something similar. But using QT

    I don't know why you are expecting to always receive just one frame
    No I was expecting to receive only one byte, but I can't just readAll, or readLine because the input "file" is a stream that newer ends So this "50" just says to QFile "read only 50 bytes and stop" and that is what I expected.
    I chenged this to

    Qt Code:
    1. void MainWindow::readyRead(){
    2. static QByteArray buf;
    3. buf.append(in->read(1));
    4.  
    5. if (buf.size()==50){
    6. qDebug()<<buf;
    7. buf.clear();
    8. }
    9. }
    To copy to clipboard, switch view to plain text mode 

    The output is probably OK, I didn't check it because of bad performance...
    In normal console (cat hidraw) data flow is constant, something like 1 frame every couple ms, but my app stops for 2s and after that print ~50 frames.

  6. #6
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Reading from /dev/hidrawX

    Every time you see readyRead() your code reads only a single byte ignoring the (potentially) hundreds of other bytes that may be available. It then waits for another readyRead() signal, which will not occur until more new bytes become available, to read another single byte and ignore what else is piling up in the socket's buffer. It needs 50 readyRead() signals before you finally output the first block of 50 bytes. If it receives new data on a 50ms cycle then 2500ms will elapse before the first block pops out. See the problem now?

    You need to read all the available bytes every time you get readyRead(). Then, for every complete 50 byte block in the buffer you process it and remove it from the buffer. You exit the readyRead handler with an incomplete block still in the buffer (or nothing).

    Something like this:
    Qt Code:
    1. void MainWindow::readyRead(){
    2. static QByteArray buf;
    3. buf.append(in->readAll());
    4.  
    5. while (buf.size() >= 50){
    6. qDebug() << buf.left(50).toHex() ;
    7. buf = buf.mid(50);
    8. }
    9. }
    To copy to clipboard, switch view to plain text mode 

  7. #7
    Join Date
    Oct 2011
    Posts
    51
    Thanks
    5
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Reading from /dev/hidrawX

    I can't check it now, but as far as I remember /dev/hidrawX (and other devices) don't have size() (or bytesAvalible()), and readAll means read until stream end's and that’s... newer.
    If it receives new data on a 50ms cycle then 2500ms will elapse before the first block pops out
    After that time, not one, but couple of blocs pops out. And see my previous post where I read 50bytes form input, effect is the same

    One thing that I don't understand is
    If it receives new data on a 50ms cycle
    Why 50ms?

  8. #8
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Reading from /dev/hidrawX

    Why 50ms?
    You told us the "Blocks are sent one every Xms". I picked 50 to illustrate why your code takes 2 seconds to output the first packet.

  9. #9
    Join Date
    Oct 2011
    Posts
    51
    Thanks
    5
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Reading from /dev/hidrawX

    I though so, but wanted to be sure

  10. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Reading from /dev/hidrawX

    Quote Originally Posted by cszawisza View Post
    I can't check it now, but as far as I remember /dev/hidrawX (and other devices) don't have size() (or bytesAvalible()), and readAll means read until stream end's and that’s... newer.
    readAll() means "read whatever is available". For a sequential device it won't use size(). However readAll() will work just fine.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  11. #11
    Join Date
    Oct 2011
    Posts
    51
    Thanks
    5
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Reading from /dev/hidrawX

    I've done some tests and I can say that readAll() hangs the application (reading never ends), size is always 0, bytes available behave strange... some examples:


    First version of function is reading a fixed number of bytes. First in output is "bytes avalible: 0" then application takes a long break and print the rest (like it was waiting to receive 16k bytes, and then start reading)

    Qt Code:
    1. void MainWindow::readyRead(){
    2. static QByteArray buf;
    3. qDebug() <<"bytes avalible: "<< in->bytesAvailable();
    4. buf.append(in->read(50));
    5.  
    6. while (buf.size() >= 50){
    7. qDebug() << buf.left(50).toHex() ;
    8. buf = buf.mid(50);
    9. }
    10. }
    To copy to clipboard, switch view to plain text mode 
    output
    Qt Code:
    1. bytes avalible: 0
    2. // LONG BREAK
    3. "01000000000083797c790000000000000000000000000000000000000003ef160000000033fd7701de1e02f8019201ed0101"
    4. bytes avalible: 16334
    5. "000000000083797c790000000000000000000000000000000000000003ef160000000033fd7701de1e02f8019201ec010100"
    6. bytes avalible: 16284
    7. "0000000083797c790000000000000000000000000000000000000003ef160000000033fd7701de1e02f8019201ed01010000"
    To copy to clipboard, switch view to plain text mode 

    After that I tried to use bytesAvailable() to read all bytes in buffer at once. The result was surprising. bytesAvalible started to return only 0 value
    Qt Code:
    1. void MainWindow::readyRead(){
    2. static QByteArray buf;
    3. qDebug() <<"bytes avalible: "<< in->bytesAvailable();
    4. buf.append(in->read(in->bytesAvailable()));
    5.  
    6. while (buf.size() >= 50){
    7. qDebug() << buf.left(50).toHex() ;
    8. buf = buf.mid(50);
    9. }
    10. }
    To copy to clipboard, switch view to plain text mode 
    output
    Qt Code:
    1. bytes avalible: 0
    2. bytes avalible: 0
    3. bytes avalible: 0
    4. (...)
    To copy to clipboard, switch view to plain text mode 

    Changing read() to readAll() results in application hang.
    Qt Code:
    1. void MainWindow::readyRead(){
    2. static QByteArray buf;
    3. qDebug() <<"bytes avalible: "<< in->bytesAvailable();
    4. buf.append(in->readAll());
    5.  
    6. while (buf.size() >= 50){
    7. qDebug() << buf.left(50).toHex() ;
    8. buf = buf.mid(50);
    9. }
    10. }
    To copy to clipboard, switch view to plain text mode 
    output
    Qt Code:
    1. bytes avalible: 0
    To copy to clipboard, switch view to plain text mode 

    The best way to read from this device seems to by reading a fixed number of bytes and then process it, but I can't wait for 16k blocks!

  12. #12
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Reading from /dev/hidrawX

    Quote Originally Posted by cszawisza View Post
    I've done some tests and I can say that readAll() hangs the application (reading never ends), size is always 0, bytes available behave strange...
    How are you opening the file?

    Does calling isSequential() return true? If not then you didn't open the file correctly. Remember /dev/* files are not regular files.

    See QIODevice::isSequential() for more info.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  13. #13
    Join Date
    Oct 2011
    Posts
    51
    Thanks
    5
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Reading from /dev/hidrawX

    isSequential returns true

    Qt Code:
    1. in = new QFile ("/dev/hidraw2");
    2.  
    3. if(in->open(QFile::ReadOnly)) {
    4. qDebug()<< in->isSequential();
    5. sn = new QSocketNotifier (in->handle(),QSocketNotifier::Read);
    6. sn->setEnabled(true);
    7. connect(sn, SIGNAL(activated(int)), this, SLOT(readyRead()));
    8. }
    To copy to clipboard, switch view to plain text mode 

    output
    Qt Code:
    1. true
    To copy to clipboard, switch view to plain text mode 

  14. #14
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Reading from /dev/hidrawX

    If the file is correctly determined as sequential then calling readAll() when there is anything to be read should not block the call.

    I don't know how this particular device driver works. Maybe instead of appending data, it discards it and replaces it with new data. In that case I'd suggest opening the file in unbuffered mode, it might help.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  15. #15
    Join Date
    Oct 2011
    Posts
    51
    Thanks
    5
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Reading from /dev/hidrawX

    Opening file in Unbuffered mode helped in case of using read(50), readAll() still behave like earlier.
    The way it works now is satisfying for me, so this topic can be closed. Thanks for your help!
    But I'm wondering now why readAll() still don't work...

  16. #16
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Reading from /dev/hidrawX

    The problem is using read(50) is just plain wrong unless the device driver guarantees that the file always has just 50 bytes of content (in other words that it always returns just the current sample). This is really something driver-dependent. If you can dig up the documentation of the driver (or better yet inspect the source code) and find out that such a guarantee is there then you're safe. Otherwise don't be suprised when the code fails you tomorrow.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  17. The following user says thank you to wysota for this useful post:

    cszawisza (5th September 2013)

  18. #17
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Reading from /dev/hidrawX

    Humour me and try:
    Qt Code:
    1. #include <QtCore>
    2. #include <fcntl.h>
    3.  
    4. class Reader: public QObject
    5. {
    6. Q_OBJECT
    7. int fd;
    8. QSocketNotifier *notifier;
    9.  
    10. public:
    11. explicit Reader(QObject *p = 0): QObject(p) {
    12. fd = open("/dev/hiddraw0", O_RDONLY|O_NONBLOCK);
    13. if (fd >= 0) {
    14. notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
    15. connect(notifier, SIGNAL(activated(int)), this, SLOT(handleRead()));
    16. }
    17. else
    18. qFatal("Could not open");
    19.  
    20. }
    21. public slots:
    22. void handleRead() {
    23. static QByteArray buffer;
    24.  
    25. ssize_t count;
    26. char block[128];
    27. notifier->setEnabled(false);
    28. do {
    29. count = read(fd, block, 128);
    30. buffer.append(block, count);
    31. } while(count > 0);
    32. qDebug() << "Read done, buffer size" << buffer.size();
    33. notifier->setEnabled(true);
    34. }
    35. };
    36.  
    37. int main(int argc, char **argv)
    38. {
    39. QCoreApplication app(argc, argv);
    40. Reader r;
    41. return app.exec();
    42. }
    43. #include "main.moc"
    To copy to clipboard, switch view to plain text mode 

  19. The following user says thank you to ChrisW67 for this useful post:

    cszawisza (5th September 2013)

  20. #18
    Join Date
    Oct 2011
    Posts
    51
    Thanks
    5
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Reading from /dev/hidrawX

    Thank you ChrisW67 your method works perfect! Only thing that I must change is add #include <unistd.h> line and change the hidraw device name!!

    To wysota. If you want to test readAll() on this driver you can just listen to your PC mouse (hidraw0 or hidraw1 in my case) it behaves very similar, the main difference is that frame size is not always the same, so my method will not work.
    Thank you for help once again!

Similar Threads

  1. Reading xml through Qt
    By vikuseth in forum Newbie
    Replies: 3
    Last Post: 6th December 2012, 10:52
  2. QPixmap reading
    By been_1990 in forum General Programming
    Replies: 8
    Last Post: 9th July 2009, 10:42
  3. reading files
    By baray98 in forum Newbie
    Replies: 2
    Last Post: 20th September 2007, 12:31
  4. reading XML
    By joseph in forum Qt Programming
    Replies: 1
    Last Post: 22nd January 2007, 09:30
  5. Server not reading
    By probine in forum Qt Programming
    Replies: 1
    Last Post: 7th December 2006, 14:45

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.